From d43d30ee3f9b59c424f34d024c79e9283f57968f Mon Sep 17 00:00:00 2001 From: potaser Date: Fri, 9 Oct 2026 16:54:03 +0800 Subject: [PATCH 1/8] feat: add review_service with plant genomics presubmit, journals endpoint, and BFF proxy --- .gitignore | 8 + review_service/.env.example | 27 ++ review_service/__init__.py | 7 + review_service/app/__init__.py | 1 + review_service/app/config.py | 78 ++++++ review_service/app/db.py | 191 +++++++++++++ review_service/app/main.py | 71 +++++ review_service/app/routers/__init__.py | 1 + review_service/app/routers/journals.py | 292 ++++++++++++++++++++ review_service/app/routers/presubmit.py | 87 ++++++ review_service/app/services/__init__.py | 1 + review_service/app/services/journal_kb.py | 223 +++++++++++++++ review_service/app/services/journal_rank.py | 210 ++++++++++++++ review_service/app/services/llm.py | 203 ++++++++++++++ review_service/app/services/paper_parse.py | 139 ++++++++++ review_service/app/services/self_review.py | 155 +++++++++++ review_service/data/journals/journals.json | 62 +++++ review_service/pytest.ini | 6 + review_service/restart.sh | 33 +++ review_service/tests/test_presubmit.py | 163 +++++++++++ review_service/tests/test_recommend.py | 271 ++++++++++++++++++ sdk/app/config.py | 5 + sdk/app/main.py | 3 + sdk/app/routers/review_proxy.py | 85 ++++++ 24 files changed, 2322 insertions(+) create mode 100644 review_service/.env.example create mode 100644 review_service/__init__.py create mode 100644 review_service/app/__init__.py create mode 100644 review_service/app/config.py create mode 100644 review_service/app/db.py create mode 100644 review_service/app/main.py create mode 100644 review_service/app/routers/__init__.py create mode 100644 review_service/app/routers/journals.py create mode 100644 review_service/app/routers/presubmit.py create mode 100644 review_service/app/services/__init__.py create mode 100644 review_service/app/services/journal_kb.py create mode 100644 review_service/app/services/journal_rank.py create mode 100644 review_service/app/services/llm.py create mode 100644 review_service/app/services/paper_parse.py create mode 100644 review_service/app/services/self_review.py create mode 100644 review_service/data/journals/journals.json create mode 100644 review_service/pytest.ini create mode 100755 review_service/restart.sh create mode 100644 review_service/tests/test_presubmit.py create mode 100644 review_service/tests/test_recommend.py create mode 100644 sdk/app/routers/review_proxy.py diff --git a/.gitignore b/.gitignore index 3fc8ecb..b36139e 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,11 @@ paper_writer_service/paper.db paper_writer_service/paper.db-shm paper_writer_service/paper.db-wal paper_writer_service/paper.log + +# review_service 运行时产物(不入库) +review_service/review.db +review_service/review.db-wal +review_service/review.db-shm +review_service/review.log +# 期刊种子 journals.json 是源码:顶层 **/data/ 会误伤 review_service/data/,显式放行 +!review_service/data/ diff --git a/review_service/.env.example b/review_service/.env.example new file mode 100644 index 0000000..197247e --- /dev/null +++ b/review_service/.env.example @@ -0,0 +1,27 @@ +# review_service/.env.example —— 运行时配置模板 +# 用法: cp .env.example .env 后填写(.env 已被仓库 .gitignore 忽略,勿提交) +# restart.sh 会 `set -a; source .env` 导出给 uvicorn 进程。 + +# ---- LLM(DeepSeek;REVIEW_LLM_* 优先 → DOCGEN_LLM_* 回退 → 内置默认,见 services/llm.py)---- +# 最简做法:从部署树抄一行即可复用同一把 key: +# grep '^DOCGEN_LLM_API_KEY=' /home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new/sdk/.env >> .env +REVIEW_LLM_BASE_URL=https://api.deepseek.com/v1 +REVIEW_LLM_API_KEY= +REVIEW_LLM_MODEL=deepseek-chat +#REVIEW_LLM_TIMEOUT=300 + +# ---- 上游(只读消费)---- +#REVIEW_VSTORE_BASE_URL=http://127.0.0.1:8094 +#REVIEW_METHODOLOGY_BASE_URL=http://127.0.0.1:8092 # 预留(MinerU 重链路,当前未用) + +# ---- PDF 解析(经 vstore)---- +#REVIEW_PARSE_TIMEOUT=180 # ingest→取文→清理 总读超时(秒) +#REVIEW_PARSE_DELETE_AFTER=1 # 1=解析后删除 vstore 临时文档(0=保留便于排查) + +# ---- 自审稿 ---- +#REVIEW_PRESUBMIT_READ_TIMEOUT=360 # LLM 长调用读超时(秒) +#REVIEW_MAX_TEXT_CHARS=60000 # 送 LLM 的正文截断上限 +#REVIEW_MAX_PDF_BYTES=52428800 # 上传 PDF 上限 50MB + +# ---- 服务(restart.sh 读取)---- +#REVIEW_BIND_HOST=127.0.0.1 diff --git a/review_service/__init__.py b/review_service/__init__.py new file mode 100644 index 0000000..4a7865b --- /dev/null +++ b/review_service/__init__.py @@ -0,0 +1,7 @@ +"""review_service —— 科研投稿与智能审稿助手(8100)。 + +独立部署树(模式同 paper_writer_service 8097 / bioflow_service 8098): +- BFF(sdk 8090) 经 routers/review_proxy.py 条件反代 /api/review/*(REVIEW_ENABLED)。 +- 上游只读消费:vstore 8094(PDF 解析)、DeepSeek(LLM,REVIEW_LLM_*/DOCGEN_LLM_*)。 +- 约束见根目录 AGENTS.md:审稿相关新代码只允许落在本目录。 +""" diff --git a/review_service/app/__init__.py b/review_service/app/__init__.py new file mode 100644 index 0000000..e701edd --- /dev/null +++ b/review_service/app/__init__.py @@ -0,0 +1 @@ +"""review 服务(8100)应用包。""" diff --git a/review_service/app/config.py b/review_service/app/config.py new file mode 100644 index 0000000..cf9533a --- /dev/null +++ b/review_service/app/config.py @@ -0,0 +1,78 @@ +"""config.py —— review 服务(8100)环境变量驱动配置(pydantic-settings)。 + +全部键可用环境变量覆盖(前缀 REVIEW_)。LLM 沿用 docgen 的裸键模式: +优先 REVIEW_LLM_*,回退 DOCGEN_LLM_*(与 paper_writer_service 共享同一套 +DeepSeek 凭据,由 services/llm.py 直接读 os.environ)。零硬编码宿主路径。 +""" +from __future__ import annotations + +from functools import lru_cache +from pathlib import Path + +from pydantic_settings import BaseSettings, SettingsConfigDict + + +class Settings(BaseSettings): + model_config = SettingsConfigDict( + env_file=".env", + env_file_encoding="utf-8", + extra="ignore", + env_prefix="REVIEW_", + ) + + app_name: str = "plantai-review-service" + version: str = "0.1.0" + + # ---- 上游(只读消费;不修改 vstore/methodology 任何代码)---- + # vstore 8094:POST /api/vstore/ingest + GET/DELETE /api/vstore/documents/{id} + # (pymupdf 段落解析,同步秒级;methodology 8092 的 MinerU 链路是 + # 分钟级异步 job,不适配同步自审稿,仅预留地址供后续扩展) + vstore_base_url: str = "http://127.0.0.1:8094" + methodology_base_url: str = "http://127.0.0.1:8092" + + # ---- PDF 解析 ---- + parse_timeout: float = 180.0 # vstore ingest→fetch→delete 读超时(秒) + parse_delete_after: bool = True # 解析完成后删除 vstore 临时文档(不污染私有库) + + # ---- 自审稿(presubmit)---- + presubmit_read_timeout: float = 360.0 # LLM 长调用读超时(秒) + max_text_chars: int = 60000 # 送 LLM 的正文截断上限(约 3 万汉字/6 万字符) + max_pdf_bytes: int = 50 * 1024 * 1024 # 上传 PDF 上限 50MB(对齐 extraction FR-EXTRACT-004) + + # ---- 期刊情报与投稿推荐(recommend)---- + db_path: str = "review.db" # 独立 SQLite(相对 review_service/;REVIEW_DB_PATH 覆盖) + journals_seed_path: str = "data/journals/journals.json" # 种子(相对 review_service/) + vstore_match_timeout: float = 30.0 # scope 入库/向量检索读超时(秒) + recommend_read_timeout: float = 60.0 # LLM 重排读超时(秒) + recommend_query_chars: int = 3000 # 送 vstore 的检索 query 截断(防嵌入模型超长) + recommend_scope_top_k: int = 10 # search-chunks top_k(vstore 上限 20) + + @property + def _service_root(self) -> "Path": + # review_service/app/config.py → review_service/(相对本文件定位,不依赖 cwd) + return Path(__file__).resolve().parent.parent + + @property + def db_path_abs(self) -> "Path": + # 绝对 db_path 会被 Path 除法原样返回;相对路径落在 review_service/ 下 + return self._service_root / self.db_path + + @property + def journals_seed_abs(self) -> "Path": + return self._service_root / self.journals_seed_path + + @property + def vstore_base(self) -> str: + return self.vstore_base_url.rstrip("/") + + @property + def methodology_base(self) -> str: + return self.methodology_base_url.rstrip("/") + + +@lru_cache(maxsize=1) +def get_settings() -> Settings: + return Settings() + + +settings = get_settings() diff --git a/review_service/app/db.py b/review_service/app/db.py new file mode 100644 index 0000000..1c312a8 --- /dev/null +++ b/review_service/app/db.py @@ -0,0 +1,191 @@ +"""app/db.py —— review 服务独立 SQLite(aiosqlite + WAL,无 ORM):journals 表。 + +- 单连接 + asyncio 写锁(模式对齐 paper_writer_service/bioflow,但表结构与种子 + 逻辑为本模块自研);路径默认 review_service/review.db(REVIEW_DB_PATH 覆盖)。 +- 种子:data/journals/journals.json → journals 表(幂等 upsert,vstore_doc_id 列 + 永不被种子覆盖——该列记录 scope_desc 在 vstore 8094 的 document_id)。 +- 只在 review_service/ 内使用,不触碰 BFF/生产服务数据库。 +""" +from __future__ import annotations + +import asyncio +import json +from pathlib import Path +from typing import Any, Iterable + +import aiosqlite + +from .config import get_settings + +_SCHEMA = """ +CREATE TABLE IF NOT EXISTS journals ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + scope_desc TEXT NOT NULL, + impact_factor REAL, + review_time_weeks REAL, + acceptance_rate REAL, + submission_deadline TEXT, + official_url TEXT, + last_updated TEXT NOT NULL, + vstore_doc_id TEXT +); +""" + +# 种子 upsert 列(刻意不含 vstore_doc_id:种子刷新不得清掉向量库映射) +_SEED_COLS = ( + "id", + "name", + "scope_desc", + "impact_factor", + "review_time_weeks", + "acceptance_rate", + "submission_deadline", + "official_url", + "last_updated", +) +_UPSERT_SQL = ( + "INSERT INTO journals (" + ", ".join(_SEED_COLS) + ") VALUES (" + + ", ".join("?" for _ in _SEED_COLS) + ") " + + "ON CONFLICT(id) DO UPDATE SET " + + ", ".join(f"{c}=excluded.{c}" for c in _SEED_COLS if c != "id") +) + + +class SeedError(Exception): + """种子文件缺失/损坏(journals.json 不可读)。""" + + +class Database: + """aiosqlite 单连接封装(WAL;写串行化)。""" + + def __init__(self, path: str | Path | None = None) -> None: + self._path: Path | None = Path(path) if path is not None else None + self._conn: aiosqlite.Connection | None = None + self._lock = asyncio.Lock() + + @property + def path(self) -> Path: + if self._path is None: + self._path = get_settings().db_path_abs + return self._path + + def set_path(self, path: str | Path) -> None: + """测试注入:在进入 TestClient lifespan 之前预置库路径(须尚未 connect)。""" + if self._conn is not None: + raise RuntimeError("Database 已连接,无法再改路径(先 close_db())") + self._path = Path(path) + + @property + def connected(self) -> bool: + return self._conn is not None + + async def connect(self) -> None: + self.path.parent.mkdir(parents=True, exist_ok=True) + self._conn = await aiosqlite.connect(self.path) + self._conn.row_factory = aiosqlite.Row + await self._conn.execute("PRAGMA journal_mode=WAL") + await self._conn.execute("PRAGMA busy_timeout=5000") + await self._conn.executescript(_SCHEMA) + await self._conn.commit() + + async def close(self) -> None: + if self._conn is not None: + await self._conn.close() + self._conn = None + + @property + def conn(self) -> aiosqlite.Connection: + if self._conn is None: + raise RuntimeError("Database 未初始化:先 await init_db()") + return self._conn + + async def fetchall(self, sql: str, params: Iterable[Any] = ()) -> list[dict[str, Any]]: + async with self.conn.execute(sql, tuple(params)) as cur: + rows = await cur.fetchall() + return [dict(r) for r in rows] + + async def fetchone(self, sql: str, params: Iterable[Any] = ()) -> dict[str, Any] | None: + async with self.conn.execute(sql, tuple(params)) as cur: + row = await cur.fetchone() + return dict(row) if row is not None else None + + async def execute(self, sql: str, params: Iterable[Any] = ()) -> int: + async with self._lock: + cur = await self.conn.execute(sql, tuple(params)) + await self._conn.commit() # type: ignore[union-attr] + return cur.lastrowid or 0 + + async def executemany(self, sql: str, seq: list[tuple[Any, ...]]) -> None: + async with self._lock: + await self.conn.executemany(sql, seq) + await self._conn.commit() # type: ignore[union-attr] + + +db = Database() + + +async def init_db(path: str | Path | None = None) -> None: + """幂等初始化:已连接则跳过(测试可在 lifespan 前 set_path 注入路径)。""" + if path is not None: + db.set_path(path) + if db.connected: + return + await db.connect() + + +async def close_db() -> None: + await db.close() + + +def set_path(path: str | Path) -> None: + """同步注入库路径(测试 fixture 用;须在 init_db 之前调用)。""" + db.set_path(path) + + +async def ensure_journals_seeded() -> int: + """装载种子期刊(幂等)。返回 journals 表行数。""" + row = await db.fetchone("SELECT COUNT(*) AS c FROM journals") + if row and int(row["c"]) > 0: + return int(row["c"]) + + seed_file = get_settings().journals_seed_abs + try: + payload = json.loads(Path(seed_file).read_text(encoding="utf-8")) + except FileNotFoundError as exc: + raise SeedError(f"期刊种子文件不存在:{seed_file}") from exc + except (OSError, ValueError) as exc: + raise SeedError(f"期刊种子文件不可读:{exc}") from exc + + journals = payload.get("journals") if isinstance(payload, dict) else None + if not isinstance(journals, list) or not journals: + raise SeedError(f"期刊种子文件缺少 journals 数组:{seed_file}") + + rows: list[tuple[Any, ...]] = [] + for item in journals: + if not isinstance(item, dict) or not item.get("id") or not item.get("name"): + continue + rows.append(tuple(item.get(c) for c in _SEED_COLS)) + if not rows: + raise SeedError(f"期刊种子文件无有效条目:{seed_file}") + + await db.executemany(_UPSERT_SQL, rows) + return len(rows) + + +async def list_journals() -> list[dict[str, Any]]: + """全部期刊(impact_factor 降序,NULL 靠后)。""" + return await db.fetchall( + "SELECT * FROM journals ORDER BY impact_factor DESC, name ASC" + ) + + +async def get_journal(journal_id: str) -> dict[str, Any] | None: + return await db.fetchone("SELECT * FROM journals WHERE id = ?", (journal_id,)) + + +async def set_vstore_doc_id(journal_id: str, doc_id: str) -> None: + """记录 scope_desc 在 vstore 的 document_id(向量白名单检索用)。""" + await db.execute( + "UPDATE journals SET vstore_doc_id = ? WHERE id = ?", (doc_id, journal_id) + ) diff --git a/review_service/app/main.py b/review_service/app/main.py new file mode 100644 index 0000000..1611e90 --- /dev/null +++ b/review_service/app/main.py @@ -0,0 +1,71 @@ +"""main.py —— review 服务应用入口(uvicorn 入口)。 + +- 独立部署树 review_service/(科研投稿与智能审稿助手,端口 8100)。 +- 端点:/health(GET,BFF 探活反代)+ /api/review/*(自审稿等业务路由)。 +- 不依赖 BFF/生产服务(8090 等绝不探测/连接);上游仅消费 vstore 8094。 +""" +from __future__ import annotations + +import logging +from contextlib import asynccontextmanager + +import httpx +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware + +from .config import get_settings +from .db import close_db, init_db +from .routers import journals, presubmit + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +def create_app() -> FastAPI: + settings = get_settings() + app = FastAPI(title=settings.app_name, version=settings.version) + + app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=False, + allow_methods=["*"], + allow_headers=["*"], + ) + + @asynccontextmanager + async def _lifespan(_app: FastAPI): + # journals 推荐依赖独立 SQLite:启动即建表(幂等;测试可先 set_path 注入 + # tmp 路径,本函数沿用注入路径) + await init_db() + try: + yield + finally: + await close_db() + + app.router.lifespan_context = _lifespan + + @app.get("/health") + async def health() -> dict[str, object]: + vstore_ok = False + vstore_error: str | None = None + try: + async with httpx.AsyncClient(timeout=2.0) as client: + resp = await client.get(f"{settings.vstore_base}/api/vstore/health") + resp.raise_for_status() + vstore_ok = bool(resp.json().get("ok")) + except Exception as exc: # noqa: BLE001 + vstore_error = str(exc) + return { + "ok": True, + "status": "ok" if vstore_ok else "degraded", + "upstreams": {"vstore": {"connected": vstore_ok, "error": vstore_error}}, + "version": settings.version, + } + + app.include_router(presubmit.router) + app.include_router(journals.router) + return app + + +app = create_app() diff --git a/review_service/app/routers/__init__.py b/review_service/app/routers/__init__.py new file mode 100644 index 0000000..f026b28 --- /dev/null +++ b/review_service/app/routers/__init__.py @@ -0,0 +1 @@ +"""review 服务路由包。""" diff --git a/review_service/app/routers/journals.py b/review_service/app/routers/journals.py new file mode 100644 index 0000000..ad294fe --- /dev/null +++ b/review_service/app/routers/journals.py @@ -0,0 +1,292 @@ +"""routers/journals.py —— 期刊情报与智能投稿推荐。 + +- GET /api/review/journals 只读:journals 表全量列表(?field=/&order= 排序), + meta 含 count / last_updated / data_source_note。无任何写接口;空表返回 + 空数组 + meta.count=0(HTTP 200,绝不 500)。 +- POST /api/review/recommend 智能投稿推荐:vstore 向量匹配(摘要 vs + scope_desc,白名单检索)→ LLM 按 id 白名单重排(幻觉期刊丢弃、缺漏规则 + 补位)→ 三档输出:挑战型 / 适配型 / 稳妥型,附匹配理由与风险提示。 + +降级哲学(同 presubmit):向量失败 → 全量候选 + vector_ok=false; +LLM 失败 → 规则分档 + llm_ok=false;推荐永不 5xx。仅入参非法返回 +VALIDATION 错误信封(HTTP 200,与本服务其余端点一致)。 +""" +from __future__ import annotations + +import logging +from typing import Any, Literal + +from fastapi import APIRouter +from pydantic import BaseModel, Field + +from ..config import get_settings +from ..db import SeedError, ensure_journals_seeded, list_journals +from ..services import journal_kb, journal_rank, llm + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/api/review", tags=["review-journals"]) + + +# ---- 请求/响应模型 ---- + +class Preferences(BaseModel): + max_review_weeks: float | None = Field(default=None, ge=1, le=104) + min_impact_factor: float | None = Field(default=None, ge=0, le=200) + tier_focus: Literal["all", "challenge", "fit", "safe"] = "all" + + +class RecommendRequest(BaseModel): + abstract: str + preferences: Preferences = Preferences() + + +class JournalItem(BaseModel): + id: str + name: str + impact_factor: float | None = None + review_time_weeks: float | None = None + acceptance_rate: float | None = None + official_url: str | None = None + similarity: float | None = None + tier: str + match_reason: str + risk_note: str + + +class TierBox(BaseModel): + label: str + items: list[JournalItem] + + +class RecommendResponse(BaseModel): + ok: bool + tiers: dict[str, TierBox] | None = None + meta: dict[str, Any] | None = None + error: dict[str, Any] | None = None + + +# ---- GET /api/review/journals(只读列表)---- + +class JournalBrief(BaseModel): + """期刊公开字段(journals 表全列;不含 vstore_doc_id 内部映射)。""" + id: str + name: str + scope_desc: str = "" + impact_factor: float | None = None + review_time_weeks: float | None = None + acceptance_rate: float | None = None + submission_deadline: str | None = None + official_url: str | None = None + last_updated: str = "" + + +class JournalsListResponse(BaseModel): + ok: bool + items: list[JournalBrief] = [] + meta: dict[str, Any] | None = None + error: dict[str, Any] | None = None + + +# ?field= 排序白名单(列名无法参数化,白名单防注入;非法值 → VALIDATION 信封) +_SORT_FIELDS = frozenset({ + "id", + "name", + "impact_factor", + "review_time_weeks", + "acceptance_rate", + "last_updated", +}) +_DATA_SOURCE_NOTE = ( + "IF/审稿周期为公开近似值,acceptance_rate 为 null 表示暂无公开数据,需人工核验。" +) + + +def _sort_rows(rows: list[dict[str, Any]], field: str, order: str) -> list[dict[str, Any]]: + """按白名单字段排序;NULL 恒排最后;次序不稳定时按 db 默认序(稳定排序保留)。""" + present = [r for r in rows if r.get(field) is not None] + missing = [r for r in rows if r.get(field) is None] + present.sort(key=lambda r: r.get(field), reverse=(order == "desc")) + return present + missing + + +def _list_error(message: str) -> JournalsListResponse: + return JournalsListResponse( + ok=False, items=[], meta=None, + error={"code": "VALIDATION", "message": message, "degraded": False}, + ) + + +@router.get("/journals", response_model=JournalsListResponse) +async def journals_list( + field: str = "name", + order: str = "asc", +) -> JournalsListResponse: + """只读:journals 表全量列表(无写/删/改接口)。 + + - ?field= 排序字段白名单:id/name/impact_factor/review_time_weeks/ + acceptance_rate/last_updated,默认 name; + - ?order=asc|desc,默认 asc; + - 空表 → items=[] + meta.count=0(HTTP 200,不报错)。种子装载由 + POST /recommend 首次调用幂等完成,本端点严格只读。 + """ + col = (field or "").strip() + if col not in _SORT_FIELDS: + return _list_error( + f"不支持的排序字段 field={field!r},可选:{', '.join(sorted(_SORT_FIELDS))}" + ) + ord_norm = (order or "asc").strip().lower() + if ord_norm not in ("asc", "desc"): + return _list_error(f"不支持的排序方向 order={order!r},可选:asc, desc") + + rows = await list_journals() + rows = _sort_rows(rows, col, ord_norm) + + items = [ + JournalBrief( + id=str(r.get("id") or ""), + name=str(r.get("name") or ""), + scope_desc=str(r.get("scope_desc") or ""), + impact_factor=r.get("impact_factor"), + review_time_weeks=r.get("review_time_weeks"), + acceptance_rate=r.get("acceptance_rate"), + submission_deadline=r.get("submission_deadline"), + official_url=r.get("official_url"), + last_updated=str(r.get("last_updated") or ""), + ) + for r in rows + ] + latest = max((str(r.get("last_updated") or "") for r in rows), default="") + meta: dict[str, Any] = { + "count": len(items), + "last_updated": latest or None, + "data_source_note": _DATA_SOURCE_NOTE, + } + return JournalsListResponse(ok=True, items=items, meta=meta, error=None) + + +def _error(code: str, message: str, *, degraded: bool = False) -> RecommendResponse: + return RecommendResponse( + ok=False, tiers=None, meta=None, + error={"code": code, "message": message, "degraded": degraded}, + ) + + +def _item_sort_key(it: JournalItem) -> tuple[int, float, float]: + return ( + 1 if it.similarity is None else 0, + -(it.similarity or 0.0), + -(it.impact_factor or 0.0), + ) + + +def _apply_soft_preferences(item: JournalItem, prefs: Preferences) -> None: + """软偏好:不满足只加风险提示,不删条目。""" + weeks = item.review_time_weeks + if prefs.max_review_weeks is not None and weeks is not None and weeks > prefs.max_review_weeks: + prefix = f"⚠ 审稿约 {weeks:g} 周,超出你 {prefs.max_review_weeks:g} 周的周期偏好;" + item.risk_note = prefix + ("无" if item.risk_note == "无" else item.risk_note) + inf = item.impact_factor + if prefs.min_impact_factor is not None: + if inf is None: + item.risk_note = "⚠ 影响因子未收录,无法确认满足你的要求;" + item.risk_note + elif inf < prefs.min_impact_factor: + prefix = f"⚠ 影响因子 {inf:g} 低于你 {prefs.min_impact_factor:g} 的要求;" + item.risk_note = prefix + ("无" if item.risk_note == "无" else item.risk_note) + + +@router.post("/recommend", response_model=RecommendResponse) +async def recommend(req: RecommendRequest) -> RecommendResponse: + settings = get_settings() + + # ---- 入参校验(手动,错误信封与本服务其余端点一致)---- + abstract = (req.abstract or "").strip() + if len(abstract) < 50: + return _error("VALIDATION", "abstract 至少需要 50 个字符(请提供摘要或正文片段)") + if len(abstract) > 20000: + return _error("VALIDATION", "abstract 超过 20000 字符上限") + + prefs = req.preferences + + # ---- 种子 + 期刊元数据 ---- + try: + await ensure_journals_seeded() + journals = await list_journals() + except SeedError as exc: + logger.error("recommend: 种子装载失败:%s", exc) + return _error("SEED_UNAVAILABLE", str(exc), degraded=True) + if not journals: + return _error("SEED_UNAVAILABLE", "期刊库为空", degraded=True) + + # ---- ① vstore 向量匹配(摘要 vs scope_desc)---- + try: + candidates, vector_ok = await journal_kb.match(abstract, journals) + except journal_kb.MatchError as exc: + logger.warning("recommend: 向量匹配降级:%s", exc) + candidates, vector_ok = [], False + if not candidates: + # 无有效语义分 → 全量候选(similarity=None),LLM 仍可按 scope 文本重排 + candidates = [{"journal": j, "similarity": None} for j in journals] + vector_ok = False + + # ---- ② LLM 重排(id 白名单硬校验)---- + prefs_dict = prefs.model_dump(exclude_none=True) + llm_ok = True + dropped = 0 + repaired = 0 + try: + rankings, dropped, repaired = await journal_rank.rerank(abstract, candidates, prefs_dict) + except (llm.LLMError, journal_rank.RankError, ValueError) as exc: + # ValueError:complete_json 最终 json.loads 修复仍失败(同 presubmit 宽容口径) + logger.warning("recommend: LLM 重排降级为规则分档:%s", exc) + rankings = journal_rank.fallback_rankings(candidates) + llm_ok = False + + # ---- ③ 三档组装(名称/指标全部来自 DB,不采信 LLM 文本)---- + by_id = {str(c["journal"]["id"]): c for c in candidates} + tiers: dict[str, list[JournalItem]] = {t: [] for t in journal_rank.TIERS} + for r in rankings: + cand = by_id.get(r.journal_id) + if cand is None: + continue + j = cand["journal"] + sim = cand.get("similarity") + item = JournalItem( + id=str(j["id"]), + name=str(j.get("name") or j["id"]), + impact_factor=j.get("impact_factor"), + review_time_weeks=j.get("review_time_weeks"), + acceptance_rate=j.get("acceptance_rate"), + official_url=j.get("official_url"), + similarity=round(float(sim), 4) if sim is not None else None, + tier=r.tier, + match_reason=r.match_reason, + risk_note=r.risk_note, + ) + _apply_soft_preferences(item, prefs) + tiers.setdefault(r.tier, []).append(item) + + # 档内排序:相似度(None 靠后)→ 影响因子 + for box in tiers.values(): + box.sort(key=_item_sort_key) + + # tier_focus:软展示聚焦(默认 all;聚焦时其余档 items 置空,label 保留) + out_tiers: dict[str, TierBox] = {} + for t in journal_rank.TIERS: + items = tiers.get(t, []) + if prefs.tier_focus != "all" and t != prefs.tier_focus: + items = [] + out_tiers[t] = TierBox(label=journal_rank.TIER_LABELS[t], items=items) + + meta: dict[str, Any] = { + "model": llm._llm_config()["model"], + "vector_ok": vector_ok, + "llm_ok": llm_ok, + "seed_count": len(journals), + "candidate_count": len(candidates), + "dropped_hallucinated": dropped, + "repaired": repaired, + "preferences": prefs_dict, + "abstract_chars": len(abstract), + } + return RecommendResponse(ok=True, tiers=out_tiers, meta=meta, error=None) diff --git a/review_service/app/routers/presubmit.py b/review_service/app/routers/presubmit.py new file mode 100644 index 0000000..f15b69e --- /dev/null +++ b/review_service/app/routers/presubmit.py @@ -0,0 +1,87 @@ +"""routers/presubmit.py —— 投稿前自审稿(POST /api/review/presubmit)。 + +流程:上传 PDF → paper_parse(vstore 8094 解析)→ LLM 结构化审稿 +(DeepSeek json_object,System Prompt 为植物基因组学六维专属清单, +见 services/self_review.py)→ 归一化为 SelfReviewReport。 +""" +from __future__ import annotations + +import logging + +from fastapi import APIRouter, File, Form, UploadFile +from pydantic import BaseModel + +from ..config import get_settings +from ..services import llm, paper_parse, self_review + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/api/review", tags=["review-presubmit"]) + + +class PresubmitResponse(BaseModel): + ok: bool + report: self_review.SelfReviewReport | None = None + error: dict[str, object] | None = None + meta: dict[str, object] | None = None + + +def _error(code: str, message: str, *, degraded: bool = False) -> PresubmitResponse: + return PresubmitResponse( + ok=False, report=None, + error={"code": code, "message": message, "degraded": degraded}, + ) + + +@router.post("/presubmit", response_model=PresubmitResponse) +async def presubmit_review( + file: UploadFile = File(..., description="待审稿 PDF"), + target_journal: str = Form("", description="目标期刊(可选,影响格式类意见)"), +) -> PresubmitResponse: + settings = get_settings() + + filename = file.filename or "paper.pdf" + if not filename.lower().endswith(".pdf"): + return _error("VALIDATION", "仅支持 PDF 文件") + + content = await file.read() + if not content: + return _error("VALIDATION", "上传文件为空") + if len(content) > settings.max_pdf_bytes: + return _error("VALIDATION", "PDF 超过 50MB 上限") + + # ---- 解析(vstore 8094)---- + try: + text = await paper_parse.parse_pdf_bytes(content, filename=filename) + except paper_parse.ParseError as exc: + logger.warning("presubmit: 解析失败:%s", exc) + return _error("PARSE_FAILED", str(exc), degraded=True) + + truncated = len(text) > settings.max_text_chars + feed_text = text[: settings.max_text_chars] + + # ---- LLM 结构化自审(植物基因组学六维清单)---- + try: + payload = await llm.complete_json( + self_review.SYSTEM_PROMPT, + self_review.build_user_prompt(feed_text, (target_journal or "").strip()), + temperature=0.2, + max_tokens=8000, + timeout=settings.presubmit_read_timeout, + ) + except llm.LLMError as exc: + logger.error("presubmit: LLM 审稿失败:%s", exc) + return _error("UPSTREAM_DOWN", f"审稿模型调用失败:{exc}", degraded=True) + + report = self_review.coerce_report(payload) + return PresubmitResponse( + ok=True, + report=report, + meta={ + "filename": filename, + "target_journal": (target_journal or "").strip(), + "text_chars": len(feed_text), + "truncated": truncated, + "model": llm._llm_config()["model"], + }, + ) diff --git a/review_service/app/services/__init__.py b/review_service/app/services/__init__.py new file mode 100644 index 0000000..da95dd6 --- /dev/null +++ b/review_service/app/services/__init__.py @@ -0,0 +1 @@ +"""review 服务服务层包。""" diff --git a/review_service/app/services/journal_kb.py b/review_service/app/services/journal_kb.py new file mode 100644 index 0000000..b64c210 --- /dev/null +++ b/review_service/app/services/journal_kb.py @@ -0,0 +1,223 @@ +"""services/journal_kb.py —— 期刊 scope_desc → vstore 入库 + 向量匹配(只读消费 8094)。 + +链路(全部复用 vstore 既有 API,零改动): +1. ensure_scope_docs:各期刊 scope_desc 以 .txt 入库(category=journal_scope, + name=期刊名),document_id 回写 journals.vstore_doc_id(幂等:已有 id 不重灌)。 +2. match:GET /api/vstore/search-chunks?q=<摘要截断>&doc_ids=&top_k=N + → 按 doc_id 映射回期刊,取该期刊最高 chunk 分数为 similarity。 +3. 自愈:白名单命中 0 条 → GET /documents/{id} 探活 → 失效的重灌(vstore 去重 + 语义下同内容重灌会换 doc_id,需回写)→ 重试一次 → 仍 0 视为语义低相似。 + +错误语义:连通性/上游异常抛 MatchError(路由降级为全量候选); +返回 ([], False) 表示检索成功但无有效匹配(路由同样降级)。 +""" +from __future__ import annotations + +import logging +from typing import Any + +import httpx + +from ..config import get_settings +from ..db import set_vstore_doc_id + +logger = logging.getLogger(__name__) + +SCOPE_CATEGORY = "journal_scope" + + +class MatchError(Exception): + """vstore 向量匹配失败(不可达/响应异常)。""" + + +def _timeout() -> httpx.Timeout: + t = get_settings().vstore_match_timeout + return httpx.Timeout(connect=5.0, read=t, write=t, pool=5.0) + + +def _err_body(resp: httpx.Response) -> str: + try: + payload = resp.json() + except ValueError: + return (resp.text or "").strip()[:500] or "(空响应体)" + if isinstance(payload, dict): + err = payload.get("error") + if isinstance(err, dict) and err.get("message"): + return str(err["message"]) + if isinstance(err, str): + return err + return str(payload)[:500] + + +async def _ingest_scope(client: httpx.AsyncClient, base: str, journal: dict[str, Any]) -> str: + """单本期刊 scope_desc 入库,返回 document_id。""" + content = str(journal.get("scope_desc") or "").strip() + if not content: + raise MatchError(f"期刊 scope_desc 为空:{journal.get('id')}") + jid = str(journal.get("id") or "") + try: + resp = await client.post( + f"{base}/api/vstore/ingest", + files={"file": (f"{jid}.txt", content.encode("utf-8"), "text/plain")}, + data={ + "name": str(journal.get("name") or jid), + "category": SCOPE_CATEGORY, + "description": "review_service 期刊范围种子(scope_desc 向量匹配)", + }, + ) + except httpx.HTTPError as exc: + raise MatchError(f"vstore 不可达({base}):{exc}") from exc + if resp.status_code >= 400: + raise MatchError(f"vstore ingest 失败(HTTP {resp.status_code}):{_err_body(resp)}") + try: + payload = resp.json() + except ValueError as exc: + raise MatchError(f"vstore ingest 响应非 JSON:{exc}") from exc + if not isinstance(payload, dict) or not payload.get("ok"): + raise MatchError( + str((payload.get("error") or {}).get("message") if isinstance(payload, dict) else "") or "vstore ingest 失败" + ) + doc_id = str((payload.get("item") or {}).get("document_id") or "") + if not doc_id: + raise MatchError("vstore ingest 响应缺少 document_id") + return doc_id + + +async def ensure_scope_docs(journals: list[dict[str, Any]]) -> list[dict[str, Any]]: + """补齐缺失的 scope 入库映射(就地回写 vstore_doc_id 并持久到 DB)。""" + settings = get_settings() + missing = [j for j in journals if not j.get("vstore_doc_id")] + if not missing: + return journals + async with httpx.AsyncClient(timeout=_timeout()) as client: + for j in missing: + try: + doc_id = await _ingest_scope(client, settings.vstore_base, j) + except MatchError as exc: + # 单本失败不阻断其余(该期刊将不进白名单,由路由降级兜底) + logger.warning("journal_kb: scope 入库失败(%s):%s", j.get("id"), exc) + continue + j["vstore_doc_id"] = doc_id + await set_vstore_doc_id(str(j["id"]), doc_id) + return journals + + +async def _search( + client: httpx.AsyncClient, base: str, query: str, doc_ids: list[str] +) -> list[dict[str, Any]]: + """chunk 级白名单检索。连通/上游错误抛 MatchError。""" + if not doc_ids: + # doc_ids 为空时 vstore 侧等于不过滤 → 会命中用户私有库,必须拦死 + raise MatchError("白名单为空,拒绝全库检索") + try: + resp = await client.get( + f"{base}/api/vstore/search-chunks", + params={ + "q": query, + "top_k": get_settings().recommend_scope_top_k, + "doc_ids": ",".join(doc_ids), + }, + ) + except httpx.HTTPError as exc: + raise MatchError(f"vstore search-chunks 不可达:{exc}") from exc + if resp.status_code >= 400: + raise MatchError(f"vstore search-chunks 失败(HTTP {resp.status_code}):{_err_body(resp)}") + try: + payload = resp.json() + except ValueError as exc: + raise MatchError(f"vstore search-chunks 响应非 JSON:{exc}") from exc + if not isinstance(payload, dict) or not payload.get("ok"): + raise MatchError( + str((payload.get("error") or {}).get("message") if isinstance(payload, dict) else "") or "vstore search-chunks 失败" + ) + items = payload.get("items") + return items if isinstance(items, list) else [] + + +async def _doc_alive(client: httpx.AsyncClient, base: str, doc_id: str) -> bool: + try: + resp = await client.get(f"{base}/api/vstore/documents/{doc_id}") + except httpx.HTTPError: + return False + if resp.status_code != 200: + return False + try: + payload = resp.json() + except ValueError: + return False + return bool(isinstance(payload, dict) and payload.get("ok")) + + +async def _refresh_dead_docs( + client: httpx.AsyncClient, base: str, journals: list[dict[str, Any]] +) -> None: + """白名单 0 命中时探活:失效文档重灌并回写新 id。""" + for j in journals: + doc_id = str(j.get("vstore_doc_id") or "") + if not doc_id or await _doc_alive(client, base, doc_id): + continue + try: + new_id = await _ingest_scope(client, base, j) + except MatchError as exc: + logger.warning("journal_kb: scope 重灌失败(%s):%s", j.get("id"), exc) + continue + j["vstore_doc_id"] = new_id + await set_vstore_doc_id(str(j["id"]), new_id) + + +async def match( + abstract: str, journals: list[dict[str, Any]] +) -> tuple[list[dict[str, Any]], bool]: + """摘要 vs scope_desc 向量匹配。 + + 返回 (candidates, vector_ok);candidates 元素: + {"journal": , "similarity": float} + 按 similarity 降序。MatchError → 路由降级;([], False) → 语义低相似。 + """ + settings = get_settings() + query = abstract.strip()[: settings.recommend_query_chars] + if not query: + return [], False + + await ensure_scope_docs(journals) + whitelisted = [j for j in journals if j.get("vstore_doc_id")] + if not whitelisted: + raise MatchError("无任何期刊 scope 入库成功(vstore_doc_id 为空)") + + doc_map = {str(j["vstore_doc_id"]): j for j in whitelisted} + timeout = _timeout() + async with httpx.AsyncClient(timeout=timeout) as client: + items = await _search(client, settings.vstore_base, query, list(doc_map)) + if not items: + await _refresh_dead_docs(client, settings.vstore_base, whitelisted) + doc_map = {str(j["vstore_doc_id"]): j for j in whitelisted if j.get("vstore_doc_id")} + if not doc_map: + return [], False + items = await _search(client, settings.vstore_base, query, list(doc_map)) + + # 聚合:每本期刊取最高 chunk 分 + best: dict[str, float] = {} + for item in items: + if not isinstance(item, dict): + continue + j = doc_map.get(str(item.get("doc_id") or "")) + if j is None: + continue + try: + score = float(item.get("score")) + except (TypeError, ValueError): + continue + jid = str(j["id"]) + if jid not in best or score > best[jid]: + best[jid] = score + if not best: + return [], False + + by_id = {str(j["id"]): j for j in journals} + candidates = [ + {"journal": by_id[jid], "similarity": score} + for jid, score in best.items() + if jid in by_id + ] + candidates.sort(key=lambda c: c["similarity"], reverse=True) + return candidates, bool(candidates) diff --git a/review_service/app/services/journal_rank.py b/review_service/app/services/journal_rank.py new file mode 100644 index 0000000..d478369 --- /dev/null +++ b/review_service/app/services/journal_rank.py @@ -0,0 +1,210 @@ +"""services/journal_rank.py —— LLM 重排 + 幻觉防护 + 三档归类。 + +职责: +1. rerank:把带语义分的候选期刊(来自 journal_kb)+ 用户偏好交给 LLM, + 要求按 id 白名单返回 {rankings:[{id, tier, match_reason, risk_note}]}。 +2. validate:硬校验——白名单外 id 丢弃(幻觉拦截);tier 非法/LLM 缺漏的 + 期刊按规则补位(绝不因 LLM 输出丢失候选期刊);期刊名称/指标一律不采信 + LLM,最终展示全部用 DB 字段(防止改名型幻觉)。 +3. fallback_rankings:LLM 不可用时的确定性规则分档(按 impact_factor)。 + +三档语义:challenge 挑战型(高影响/慢审稿)、fit 适配型(均衡)、 +safe 稳妥型(快速/门槛低)。 +""" +from __future__ import annotations + +import json +from dataclasses import dataclass +from typing import Any + +from ..config import get_settings +from . import llm + +TIERS = ("challenge", "fit", "safe") +TIER_LABELS = { + "challenge": "挑战型(高影响因子/慢审稿)", + "fit": "适配型(中等影响/周期适中)", + "safe": "稳妥型(快速发表/门槛较低)", +} + +# 规则分档阈值(近似值,可后续配置化) +_CHALLENGE_MIN_IF = 9.0 +_SAFE_MAX_IF = 4.0 + +# tier 同义词归一(LLM 偶发中文标签) +_TIER_ALIASES = { + "挑战": "challenge", + "挑战型": "challenge", + "高风险": "challenge", + "适配": "fit", + "适配型": "fit", + "稳妥": "safe", + "稳妥型": "safe", + "低风险": "safe", +} + +SYSTEM_PROMPT = """你是学术投稿推荐专家(植物基因组学方向)。根据给定候选期刊、论文摘要与用户偏好,为**每一个**候选期刊输出推荐分档与理由。 + +硬规则(违反即视为无效输出): +1. id 白名单:只能使用输入 candidates 中出现的 id;绝对禁止添加、替换或臆造列表之外的任何期刊。 +2. 每个输入 id 恰好输出一次,不得遗漏、不得重复;期刊名称等元数据由系统填充,你只输出 id。 +3. tier 只能取 challenge | fit | safe: + - challenge(挑战型):高影响因子、审稿较慢或竞争激烈的期刊 + - fit(适配型):影响力与发表周期均衡、与论文契合的期刊 + - safe(稳妥型):审稿较快、门槛较低、命中概率较高的期刊 +4. match_reason:中文,1-2 句,结合摘要的研究主题与该刊 scope_desc 及指标(如有 similarity 一并参考),说明为何匹配/不匹配。 +5. risk_note:中文,1-2 句,指出投稿风险(超出用户偏好、IF 门槛偏高、范围匹配偏弱、审稿周期长等);无明显风险写「无」。 +6. 用户 preferences 为软约束:不满足偏好的期刊仍必须输出,并在 risk_note 中明确说明。 +7. 不确定时宁可保守陈述,禁止编造统计数据(录用率、审稿天数等)。 + +输出:仅一个 JSON 对象,格式: +{"rankings":[{"id":"...","tier":"challenge","match_reason":"...","risk_note":"..."}]} +不要输出任何 JSON 之外的内容。""" + + +class RankError(Exception): + """LLM 输出形态异常(无法按 JSON 解析/结构非法)。""" + + +@dataclass +class Ranking: + journal_id: str + tier: str + match_reason: str + risk_note: str + + +def rule_tier(journal: dict[str, Any]) -> str: + """确定性分档规则(LLM 缺漏/不可用时兜底)。""" + inf = journal.get("impact_factor") + weeks = journal.get("review_time_weeks") + if isinstance(inf, (int, float)): + if inf >= _CHALLENGE_MIN_IF: + return "challenge" + if inf <= _SAFE_MAX_IF: + return "safe" + elif isinstance(weeks, (int, float)) and weeks <= 4: + return "safe" + return "fit" + + +def build_user_prompt( + abstract: str, + candidates: list[dict[str, Any]], + preferences: dict[str, Any], +) -> str: + """候选 + 偏好 + 摘要 → 用户消息(JSON)。""" + payload = { + "abstract": abstract.strip()[:4000], + "preferences": preferences or {}, + "candidates": [ + { + "id": str(c["journal"]["id"]), + "name": str(c["journal"].get("name") or ""), + "impact_factor": c["journal"].get("impact_factor"), + "review_time_weeks": c["journal"].get("review_time_weeks"), + "acceptance_rate": c["journal"].get("acceptance_rate"), + "similarity": c.get("similarity"), + "scope_desc": str(c["journal"].get("scope_desc") or "")[:400], + } + for c in candidates + ], + } + return json.dumps(payload, ensure_ascii=False) + + +def _normalize_tier(raw: Any) -> str | None: + tier = str(raw or "").strip().lower() + tier = _TIER_ALIASES.get(str(raw or "").strip(), tier) + return tier if tier in TIERS else None + + +def validate_rankings( + payload: Any, candidates: list[dict[str, Any]] +) -> tuple[list[Ranking], int, int]: + """校验 LLM 输出。 + + 返回 (rankings, dropped_hallucinated, repaired): + - 白名单外 id / 重复 id → 丢弃并计数(repaired 中重复不计); + - tier 非法、LLM 缺漏的 id → 按规则补位(repaired 计数)。 + """ + if not isinstance(payload, dict) or not isinstance(payload.get("rankings"), list): + raise RankError("LLM 输出缺少 rankings 数组") + + by_id = {str(c["journal"]["id"]): c["journal"] for c in candidates} + input_ids = list(by_id) + seen: set[str] = set() + rankings: list[Ranking] = [] + dropped = 0 + repaired = 0 + + for entry in payload["rankings"]: + if not isinstance(entry, dict): + dropped += 1 + continue + jid = str(entry.get("id") or "").strip() + if jid in seen: + continue + if jid not in by_id: + dropped += 1 # 幻觉期刊:绝不进输出 + continue + seen.add(jid) + tier = _normalize_tier(entry.get("tier")) + if tier is None: + tier = rule_tier(by_id[jid]) + repaired += 1 + reason = str(entry.get("match_reason") or "").strip() or "基于期刊范围与指标的匹配" + risk = str(entry.get("risk_note") or "").strip() or "无" + rankings.append(Ranking(journal_id=jid, tier=tier, match_reason=reason, risk_note=risk)) + + for jid in input_ids: + if jid in seen: + continue + rankings.append( + Ranking( + journal_id=jid, + tier=rule_tier(by_id[jid]), + match_reason="LLM 未给出该期刊条目,已按影响因子/周期规则补位", + risk_note="未提供(LLM 输出缺漏,规则兜底)", + ) + ) + repaired += 1 + return rankings, dropped, repaired + + +async def rerank( + abstract: str, + candidates: list[dict[str, Any]], + preferences: dict[str, Any], +) -> tuple[list[Ranking], int, int]: + """LLM 重排 + 校验。LLMError / RankError 上抛(路由降级为规则分档)。""" + settings = get_settings() + payload = await llm.complete_json( + SYSTEM_PROMPT, + build_user_prompt(abstract, candidates, preferences), + temperature=0.2, + max_tokens=3000, + timeout=settings.recommend_read_timeout, + ) + return validate_rankings(payload, candidates) + + +def fallback_rankings(candidates: list[dict[str, Any]]) -> list[Ranking]: + """LLM 不可用时的确定性分档(不丢任何候选期刊)。""" + rankings: list[Ranking] = [] + for c in candidates: + j = c["journal"] + inf = j.get("impact_factor") + weeks = j.get("review_time_weeks") + rankings.append( + Ranking( + journal_id=str(j["id"]), + tier=rule_tier(j), + match_reason=( + f"规则分档:影响因子 {inf if inf is not None else '未收录'}、" + f"审稿约 {weeks if weeks is not None else '未收录'} 周" + ), + risk_note="LLM 不可用,本条按影响因子/周期规则估算", + ) + ) + return rankings diff --git a/review_service/app/services/llm.py b/review_service/app/services/llm.py new file mode 100644 index 0000000..06c8e43 --- /dev/null +++ b/review_service/app/services/llm.py @@ -0,0 +1,203 @@ +"""services/llm.py —— LLM 调用(httpx 裸调 DeepSeek,模式同 paper_writer_service)。 + +- complete_text(system, user, *, temperature=0.3, max_tokens=8000, timeout=None) -> str +- complete_json(...)(response_format json_object + 一次 JSON 修复重试) +- 4 次尝试(1.5s / 3s / 6s 指数退避,429 / 5xx / 超时) +- env 键(优先 REVIEW_LLM_*,回退 DOCGEN_LLM_*,再回退内置默认): + *_LLM_BASE_URL / *_LLM_API_KEY / *_LLM_MODEL / *_LLM_TIMEOUT +""" +from __future__ import annotations + +import asyncio +import json +import logging +import os +from typing import Any + +import httpx + +logger = logging.getLogger(__name__) + +DEFAULT_LLM_BASE_URL = "https://api.deepseek.com/v1" +DEFAULT_LLM_MODEL = "deepseek-chat" +DEFAULT_LLM_TIMEOUT = 300.0 +BACKOFF_SECONDS = (1.5, 3.0, 6.0) +MAX_ATTEMPTS = 4 + + +class LLMError(Exception): + """LLM 调用失败(重试尽/响应异常)。""" + + +def _env(keys: tuple[str, ...], default: str = "") -> str: + for key in keys: + val = os.environ.get(key) + if val: + return val + return default + + +def _llm_config() -> dict[str, Any]: + return { + "base_url": _env( + ("REVIEW_LLM_BASE_URL", "DOCGEN_LLM_BASE_URL"), DEFAULT_LLM_BASE_URL + ).rstrip("/"), + "api_key": _env(("REVIEW_LLM_API_KEY", "DOCGEN_LLM_API_KEY"), ""), + "model": _env(("REVIEW_LLM_MODEL", "DOCGEN_LLM_MODEL"), DEFAULT_LLM_MODEL), + "timeout": float( + _env(("REVIEW_LLM_TIMEOUT", "DOCGEN_LLM_TIMEOUT"), str(DEFAULT_LLM_TIMEOUT)) + ), + } + + +def _extract_text(payload: dict[str, Any]) -> str: + try: + choices = payload.get("choices") or [] + if choices: + content = choices[0].get("message", {}).get("content") + if isinstance(content, str): + return content + if isinstance(content, list): + return "".join( + str(c.get("text", "")) if isinstance(c, dict) else str(c) for c in content + ) + except Exception: + pass + return "" + + +async def _chat_once( + client: httpx.AsyncClient, + cfg: dict[str, Any], + system: str, + user: str, + *, + temperature: float, + max_tokens: int, + json_mode: bool, + timeout: float | None, +) -> str: + headers = {"Content-Type": "application/json"} + if cfg["api_key"]: + headers["Authorization"] = f"Bearer {cfg['api_key']}" + body: dict[str, Any] = { + "model": cfg["model"], + "messages": [ + {"role": "system", "content": system}, + {"role": "user", "content": user}, + ], + "temperature": temperature, + "max_tokens": max_tokens, + } + if json_mode: + body["response_format"] = {"type": "json_object"} + resp = await client.post( + f"{cfg['base_url']}/chat/completions", + headers=headers, + json=body, + timeout=timeout if timeout is not None else cfg["timeout"], + ) + resp.raise_for_status() + payload = resp.json() + if not isinstance(payload, dict): + raise LLMError("LLM 响应形态异常(非 JSON 对象)") + text = _extract_text(payload) + if not text: + raise LLMError("LLM 响应缺少 choices[0].message.content") + return text + + +async def _complete( + system: str, + user: str, + *, + temperature: float, + max_tokens: int, + json_mode: bool, + timeout: float | None, +) -> str: + cfg = _llm_config() + last_exc: BaseException | None = None + async with httpx.AsyncClient() as client: + for attempt in range(MAX_ATTEMPTS): + try: + return await _chat_once( + client, cfg, system, user, + temperature=temperature, max_tokens=max_tokens, json_mode=json_mode, + timeout=timeout, + ) + except LLMError: + raise + except (httpx.HTTPStatusError, httpx.HTTPError, httpx.TimeoutException) as exc: + last_exc = exc + status = getattr(getattr(exc, "response", None), "status_code", None) + retryable = status is None or status == 429 or status >= 500 + if not retryable or attempt == MAX_ATTEMPTS - 1: + raise LLMError(f"LLM 调用失败(HTTP {status or '网络'}):{exc}") from exc + await asyncio.sleep(BACKOFF_SECONDS[min(attempt, len(BACKOFF_SECONDS) - 1)]) + raise LLMError(f"LLM 调用失败:{last_exc}") + + +async def complete_text( + system: str, + user: str, + *, + temperature: float = 0.3, + max_tokens: int = 8000, + timeout: float | None = None, +) -> str: + """文本补全。失败抛 LLMError。""" + return await _complete( + system, user, temperature=temperature, max_tokens=max_tokens, json_mode=False, + timeout=timeout, + ) + + +def _repair_json(text: str) -> str: + text = text.strip() + if text.startswith("```"): + text = text.strip("`") + if text.lower().startswith("json"): + text = text[4:] + text = text.strip() + if not text: + raise LLMError("LLM 返回空内容") + if text.startswith("{"): + return text + start = text.find("{") + end = text.rfind("}") + if start >= 0 and end > start: + return text[start:end + 1] + raise LLMError("LLM 输出中未找到 JSON 对象") + + +async def complete_json( + system: str, + user: str, + *, + temperature: float = 0.3, + max_tokens: int = 8000, + timeout: float | None = None, +) -> dict[str, Any]: + """JSON 补全(json_object + 一次修复重试)。""" + text = await _complete( + system, user, temperature=temperature, max_tokens=max_tokens, json_mode=True, + timeout=timeout, + ) + try: + return json.loads(text) + except ValueError: + pass + text2 = await _complete( + system + "\n(重要:你的回答必须是单个合法 JSON 对象,不要输出其他任何内容)", + user, + temperature=temperature, + max_tokens=max_tokens, + json_mode=True, + timeout=timeout, + ) + try: + return json.loads(text2) + except ValueError: + repaired = _repair_json(text2) + return json.loads(repaired) diff --git a/review_service/app/services/paper_parse.py b/review_service/app/services/paper_parse.py new file mode 100644 index 0000000..cb7c3f5 --- /dev/null +++ b/review_service/app/services/paper_parse.py @@ -0,0 +1,139 @@ +"""paper_parse.py —— PDF → 纯文本(经 vstore 8094 现有解析接口,零改动复用)。 + +链路(全部只读消费 vstore 既有 API,不修改 vstore 代码): +1. POST {vstore}/api/vstore/ingest multipart file(vstore 内部 pymupdf 解析) +2. GET {vstore}/api/vstore/documents/{doc_id} → document.paragraphs 拼接纯文本 +3. DELETE {vstore}/api/vstore/documents/{doc_id} (临时解析件 best-effort 清理, + REVIEW_PARSE_DELETE_AFTER=0 可关闭——保留文档便于人工排查) + +为何不用 methodology 8092:其 /extract-upload 是 MinerU 分钟级异步 job +(MinerU 子进程 + LLM 抽取两阶段),不适配同步自审稿;vstore 段落解析秒级 +返回,满足 presubmit 场景。methodology 地址在 config 中预留供后续扩展。 +""" +from __future__ import annotations + +import logging +from typing import Any + +import httpx + +from ..config import get_settings + +logger = logging.getLogger(__name__) + + +class ParseError(Exception): + """PDF 解析失败(上游不可达/响应异常/空文本)。""" + + +async def parse_pdf(path: str) -> str: + """接收 PDF 文件路径,返回拼接后的纯文本。失败抛 ParseError。""" + try: + with open(path, "rb") as fh: + file_bytes = fh.read() + except OSError as exc: + raise ParseError(f"读取 PDF 失败:{exc}") from exc + return await parse_pdf_bytes(file_bytes, filename=str(path).rsplit("/", 1)[-1] or "paper.pdf") + + +async def parse_pdf_bytes(file_bytes: bytes, filename: str = "paper.pdf") -> str: + """接收 PDF 字节流,返回拼接后的纯文本。失败抛 ParseError。""" + if not file_bytes: + raise ParseError("PDF 内容为空") + + settings = get_settings() + base = settings.vstore_base + timeout = httpx.Timeout( + connect=5.0, read=settings.parse_timeout, write=settings.parse_timeout, pool=5.0 + ) + + async with httpx.AsyncClient(timeout=timeout) as client: + # ---- 1) ingest(vstore 内部 pymupdf 解析 + 嵌入 + 加密落盘)---- + try: + resp = await client.post( + f"{base}/api/vstore/ingest", + files={"file": (filename, file_bytes, "application/pdf")}, + data={ + "name": filename, + "category": "review_presubmit", + "description": "review_service 临时解析件", + }, + ) + except httpx.HTTPError as exc: + raise ParseError(f"vstore 不可达({base}):{exc}") from exc + + if resp.status_code >= 400: + # 读上游错误体(信封 JSON 或裸文本),区分“不可达”与“上游报错” + raise ParseError(f"vstore ingest 失败(HTTP {resp.status_code}):{_err_body(resp)}") + + try: + payload = resp.json() + except ValueError as exc: + raise ParseError(f"vstore ingest 响应非 JSON:{exc}") from exc + + if not isinstance(payload, dict) or not payload.get("ok"): + message = _err_message(payload) or "vstore ingest 失败" + raise ParseError(message) + doc_id = str((payload.get("item") or {}).get("document_id") or "") + if not doc_id: + raise ParseError("vstore ingest 响应缺少 document_id") + + # ---- 2) 取明文全文(paragraphs 拼接)+ 3) 清理临时件 ---- + try: + text = await _fetch_text(client, base, doc_id) + finally: + if settings.parse_delete_after: + await _best_effort_delete(client, base, doc_id) + + text = text.strip() + if not text: + raise ParseError("PDF 解析结果为空(可能是扫描件/图片型 PDF,vstore 无 OCR)") + return text + + +async def _fetch_text(client: httpx.AsyncClient, base: str, doc_id: str) -> str: + """取 vstore 文档明文并按段落拼接纯文本。""" + try: + resp = await client.get(f"{base}/api/vstore/documents/{doc_id}") + except httpx.HTTPError as exc: + raise ParseError(f"vstore 取文档失败({doc_id}):{exc}") from exc + if resp.status_code >= 400: + raise ParseError( + f"vstore 取文档失败({doc_id},HTTP {resp.status_code}):{_err_body(resp)}" + ) + try: + payload = resp.json() + except ValueError as exc: + raise ParseError(f"vstore 取文档响应非 JSON({doc_id}):{exc}") from exc + if not isinstance(payload, dict) or not payload.get("ok"): + raise ParseError(_err_message(payload) or f"vstore 取文档失败({doc_id})") + + document: dict[str, Any] = payload.get("document") or {} + paragraphs = document.get("paragraphs") or [] + return "\n".join(str(p) for p in paragraphs if str(p).strip()) + + +async def _best_effort_delete(client: httpx.AsyncClient, base: str, doc_id: str) -> None: + try: + await client.delete(f"{base}/api/vstore/documents/{doc_id}") + except Exception: # noqa: BLE001 - 清理失败不阻断(文档级 secure_delete 已尽力) + logger.warning("paper_parse: vstore 临时文档清理失败(%s)", doc_id, exc_info=True) + + +def _err_message(payload: Any) -> str: + if isinstance(payload, dict): + err = payload.get("error") + if isinstance(err, dict): + return str(err.get("message") or "") + if isinstance(err, str): + return err + return "" + + +def _err_body(resp: httpx.Response) -> str: + """上游错误体:优先 JSON 信封 message,回退裸文本(截断 500 字符)。""" + try: + payload = resp.json() + except ValueError: + return (resp.text or "").strip()[:500] or "(空响应体)" + return _err_message(payload) or str(payload)[:500] diff --git a/review_service/app/services/self_review.py b/review_service/app/services/self_review.py new file mode 100644 index 0000000..0def3bd --- /dev/null +++ b/review_service/app/services/self_review.py @@ -0,0 +1,155 @@ +"""services/self_review.py —— 植物基因组学专属自审稿(System Prompt + 报告模型)。 + +六大领域维度检查清单硬编码在 SYSTEM_PROMPT(发给 DeepSeek): +1. 基因组组装质量(N50/L50/BUSCO 完整格式/Hi-C 挂载率,缺项即 Major) +2. 基因注释可靠性(MAKER/AUGUSTUS 流程、RNA-seq 证据、基因数与已知范围一致性) +3. 比较基因组学与进化(Bootstrap/后验概率、OrthoFinder 等直系同源策略) +4. 数据可用性合规(SRA/BioProject + 组装/GFF3 Accession,缺失即 Major) +5. 统计与实验设计(GWAS/QTL 样本量·多重校正·群体结构;转录组生物学重复) +6. 伦理与合规·植物特异性(凭证标本 voucher、ABS 惠益分享声明) + +Major/Minor 每条必须给 Evidence(论文章节位置或具体指标数值),由 coerce +宽容归一化(缺失补空串,不丢条目)。 +""" +from __future__ import annotations + +from pydantic import BaseModel, Field + +RECOMMENDATIONS = ("accept", "minor_revision", "major_revision", "reject") + +SYSTEM_PROMPT = """你是一位植物基因组学领域资深审稿人,长期为 Plant Cell、Nature Plants、 +Genome Biology、Molecular Plant、Plant Journal 等期刊审稿。请对用户提供的论文正文做 +投稿前自审(pre-submission self review),严格按以下六个植物基因组学专属维度逐项检查, +输出结构化审稿意见。所有条目使用中文撰写(专业术语、指标名、工具名保留英文)。 + +【维度一:基因组组装质量】必查指标: +- contig N50 / scaffold N50 / L50(报了哪个要写明哪个) +- BUSCO 完整度:必须按完整格式报告——例如 + "Complete 95.3% [S:93.1%, D:2.2%], Missing 4.7%, n=1614 (embryophyta_odb10)" + (含 Complete/Single-copy/Duplicated/Missing 四项与数据集版本、n 值) +- Hi-C 挂载率(anchoring rate,chromosome-level 比例)及挂载到染色体的 scaffold 比例 +判定规则:若论文只报 N50 而未报 BUSCO 完整度或 Hi-C 挂载率(组装类论文),直接列为 +Major Weakness。同时检查组装是否为 pseudo-chromosome 级别、污染评估(如 k-mer/coverage +检查)与 gap 比例。 + +【维度二:基因注释可靠性】检查: +- 是否使用标准注释流程(MAKER、AUGUSTUS、BRAKER、GeMoMa、EVidenceModeler 等),参数与版本是否交代 +- 是否有转录组证据支持:RNA-seq(组织/时期/物种内或近缘种)比对支撑比例,或蛋白同源证据 +- 基因数量是否与该物种已知基因数范围一致(如水稻 ~37-40k、拟南芥 ~27k、玉米 ~39-45k、 + 小麦 ~107k、大豆 ~46k;近缘种偏差过大须说明);有无转座元件基因误注释的排查 +- 注释质量评估:BRAKER/AED 分值、BUSCO 在蛋白集上的复核 + +【维度三:比较基因组学与进化】检查: +- 系统发育树:每个节点必须标注 Bootstrap 支持率(建议 ≥1000 次重复)或贝叶斯后验概率; + 未标注或仅"高/低支持"的描述 → Major 或 Minor(视严重程度) +- 直系同源基因鉴定策略是否说明清楚:OrthoFinder/OrthoMCL/RBX 等工具、版本、参数、 + 聚类阈值(inflation/coverage)、single-copy 标记基因的筛选方式 +- 分子进化分析是否规范:dN/dS 检验方法与多重校正、共线性(synteny)分析参数、 + 分化时间估算是否校准(化石/二次校准点) + +【维度四:数据可用性合规——极其重要】必查: +- 原始测序数据是否上传 NCBI SRA / BioProject(或 ENA/DDBJ),是否给出 Accession 号 + (PRJNA/PRJEB/ SRP 开头) +- 基因组组装是否有 GenBank/ENA accession(GCA_/GCF_),GFF3 注释文件、蛋白/CDS 文件 + 是否有可公开获取的位置(仓库 accession 或补充数据链接) +- 转录组数据是否同样有 SRA accession +判定规则:组装/注释类论文若缺失上述任何一环,直接列为 Major Weakness。 + +【维度五:统计与实验设计】检查: +- GWAS/QTL 定位:样本量/群体大小是否充分;多重检验校正是否明确(Bonferroni/FDR/ + permutation 阈值/PCA 显著性水平);群体结构控制(PCA、亲缘关系矩阵 K、分层分析) + 是否交代;表型测量描述是否充分 +- 转录组分析:生物学重复数量(≥3 为底线)、差异分析工具(DESeq2/edgeR 等)与 + 校正方法、批次效应处理、|log2FC| 与 padj 阈值 +- 其他统计:t 检验/ANOVA 是否满足前提、重复类型(生物学 vs 技术重复)写明与否 + +【维度六:伦理与合规(植物特异性)】检查: +- 野生植物材料:是否提供凭证标本(voucher specimen)信息——标本馆编号、存放机构、 + 采集地点(GPS)与采集许可;无凭证标本的野生资源取样 → Major 或 Minor(视用途) +- 遗传资源获取与惠益分享(ABS)合规性:是否声明符合《名古屋议定书》/本国遗传资源 + 获取条例(如中国《生物安全法》/《种子法》相关条款)、是否说明材料来源与授权 +- 农业转基因/基因编辑材料的合规声明(若涉及) + +输出要求(必须输出单个 JSON 对象,不要输出其他任何内容): +{ + "summary": "总体评价(3-5 句,须点明论文类型与所适用的维度)", + "major_weaknesses": [{"title": "...", "detail": "...", "evidence": "...", "suggestion": "..."}], + "minor_weaknesses": [{"title": "...", "detail": "...", "evidence": "...", "suggestion": "..."}], + "presentation_format": [{"title": "...", "detail": "...", "evidence": "...", "suggestion": "..."}], + "questions_for_authors": ["..."], + "recommendation": "major_revision" +} + +硬性规则: +1. major_weaknesses 3-8 条、minor_weaknesses 3-8 条;上述维度中命中的硬性判定规则 + (组装缺 BUSCO/挂载率、缺数据 Accession)必须出现。 +2. **每条 major_weaknesses 的 evidence 字段必填**:必须引用论文的具体章节位置 + (如 "Methods 2.1"、"Table 2"、"Results 第 3 段"、"Data Availability 一句话未见") + 或具体指标数值(如 "仅报 scaffold N50=42.6 Mb,未提供 BUSCO 与 Hi-C 挂载率")。 + evidence 严禁编造:引用不到具体位置时,写明"正文未见相关报告"。 +3. minor_weaknesses/presentation_format 的 evidence 尽量给出,无法定位时可留空字符串。 +4. 论文不涉及的维度(如纯 RNA-seq 论文不谈组装)在 summary 中说明并跳过,不硬凑条目。 +5. recommendation 只能是 accept / minor_revision / major_revision / reject 之一, + 缺失关键合规项(维度四)时通常不高于 major_revision。 +6. presentation_format 覆盖:图表规范(图注含单位/误差棒说明)、参考文献格式、 + 字数与结构、英文语法(若投英文刊)。 +""" + + +class WeaknessItem(BaseModel): + title: str + detail: str = "" + evidence: str = "" + suggestion: str = "" + + +class SelfReviewReport(BaseModel): + summary: str = "" + major_weaknesses: list[WeaknessItem] = Field(default_factory=list) + minor_weaknesses: list[WeaknessItem] = Field(default_factory=list) + presentation_format: list[WeaknessItem] = Field(default_factory=list) + questions_for_authors: list[str] = Field(default_factory=list) + recommendation: str = "major_revision" + + +def build_user_prompt(text: str, target_journal: str) -> str: + header = f"目标期刊:{target_journal}\n\n" if target_journal else "" + return f"{header}论文正文:\n\n{text}" + + +def _coerce_items(raw: object) -> list[WeaknessItem]: + items: list[WeaknessItem] = [] + if not isinstance(raw, list): + return items + for entry in raw: + if isinstance(entry, str) and entry.strip(): + items.append(WeaknessItem(title=entry.strip())) + elif isinstance(entry, dict): + title = str(entry.get("title") or "").strip() + detail = str(entry.get("detail") or "").strip() + if not title and not detail: + continue + items.append(WeaknessItem( + title=title or "(未命名)", + detail=detail, + evidence=str(entry.get("evidence") or "").strip(), + suggestion=str(entry.get("suggestion") or "").strip(), + )) + return items + + +def coerce_report(payload: dict) -> SelfReviewReport: + questions = payload.get("questions_for_authors") or [] + if not isinstance(questions, list): + questions = [] + recommendation = str(payload.get("recommendation") or "").strip().lower() + if recommendation not in RECOMMENDATIONS: + recommendation = "major_revision" + return SelfReviewReport( + summary=str(payload.get("summary") or "").strip(), + major_weaknesses=_coerce_items(payload.get("major_weaknesses")), + minor_weaknesses=_coerce_items(payload.get("minor_weaknesses")), + presentation_format=_coerce_items(payload.get("presentation_format")), + questions_for_authors=[str(q).strip() for q in questions if str(q).strip()], + recommendation=recommendation, + ) diff --git a/review_service/data/journals/journals.json b/review_service/data/journals/journals.json new file mode 100644 index 0000000..a5c0ee1 --- /dev/null +++ b/review_service/data/journals/journals.json @@ -0,0 +1,62 @@ +{ + "version": 1, + "updated": "2026-10-09", + "notes": "植物基因组学领域种子期刊。acceptance_rate 无公开权威数据一律为 null(不编造);impact_factor / review_time_weeks 为公开 JCR/期刊官网常识近似值,以 last_updated 标注刷新时间,接入真实数据源前需人工核验。scope_desc 为英文范围描述,供 vstore 向量匹配使用。", + "journals": [ + { + "id": "plant-cell", + "name": "The Plant Cell", + "scope_desc": "Broad-interest plant biology with emphasis on molecular, cellular and physiological mechanisms, including genomics, systems biology, gene regulation, signaling, and plant-microbe interactions. Publishes genome-scale and functional genomics studies with strong mechanistic insight.", + "impact_factor": 11.6, + "review_time_weeks": 6.0, + "acceptance_rate": null, + "submission_deadline": null, + "official_url": "https://academic.oup.com/plcell", + "last_updated": "2026-10-09" + }, + { + "id": "genome-biology", + "name": "Genome Biology", + "scope_desc": "High-impact open-access journal for genome-scale research across all organisms, including genome assembly and annotation, comparative and evolutionary genomics, computational methods, single-cell and multi-omics studies, and reproducible bioinformatics.", + "impact_factor": 10.1, + "review_time_weeks": 4.0, + "acceptance_rate": null, + "submission_deadline": null, + "official_url": "https://genomebiology.biomedcentral.com", + "last_updated": "2026-10-09" + }, + { + "id": "plant-journal", + "name": "The Plant Journal", + "scope_desc": "Molecular and physiological plant sciences, including genome biology and genomics, gene function, cell and developmental biology, stress and environmental responses, and plant biotechnology; favors experimental studies with clear mechanistic advance.", + "impact_factor": 7.2, + "review_time_weeks": 5.0, + "acceptance_rate": null, + "submission_deadline": null, + "official_url": "https://onlinelibrary.wiley.com/journal/1365313X", + "last_updated": "2026-10-09" + }, + { + "id": "theoretical-applied-genetics", + "name": "Theoretical and Applied Genetics", + "scope_desc": "Plant breeding and genetics research combining theoretical and applied approaches, including quantitative genetics, QTL mapping, genome-wide association studies, genomic selection, population genetics, and molecular marker applications for crop improvement.", + "impact_factor": 5.3, + "review_time_weeks": 5.0, + "acceptance_rate": null, + "submission_deadline": null, + "official_url": "https://link.springer.com/journal/338", + "last_updated": "2026-10-09" + }, + { + "id": "plant-genome", + "name": "The Plant Genome", + "scope_desc": "Plant and crop genome research with practical breeding applications, including genome assembly and annotation, structural variation, GWAS and QTL analysis, marker-assisted and genomic selection, and translational genomics for crop improvement.", + "impact_factor": 3.3, + "review_time_weeks": 4.0, + "acceptance_rate": null, + "submission_deadline": null, + "official_url": "https://acsess.onlinelibrary.wiley.com/journal/1940-3372", + "last_updated": "2026-10-09" + } + ] +} diff --git a/review_service/pytest.ini b/review_service/pytest.ini new file mode 100644 index 0000000..1f69640 --- /dev/null +++ b/review_service/pytest.ini @@ -0,0 +1,6 @@ +[pytest] +python_files = test_*.py +pythonpath = . +markers = + review_unit: 审稿服务单元测试 +asyncio_mode = auto diff --git a/review_service/restart.sh b/review_service/restart.sh new file mode 100755 index 0000000..80b522d --- /dev/null +++ b/review_service/restart.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# restart.sh —— REVIEW 服务重启脚本(8100;不触碰生产服务 8090/8091/8092/8093/8094/8097/8098)。 +# 用法: restart.sh [python] [port] +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# 默认 venv:本机统一 venv 固定路径(原先 $REPO_ROOT/../ 推导在本工作区不存在) +PYTHON="${1:-/home/xzq/5090/teamWorkspace/zh/plantai-rag-new-venv/bin/python}" +PORT="${2:-8100}" +HOST="${REVIEW_BIND_HOST:-127.0.0.1}" + +[[ -x "$PYTHON" ]] || { echo "Python not found: $PYTHON" >&2; exit 2; } + +APP_MODULE="app.main:app" +if command -v lsof >/dev/null 2>&1; then + PID="$(lsof -ti tcp:"$PORT" -sTCP:LISTEN 2>/dev/null || true)" + if [[ -n "$PID" ]]; then + echo "[restart] 停止 $PORT 旧进程 pid=$PID" + kill $PID 2>/dev/null || true + sleep 2 + fi +fi + +cd "$SCRIPT_DIR" +# 加载运行时配置(.env 不入 git):services/llm.py 直接读 REVIEW_LLM_*/DOCGEN_LLM_* +# 裸键,paper_parse.py 读 REVIEW_*——需 set -a 显式导出(同 paper_writer_service 先例)。 +set -a +[ -f .env ] && source .env +set +a +echo "[restart] 启动审稿服务 :$PORT($PYTHON)" +nohup "$PYTHON" -m uvicorn "$APP_MODULE" --host "$HOST" --port "$PORT" \ + > "$SCRIPT_DIR/review.log" 2>&1 & +echo "[restart] 完成;日志 review_service/review.log" diff --git a/review_service/tests/test_presubmit.py b/review_service/tests/test_presubmit.py new file mode 100644 index 0000000..5d4a1de --- /dev/null +++ b/review_service/tests/test_presubmit.py @@ -0,0 +1,163 @@ +"""tests/test_presubmit.py —— presubmit 离线单元测试(mock 解析与 LLM,不依赖上游)。 + +覆盖:非 PDF 校验 / 报告归一化 / LLM 失败降级 / 解析失败降级 / 非法 recommendation 回退。 +运行: cd review_service && /bin/python -m pytest -q +""" +from __future__ import annotations + +import pytest +from fastapi.testclient import TestClient + +from app.main import app +from app.services import llm, paper_parse + +FAKE_PDF = b"%PDF-1.4 fake-bytes-for-test" + +LLM_PAYLOAD = { + "summary": "研究问题清晰,但统计与证据链存在重大缺口。", + "major_weaknesses": [ + { + "title": "统计方法不当", + "detail": "未做多重检验校正", + "evidence": "Methods 2.1 仅报 p<0.05,未见 FDR/Bonferroni", + "suggestion": "补充 FDR 校正", + }, + "纯字符串条目", # 宽容归一化:字符串 → WeaknessItem(title=...) + ], + # minor 故意不带 evidence 字段 → 归一化应补空串 + "minor_weaknesses": [{"detail": "缺少缩写表", "title": "缩写"}], + "presentation_format": [{"title": "图注不完整", "detail": "Fig.2 无单位", "suggestion": "补单位"}], + "questions_for_authors": ["群体结构如何校正?", ""], + "recommendation": "MAJOR_REVISION", # 应归一化为小写 +} + + +@pytest.fixture() +def client() -> TestClient: + return TestClient(app) + + +@pytest.fixture(autouse=True) +def _mock_upstreams(monkeypatch): + async def fake_parse(file_bytes: bytes, filename: str = "paper.pdf") -> str: + assert file_bytes == FAKE_PDF + return "论文正文……" * 10 + + async def fake_llm_json(system: str, user: str, **kwargs): + assert "论文正文" in user + return dict(LLM_PAYLOAD) + + async def boom_llm(*args, **kwargs): + raise llm.LLMError("余额不足") + + async def boom_parse(*args, **kwargs): + raise paper_parse.ParseError("PDF 解析结果为空") + + monkeypatch.setattr(paper_parse, "parse_pdf_bytes", fake_parse) + monkeypatch.setattr(llm, "complete_json", fake_llm_json) + yield + # monkeypatch 自动还原 + + +def _post(client: TestClient, filename: str, content: bytes, journal: str = ""): + data = {"target_journal": journal} if journal else {} + return client.post( + "/api/review/presubmit", + files={"file": (filename, content, "application/pdf")}, + data=data, + ) + + +def test_non_pdf_rejected(client: TestClient): + r = client.post( + "/api/review/presubmit", + files={"file": ("a.txt", b"x", "text/plain")}, + ) + body = r.json() + assert body["ok"] is False + assert body["error"]["code"] == "VALIDATION" + + +def test_empty_file_rejected(client: TestClient): + body = _post(client, "p.pdf", b"").json() + assert body["ok"] is False + assert body["error"]["code"] == "VALIDATION" + + +def test_normal_report_normalized(client: TestClient): + body = _post(client, "p.pdf", FAKE_PDF, journal="Plant Cell").json() + assert body["ok"] is True + report = body["report"] + # recommendation 大写 → 小写 + assert report["recommendation"] == "major_revision" + # 字符串条目宽容归一化 + assert len(report["major_weaknesses"]) == 2 + assert report["major_weaknesses"][1]["title"] == "纯字符串条目" + # Evidence 字段:有则透传,字符串条目/缺失则为空串 + assert report["major_weaknesses"][0]["evidence"] == "Methods 2.1 仅报 p<0.05,未见 FDR/Bonferroni" + assert report["major_weaknesses"][1]["evidence"] == "" + assert report["minor_weaknesses"][0]["evidence"] == "" + # 空问题剔除 + assert report["questions_for_authors"] == ["群体结构如何校正?"] + assert report["minor_weaknesses"] and report["presentation_format"] and report["summary"] + # meta 透传 + assert body["meta"]["target_journal"] == "Plant Cell" + assert body["meta"]["text_chars"] > 0 + assert body["meta"]["truncated"] is False + + +def test_llm_failure_degrades(client: TestClient, monkeypatch): + async def boom(*args, **kwargs): + raise llm.LLMError("余额不足") + + monkeypatch.setattr(llm, "complete_json", boom) + body = _post(client, "p.pdf", FAKE_PDF).json() + assert body["ok"] is False + assert body["error"]["code"] == "UPSTREAM_DOWN" + assert body["error"]["degraded"] is True + + +def test_parse_failure_degrades(client: TestClient, monkeypatch): + async def boom(*args, **kwargs): + raise paper_parse.ParseError("PDF 解析结果为空") + + monkeypatch.setattr(paper_parse, "parse_pdf_bytes", boom) + body = _post(client, "p.pdf", FAKE_PDF).json() + assert body["ok"] is False + assert body["error"]["code"] == "PARSE_FAILED" + assert body["error"]["degraded"] is True + + +def test_invalid_recommendation_falls_back(client: TestClient, monkeypatch): + async def weird(*args, **kwargs): + return {"summary": "x", "recommendation": "strong_accept", "major_weaknesses": "not-a-list"} + + monkeypatch.setattr(llm, "complete_json", weird) + body = _post(client, "p.pdf", FAKE_PDF).json() + assert body["ok"] is True + assert body["report"]["recommendation"] == "major_revision" + assert body["report"]["major_weaknesses"] == [] + + +def test_domain_system_prompt_wired(client: TestClient, monkeypatch): + """植物基因组学六维清单 + Evidence 规则必须注入 System Prompt。""" + captured: dict[str, str] = {} + + async def spy(system: str, user: str, **kwargs): + captured["system"] = system + return dict(LLM_PAYLOAD) + + monkeypatch.setattr(llm, "complete_json", spy) + body = _post(client, "p.pdf", FAKE_PDF, journal="Plant Cell").json() + assert body["ok"] is True + system = captured["system"] + for marker in ( + "BUSCO", "N50", "L50", "Hi-C", "挂载率", # 维度1 组装质量 + "MAKER", "AUGUSTUS", "RNA-seq", # 维度2 注释可靠性 + "Bootstrap", "OrthoFinder", # 维度3 比较基因组 + "SRA", "BioProject", "GFF3", "accession", # 维度4 数据合规 + "GWAS", "多重检验校正", "生物学重复", # 维度5 统计设计 + "凭证标本", "ABS", "惠益分享", # 维度6 伦理合规 + "evidence", "章节", # Evidence 硬性要求 + ): + assert marker in system, f"System Prompt 缺少领域标记: {marker}" diff --git a/review_service/tests/test_recommend.py b/review_service/tests/test_recommend.py new file mode 100644 index 0000000..1f6e50f --- /dev/null +++ b/review_service/tests/test_recommend.py @@ -0,0 +1,271 @@ +"""tests/test_recommend.py —— /api/review/recommend 离线单元测试。 + +mock vstore 向量匹配(journal_kb.match)与 LLM(llm.complete_json),不依赖上游。 +核心回归:LLM 幻觉期刊名绝不进输出(白名单 id 硬校验 + 名称一律取 DB)。 + +运行: cd review_service && /bin/python -m pytest -q +""" +from __future__ import annotations + +import asyncio + +import pytest +from fastapi.testclient import TestClient + +from app import db as db_mod +from app.main import app +from app.services import journal_kb, journal_rank, llm + +ABSTRACT = ( + "We report a chromosome-level genome assembly of wild rice Oryza rufipogon " + "using PacBio HiFi and Hi-C sequencing, annotate 38,412 protein-coding genes " + "with RNA-seq evidence, and perform comparative genomics and GWAS analyses " + "to reveal the evolutionary basis of agronomic traits in rice." +) + +SEED_NAMES = { + "The Plant Cell", + "Genome Biology", + "The Plant Journal", + "Theoretical and Applied Genetics", + "The Plant Genome", +} + +# 覆盖全部 5 本种子期刊的合法重排结果 +ALL_RANKINGS = [ + {"id": "plant-cell", "tier": "challenge", "match_reason": "功能基因组机制研究契合", "risk_note": "竞争激烈"}, + {"id": "genome-biology", "tier": "challenge", "match_reason": "组装与比较基因组学范围契合", "risk_note": "IF 门槛高"}, + {"id": "plant-journal", "tier": "fit", "match_reason": "植物分子生物学范围契合", "risk_note": "无"}, + {"id": "theoretical-applied-genetics", "tier": "fit", "match_reason": "GWAS/驯化分析契合", "risk_note": "偏重育种"}, + {"id": "plant-genome", "tier": "safe", "match_reason": "作物基因组组装契合", "risk_note": "IF 较低"}, +] + + +def make_fake_match(scores: dict[str, float] | None = None, fail: bool = False): + async def fake(abstract: str, journals: list[dict]): + if fail: + raise journal_kb.MatchError("vstore 不可达(mock)") + out = [ + {"journal": j, "similarity": (scores or {}).get(str(j["id"]), 0.5)} + for j in journals + ] + return out, True + + return fake + + +def make_fake_llm(rankings: list[dict] | None = None, fail: bool = False, payload=None): + async def fake(system: str, user: str, **kwargs): + if fail: + raise llm.LLMError("余额不足(mock)") + if payload is not None: + return payload + return {"rankings": rankings if rankings is not None else []} + + return fake + + +@pytest.fixture() +def client(tmp_path, monkeypatch): + db_mod.set_path(tmp_path / "review_test.db") # 进 lifespan 前注入 tmp 路径 + monkeypatch.setattr(journal_kb, "match", make_fake_match()) + monkeypatch.setattr(llm, "complete_json", make_fake_llm(ALL_RANKINGS)) + with TestClient(app) as c: # CM 触发 lifespan:init_db(注入路径) + 收尾 close + yield c + + +def _all_items(body: dict) -> list[dict]: + items: list[dict] = [] + for tier in ("challenge", "fit", "safe"): + items.extend(body["tiers"][tier]["items"]) + return items + + +def test_recommend_happy_path(client: TestClient): + r = client.post("/api/review/recommend", json={"abstract": ABSTRACT}) + assert r.status_code == 200 + body = r.json() + assert body["ok"] is True + assert set(body["tiers"]) == {"challenge", "fit", "safe"} + assert "挑战型" in body["tiers"]["challenge"]["label"] + assert "适配型" in body["tiers"]["fit"]["label"] + assert "稳妥型" in body["tiers"]["safe"]["label"] + + items = _all_items(body) + assert len(items) == 5 + assert {it["name"] for it in items} == SEED_NAMES + for it in items: + assert it["match_reason"], f"缺少匹配理由:{it['name']}" + assert it["risk_note"], f"缺少风险提示:{it['name']}" + assert it["similarity"] == 0.5 + # 三档内容与 LLM 输出一致 + assert [it["name"] for it in body["tiers"]["challenge"]["items"]][0] == "The Plant Cell" + assert body["tiers"]["safe"]["items"][0]["name"] == "The Plant Genome" + + meta = body["meta"] + assert meta["llm_ok"] is True and meta["vector_ok"] is True + assert meta["dropped_hallucinated"] == 0 + assert meta["seed_count"] == 5 + + +def test_seed_has_no_fabricated_acceptance_rate(client: TestClient): + """种子诚实性:无公开数据的 acceptance_rate 必须为 null。""" + body = client.post("/api/review/recommend", json={"abstract": ABSTRACT}).json() + for it in _all_items(body): + assert it["acceptance_rate"] is None, f"编造了录用率:{it['name']}" + + +def test_hallucinated_journal_dropped(client: TestClient, monkeypatch): + """LLM 幻觉期刊(白名单外 id)绝不进输出;缺漏期刊规则补位。""" + hallucinated = { + "id": "nature-genetics", + "tier": "challenge", + "match_reason": "幻觉期刊,输入列表中并不存在", + "risk_note": "x", + } + monkeypatch.setattr( + llm, + "complete_json", + make_fake_llm([hallucinated, ALL_RANKINGS[1]]), # 1 幻觉 + 1 真实,其余缺漏 + ) + body = client.post("/api/review/recommend", json={"abstract": ABSTRACT}).json() + assert body["ok"] is True + + items = _all_items(body) + raw = str(body) + assert "nature-genetics" not in raw and "Nature Genetics" not in raw + assert "幻觉期刊" not in raw # 幻觉条目的理由同样被丢弃 + assert {it["name"] for it in items} <= SEED_NAMES + assert len(items) == 5 # 4 本缺漏由规则补位,不丢候选 + assert body["meta"]["dropped_hallucinated"] == 1 + assert body["meta"]["repaired"] == 4 + + +def test_llm_name_tamper_ignored(client: TestClient, monkeypatch): + """LLM 篡改期刊名不采信:输出名称一律取 DB。""" + tampered = [ + {"id": "plant-cell", "tier": "fit", "name": "Fake Journal X", + "match_reason": "被篡改的名称", "risk_note": "无"} + ] + monkeypatch.setattr(llm, "complete_json", make_fake_llm(tampered)) + body = client.post("/api/review/recommend", json={"abstract": ABSTRACT}).json() + assert body["ok"] is True + raw = str(body) + assert "Fake Journal X" not in raw + plant_cell = [it for it in _all_items(body) if it["id"] == "plant-cell"] + assert plant_cell and plant_cell[0]["name"] == "The Plant Cell" + + +def test_llm_failure_fallback(client: TestClient, monkeypatch): + """LLM 失败 → 规则分档,推荐仍可用(永不 5xx)。""" + monkeypatch.setattr(llm, "complete_json", make_fake_llm(fail=True)) + body = client.post("/api/review/recommend", json={"abstract": ABSTRACT}).json() + assert body["ok"] is True + assert body["meta"]["llm_ok"] is False + items = _all_items(body) + assert len(items) == 5 + assert {it["name"] for it in items} == SEED_NAMES + # 规则分档:IF≥9 → challenge(The Plant Cell 11.6 / Genome Biology 10.1) + challenge = {it["name"] for it in body["tiers"]["challenge"]["items"]} + assert challenge == {"The Plant Cell", "Genome Biology"} + for it in items: + assert it["match_reason"] and it["risk_note"] + + +def test_vector_failure_degrades(client: TestClient, monkeypatch): + """向量匹配失败 → 全量候选 + similarity 为 null,不报错。""" + monkeypatch.setattr(journal_kb, "match", make_fake_match(fail=True)) + body = client.post("/api/review/recommend", json={"abstract": ABSTRACT}).json() + assert body["ok"] is True + assert body["meta"]["vector_ok"] is False + assert body["meta"]["candidate_count"] == 5 + items = _all_items(body) + assert len(items) == 5 + assert all(it["similarity"] is None for it in items) + + +def test_invalid_tier_repaired(client: TestClient, monkeypatch): + """非法 tier 按规则补位,不丢期刊。""" + bad = [ + {"id": "plant-genome", "tier": "超越顶刊", "match_reason": "tier 非法", "risk_note": "无"}, + {"id": "plant-cell", "tier": "challenge", "match_reason": "合法", "risk_note": "无"}, + ] + monkeypatch.setattr(llm, "complete_json", make_fake_llm(bad)) + body = client.post("/api/review/recommend", json={"abstract": ABSTRACT}).json() + assert body["ok"] is True + assert len(_all_items(body)) == 5 + # plant-genome 规则分档 → IF 3.3 ≤ 4 → safe + safe_ids = [it["id"] for it in body["tiers"]["safe"]["items"]] + assert "plant-genome" in safe_ids + assert body["meta"]["repaired"] >= 1 + + +def test_short_abstract_validation(client: TestClient): + body = client.post("/api/review/recommend", json={"abstract": "too short"}).json() + assert body["ok"] is False + assert body["error"]["code"] == "VALIDATION" + assert body["tiers"] is None + + +def test_tier_focus_filters_other_tiers(client: TestClient): + body = client.post( + "/api/review/recommend", + json={"abstract": ABSTRACT, "preferences": {"tier_focus": "safe"}}, + ).json() + assert body["ok"] is True + assert body["tiers"]["challenge"]["items"] == [] + assert body["tiers"]["fit"]["items"] == [] + assert body["tiers"]["safe"]["items"] # 聚焦档保留 + assert body["meta"]["preferences"]["tier_focus"] == "safe" + + +def test_soft_preference_risk_note(client: TestClient): + """软偏好:超周期偏好只加风险提示,不删条目。""" + body = client.post( + "/api/review/recommend", + json={"abstract": ABSTRACT, "preferences": {"max_review_weeks": 5}}, + ).json() + assert body["ok"] is True + items = _all_items(body) + assert len(items) == 5 # 不删 + # The Plant Cell 审稿约 6 周 > 5 周 → 带 ⚠ 提示 + pc = next(it for it in items if it["id"] == "plant-cell") + assert "超出你 5 周" in pc["risk_note"] + + +def test_seed_idempotent(tmp_path): + """种子装载幂等:连跑两次仍恰好 5 行,且不编造 acceptance_rate。""" + + async def work(): + await db_mod.init_db(tmp_path / "seed.db") + try: + await db_mod.ensure_journals_seeded() + await db_mod.ensure_journals_seeded() + return await db_mod.list_journals() + finally: + await db_mod.close_db() + + rows = asyncio.run(work()) + assert len(rows) == 5 + assert {r["id"] for r in rows} == { + "plant-cell", "genome-biology", "plant-journal", + "theoretical-applied-genetics", "plant-genome", + } + assert all(r["acceptance_rate"] is None for r in rows) + assert all(r["scope_desc"] for r in rows) + assert all(r["official_url"] for r in rows) + + +def test_rule_fallback_covers_all_tiers(): + """纯规则分档覆盖三档(不依赖 LLM 与网络)。""" + candidates = [ + {"journal": {"id": "plant-cell", "impact_factor": 11.6, "review_time_weeks": 6.0}, "similarity": None}, + {"journal": {"id": "plant-journal", "impact_factor": 7.2, "review_time_weeks": 5.0}, "similarity": None}, + {"journal": {"id": "plant-genome", "impact_factor": 3.3, "review_time_weeks": 4.0}, "similarity": None}, + ] + rankings = journal_rank.fallback_rankings(candidates) + assert {r.journal_id for r in rankings} == {"plant-cell", "plant-journal", "plant-genome"} + by_id = {r.journal_id: r.tier for r in rankings} + assert by_id["plant-cell"] == "challenge" + assert by_id["plant-journal"] == "fit" + assert by_id["plant-genome"] == "safe" diff --git a/sdk/app/config.py b/sdk/app/config.py index caa9685..8a07ef1 100644 --- a/sdk/app/config.py +++ b/sdk/app/config.py @@ -81,6 +81,11 @@ class Settings(BaseSettings): paper_writer_url: str = "http://127.0.0.1:8097" paper_writer_read_timeout: float = 360.0 # write_paper_section 同步长调用读超时(秒) + # ---- 科研审稿服务(review_service 8100;REVIEW_ENABLED 为假时路由不注册)---- + review_enabled: bool = False + review_service_url: str = "http://127.0.0.1:8100" + review_read_timeout: float = 360.0 # presubmit 上传+LLM 长调用读超时(秒) + # ---- 生产形态:BFF 静态托管 ui/dist(ARCHITECTURE.md §3,M6 挂载)---- frontend_dist_dir: str = "ui/dist" # 生产形态:静态托管 ui/dist diff --git a/sdk/app/main.py b/sdk/app/main.py index d15fac9..1a5fdcd 100644 --- a/sdk/app/main.py +++ b/sdk/app/main.py @@ -26,6 +26,7 @@ from .routers import capabilities, docgen, extraction, figures, health, kg, lega from .routers import bioflow_proxy from .routers import paper from .routers import private_docs +from .routers import review_proxy from .upstream import close_client logging.basicConfig(level=logging.INFO) @@ -62,6 +63,8 @@ def create_app() -> FastAPI: app.include_router(bioflow_proxy.router) # 生信反代(BIOFLOW_ENABLED 开关,FR-BIO-028) if get_settings().paper_writer_enabled: app.include_router(paper.router) # 论文撰写(PAPER_WRITER_ENABLED 开关) + if get_settings().review_enabled: + app.include_router(review_proxy.router) # 科研审稿反代(REVIEW_ENABLED 开关) @app.exception_handler(RequestValidationError) async def _validation_handler(_: Request, exc: RequestValidationError) -> JSONResponse: diff --git a/sdk/app/routers/review_proxy.py b/sdk/app/routers/review_proxy.py new file mode 100644 index 0000000..7adbfc7 --- /dev/null +++ b/sdk/app/routers/review_proxy.py @@ -0,0 +1,85 @@ +"""routers/review_proxy.py —— BFF 科研审稿反代(REVIEW_ENABLED 条件注册)。 + +- GET /api/review/health → 探活 review 服务 /health(离线返回 offline 标记, + 前端据此隐藏审稿入口;模式同 routers/paper.py)。 +- /api/review/{path:path} → 透明反代 review_service(8100);presubmit 为 + 上传+LLM 长调用,读超时取 settings.review_read_timeout。 +- REVIEW_ENABLED 为假时路由不注册(main.py 按开关 include,三形态部署)。 + +约束:本文件是 BFF 层对审稿模块的唯一新增面(新文件,不改既有路由逻辑)。 +review_service 失败统一 503 UPSTREAM_DOWN 信封(经 app.upstream.envelope)。 +""" +from __future__ import annotations + +import logging +from typing import Any + +import httpx +from fastapi import APIRouter, Request +from fastapi.responses import JSONResponse, Response + +from ..config import get_settings +from ..upstream import envelope + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/api/review", tags=["review-proxy"]) + +PROXY_CONNECT_TIMEOUT = 5.0 + + +def _service_base() -> str: + return get_settings().review_service_url.rstrip("/") + + +@router.get("/health") +async def review_health() -> dict[str, Any]: + """探活反代 8100 /health;离线返回 offline 标记。""" + s = get_settings() + try: + async with httpx.AsyncClient(timeout=10.0) as client: + resp = await client.get(f"{s.review_service_url.rstrip('/')}/health") + resp.raise_for_status() + return resp.json() + except Exception: # noqa: BLE001 + return {"ok": False, "status": "offline"} + + +async def _proxy(request: Request, path: str) -> Any: + """httpx 透传反代(非 SSE;presubmit 长读超时);失败→503 信封。""" + s = get_settings() + base = _service_base() + url = f"{base}/api/review/{path.lstrip('/')}" + if request.url.query: + url = f"{url}?{request.url.query}" + body = await request.body() + headers = {k: v for k, v in request.headers.items() + if k.lower() not in ("host", "content-length", "connection")} + timeout = httpx.Timeout( + connect=PROXY_CONNECT_TIMEOUT, + read=s.review_read_timeout, + write=s.review_read_timeout, + pool=5.0, + ) + async with httpx.AsyncClient(timeout=timeout) as client: + try: + upstream = await client.build_request( + request.method, url, content=body, headers=headers + ) + resp = await client.send(upstream) + except httpx.HTTPError as exc: + logger.warning("review_proxy: 审稿服务不可达 %s: %s", url, exc) + payload, status = envelope( + "UPSTREAM_DOWN", message="审稿服务当前不可用,请稍后重试", + degraded=True, status=503, + ) + return JSONResponse(status_code=status, content=payload) + content = await resp.aread() + + media_type = resp.headers.get("content-type", "") or "application/json" + return Response(status_code=resp.status_code, content=content, media_type=media_type) + + +@router.api_route("/{path:path}", methods=["GET", "POST", "PUT", "PATCH", "DELETE"]) +async def proxy_all(path: str, request: Request) -> Any: + return await _proxy(request, path) -- 2.52.0 From 5a71e29cf7cfb5b253f50de39d136947b99f240c Mon Sep 17 00:00:00 2001 From: potaser Date: Sat, 10 Oct 2026 16:05:08 +0800 Subject: [PATCH 2/8] feat(edu): complete 7-panel academic assistant + journals v4 dataset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend: - review_service: presubmit / recommend / journals / journals/directory / format-check / conferences endpoints - journals.json 5 精选种子 + journal_directory 1056 条全量(v4 数据) - v4 数据集:2025 JIF(2026 JCR 发布)+ 2025 中科院分区 + 1053 条官网 URL - format_check 行距 bug 修复(基线 y + 物理过滤 + docx EMU) BFF: - review_proxy 反代(修复 httpx build_request await bug) - REVIEW_ENABLED 开关(默认关闭,零痕部署) Frontend: - 教育科研工作台(7 面板 + 菜单 + 状态管理) - TopBar 教育科研入口(v-show 覆盖层语义,RAG 会话不丢) - 期刊情报:Tab 切换 / 搜索 / 筛选 / 分页 / 官网列 / 展开凭证 - 智能推荐 / AI预审稿 / 专业报告 / 投稿台账 / 排版规范 / 会议日历 --- AGENTS.md | 54 + review_service/app/main.py | 5 +- review_service/app/routers/conferences.py | 209 ++ review_service/app/routers/format_check.py | 81 + .../app/routers/journal_directory.py | 276 +++ review_service/app/routers/journals.py | 64 +- review_service/app/services/format_check.py | 788 +++++++ review_service/data/journals/conferences.json | 493 +++++ .../data/journals/import_report.txt | 61 + review_service/data/journals/journals.json | 67 +- .../data/journals/smoke/1_default_en.json | 1903 +++++++++++++++++ .../data/journals/smoke/2_lang_zh.json | 1779 +++++++++++++++ .../data/journals/smoke/3_q_nature.json | 1716 +++++++++++++++ .../data/journals/smoke/4_partition1_en.json | 1901 ++++++++++++++++ .../data/journals/smoke/5_domain.json | 815 +++++++ .../journals/smoke/6_zh_composite_desc.json | 1779 +++++++++++++++ .../data/journals/smoke/7_size500.json | 10 + .../data/journals/smoke/8_lang_xx.json | 10 + review_service/data/journals/source.xlsx | Bin 0 -> 123252 bytes review_service/data/journals/source_v4.xlsx | Bin 0 -> 193386 bytes review_service/scripts/import_journals.py | 579 +++++ sdk/app/routers/review_proxy.py | 2 +- ui/.gitignore | 4 +- ui/postcss.config.js | 1 + ui/src/App.vue | 9 +- ui/src/api/review.js | 110 + ui/src/components/edu/EduSideNav.vue | 113 + ui/src/components/edu/EduWorkspace.vue | 60 + .../components/edu/panels/CalendarPanel.vue | 418 ++++ ui/src/components/edu/panels/FormatPanel.vue | 495 +++++ .../components/edu/panels/JournalsPanel.vue | 770 +++++++ .../components/edu/panels/PresubmitPanel.vue | 614 ++++++ .../components/edu/panels/RecommendPanel.vue | 507 +++++ ui/src/components/edu/panels/ReportPanel.vue | 420 ++++ ui/src/components/edu/panels/TrackerPanel.vue | 394 ++++ .../components/edu/panels/TrainingPanel.vue | 16 + ui/src/components/layout/TopBar.vue | 20 + ui/src/stores/app.js | 31 + ui/src/stores/edu.js | 259 +++ ui/vite.config.js | 4 +- 40 files changed, 16821 insertions(+), 16 deletions(-) create mode 100644 AGENTS.md create mode 100644 review_service/app/routers/conferences.py create mode 100644 review_service/app/routers/format_check.py create mode 100644 review_service/app/routers/journal_directory.py create mode 100644 review_service/app/services/format_check.py create mode 100644 review_service/data/journals/conferences.json create mode 100644 review_service/data/journals/import_report.txt create mode 100644 review_service/data/journals/smoke/1_default_en.json create mode 100644 review_service/data/journals/smoke/2_lang_zh.json create mode 100644 review_service/data/journals/smoke/3_q_nature.json create mode 100644 review_service/data/journals/smoke/4_partition1_en.json create mode 100644 review_service/data/journals/smoke/5_domain.json create mode 100644 review_service/data/journals/smoke/6_zh_composite_desc.json create mode 100644 review_service/data/journals/smoke/7_size500.json create mode 100644 review_service/data/journals/smoke/8_lang_xx.json create mode 100644 review_service/data/journals/source.xlsx create mode 100644 review_service/data/journals/source_v4.xlsx create mode 100644 review_service/scripts/import_journals.py create mode 100644 ui/postcss.config.js create mode 100644 ui/src/api/review.js create mode 100644 ui/src/components/edu/EduSideNav.vue create mode 100644 ui/src/components/edu/EduWorkspace.vue create mode 100644 ui/src/components/edu/panels/CalendarPanel.vue create mode 100644 ui/src/components/edu/panels/FormatPanel.vue create mode 100644 ui/src/components/edu/panels/JournalsPanel.vue create mode 100644 ui/src/components/edu/panels/PresubmitPanel.vue create mode 100644 ui/src/components/edu/panels/RecommendPanel.vue create mode 100644 ui/src/components/edu/panels/ReportPanel.vue create mode 100644 ui/src/components/edu/panels/TrackerPanel.vue create mode 100644 ui/src/components/edu/panels/TrainingPanel.vue create mode 100644 ui/src/stores/app.js create mode 100644 ui/src/stores/edu.js diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..2303d46 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,54 @@ +# AGENTS.md —— 协作约束(科研审稿模块) + +## 项目背景 + +本项目(PlantAI-rag-new)是植物基因组学文献知识工作台,拥有自研 RAG 与知识库 +(Qdrant + Neo4j + vstore)。2026-10 起新增「科研投稿与智能审稿助手」功能 +(审稿周期/期刊分析/期刊推荐/投稿前自审/审稿意见辅助/格式检查)。 + +## 审稿模块(review_service)约束 —— 必须遵守 + +1. **所有审稿相关新代码只允许写在 `review_service/` 目录下新增**。 + - 服务自身:FastAPI 独立进程,端口 8100(模式同 `paper_writer_service` 8097 / `bioflow_service` 8098)。 + - 环境变量前缀统一 `REVIEW_`;LLM 凭据复用 `DOCGEN_LLM_*` 裸键(回退链见 `review_service/app/services/llm.py`)。 +2. **BFF(`sdk/`)层只允许条件注册代理路由**: + - 允许的全部改动 = `sdk/app/config.py` 增加 `review_enabled` / `review_service_url` 等开关键 + + `sdk/app/main.py` 按开关 `include_router(review_proxy.router)` + + 新文件 `sdk/app/routers/review_proxy.py`(反代实现)。 + - **严禁**修改 sdk 下其他 router/service/db 的任何既有逻辑。 +3. **严禁修改现有 RAG 核心与既有服务代码**,包括但不限于: + - `agent/`(qa 8091 / methodology 8092 / legacy-rag 8093) + - `vstore/`(8094,审稿服务只经 HTTP 只读消费其 `/api/vstore/*` 接口) + - `paper_writer_service/`、`bioflow_service/`、`bioflow_kernel/` + - `ui/`(前端入口另行按 UI_SPEC 流程评审) + - `knowledge/`、`kb-libraries/`、`tooling/`(依赖锁另议) +4. **依赖纪律**:审稿服务只使用统一 venv(`tooling/requirements.lock`)中已有的库 + (fastapi / httpx / pydantic-settings 等)。如确需新增全局依赖, + 须先更新 `tooling/requirements.lock` 并经人工确认。 +5. **上游对接只读**:PDF 解析走 vstore 8094(`POST /api/vstore/ingest` + + `GET/DELETE /api/vstore/documents/{id}`);LLM 走 DeepSeek OpenAI 兼容接口; + 后续期刊数据/期刊推荐等子功能同样以新 service + 新路由在 `review_service/` 内扩展。 +6. **format_check 例外**:format_check 允许用 pymupdf 本地解档获取版式元数据 + (字体/边距/行距/页数),因为 vstore 只回文本不返回版式信息。正文提取仍走 vstore。 + +## 目录速览(审稿模块) + +``` +review_service/ +├── app/main.py # FastAPI 入口(/health + 挂载业务路由) +├── app/config.py # pydantic-settings(REVIEW_ 前缀) +├── app/routers/presubmit.py # POST /api/review/presubmit(自审稿报告) +├── app/routers/format_check.py # POST /api/review/format-check(版式与规范检查) +├── app/services/llm.py # DeepSeek httpx 封装(complete_text/complete_json) +├── app/services/paper_parse.py # PDF → 纯文本(经 vstore 解析接口) +├── app/services/format_check.py# 版式规则引擎(pymupdf/docx 本地解档 + 规则检查) +├── restart.sh # 8100 重启脚本 +└── pytest.ini +``` + +## 启动 + +```bash +cd review_service && bash restart.sh # 默认 8100,venv 从 ../plantai-rag-new-venv 推导 +# BFF 开关:sdk/.env 加 REVIEW_ENABLED=1 后 bff_restart(反代 /api/review/*) +``` diff --git a/review_service/app/main.py b/review_service/app/main.py index 1611e90..763340e 100644 --- a/review_service/app/main.py +++ b/review_service/app/main.py @@ -15,7 +15,7 @@ from fastapi.middleware.cors import CORSMiddleware from .config import get_settings from .db import close_db, init_db -from .routers import journals, presubmit +from .routers import conferences, format_check, journal_directory, journals, presubmit logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) @@ -65,6 +65,9 @@ def create_app() -> FastAPI: app.include_router(presubmit.router) app.include_router(journals.router) + app.include_router(format_check.router) + app.include_router(conferences.router) + app.include_router(journal_directory.router) return app diff --git a/review_service/app/routers/conferences.py b/review_service/app/routers/conferences.py new file mode 100644 index 0000000..fb81b4b --- /dev/null +++ b/review_service/app/routers/conferences.py @@ -0,0 +1,209 @@ +"""routers/conferences.py —— 会议投稿时间线(只读静态种子)。 + +- GET /api/review/conferences?domain=&ccf=&upcoming_days=180 + data/journals/conferences.json → 过滤/排序 → 列表 + meta。 +- 数据诚实性铁律:每条会议必须带 deadline_source ∈ {placeholder, official}、 + last_verified 与 deadline_confidence ∈ {high, medium, low},缺失/非法条目加载时 + 跳过并记日志(宁缺毋造);本端点无任何生成日期的逻辑,日期只来自种子常量。 + v2 共 27/27 全 placeholder,meta.data_source_note 显式声明占位与置信度, + 由前端渲染「⚠ 日期待核验」及置信度提示。 +- 过滤语义:domain 对 domain_tags 精确匹配(大小写不敏感);ccf ∈ {A,B,C}; + upcoming_days=0 不过滤,>0 仅保留 deadline_full_paper ∈ [UTC now, now+N 天], + 缺失/不可解析截稿日期在过滤开启时排除。排序:deadline_full_paper 升序, + 缺失/不可解析恒排最后。 +- 只读无写接口;文件不可读 → ok=false + DATA_UNAVAILABLE 信封;参数非法 → + VALIDATION 信封(均 HTTP 200,对齐本服务"错误信封永远 200"约定)。 +- 静态文件首次请求加载进内存(lru_cache),进程内 O(1);不触碰 SQLite/BFF。 +""" +from __future__ import annotations + +import json +import logging +from datetime import datetime, timedelta, timezone +from functools import lru_cache +from pathlib import Path +from typing import Any + +from fastapi import APIRouter +from pydantic import BaseModel + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/api/review", tags=["review-conferences"]) + +# review_service/app/routers/ → parents[2] = review_service(对齐 format_check 写法) +_CONFERENCES_PATH = ( + Path(__file__).resolve().parents[2] / "data" / "journals" / "conferences.json" +) + +_CCF_OK = frozenset({"A", "B", "C"}) +_REQUIRED = ("id", "name", "deadline_source", "last_verified", "deadline_confidence") +_CONFIDENCE_OK = frozenset({"high", "medium", "low"}) +_SOURCE_NOTE = ( + "会议截稿/通知日期首版均为占位数据(deadline_source=placeholder)," + "接入官方渠道前须人工核验;deadline_confidence 标注日期置信度" + "(high=官方已公布/历年极稳定,medium=按历年规律推算,low=待核验);" + "所有时间按 AoE (UTC-12) 时区。" +) + + +# ---- 请求/响应模型 ---- + +class ConferenceItem(BaseModel): + """会议公开字段(种子全字段白名单;未知键丢弃)。""" + id: str + name: str + full_name: str = "" + domain_tags: list[str] = [] + application_tags: list[str] = [] + ccf_rank: str | None = None + deadline_abstract: str | None = None + deadline_full_paper: str | None = None + notification_date: str | None = None + conference_date: str | None = None + location: str | None = None + official_url: str | None = None + timezone_note: str | None = None + deadline_source: str + last_verified: str + deadline_confidence: str = "" + + +class ConferencesResponse(BaseModel): + ok: bool + items: list[ConferenceItem] = [] + meta: dict[str, Any] | None = None + error: dict[str, Any] | None = None + + +def _error(code: str, message: str) -> ConferencesResponse: + return ConferencesResponse( + ok=False, items=[], meta=None, + error={"code": code, "message": message, "degraded": False}, + ) + + +# ---- 种子加载(首次调用读盘,进程内缓存)---- + +@lru_cache(maxsize=1) +def _load_conferences() -> list[dict[str, Any]] | None: + """读 conferences.json → 合法会议列表;文件不可读 → None(DATA_UNAVAILABLE)。""" + try: + payload = json.loads(_CONFERENCES_PATH.read_text("utf-8")) + except (OSError, ValueError) as exc: + logger.warning("conferences: 种子文件不可读 %s: %s", _CONFERENCES_PATH, exc) + return None + raw = payload.get("conferences") if isinstance(payload, dict) else None + if not isinstance(raw, list): + logger.warning("conferences: 种子缺少 conferences 数组:%s", _CONFERENCES_PATH) + return None + items: list[dict[str, Any]] = [] + for conf in raw: + if not isinstance(conf, dict): + continue + missing = [k for k in _REQUIRED if not conf.get(k)] + if missing: + logger.warning("conferences: 条目缺字段 %s(id=%s),跳过", missing, conf.get("id")) + continue + if conf.get("deadline_source") not in ("placeholder", "official"): + logger.warning( + "conferences: deadline_source 非法(id=%s),跳过", conf.get("id") + ) + continue + if str(conf.get("deadline_confidence") or "").strip().lower() not in _CONFIDENCE_OK: + logger.warning( + "conferences: deadline_confidence 非法(id=%s),跳过", conf.get("id") + ) + continue + items.append(conf) + return items + + +def _parse_deadline(value: Any) -> datetime | None: + """截稿时间 → aware datetime(naive 视为 UTC);非法 → None。""" + if not isinstance(value, str) or not value.strip(): + return None + try: + dt = datetime.fromisoformat(value.strip()) + except ValueError: + return None + return dt.replace(tzinfo=timezone.utc) if dt.tzinfo is None else dt + + +# ---- GET /api/review/conferences ---- + +@router.get("/conferences", response_model=ConferencesResponse) +async def conferences_list( + domain: str = "", + ccf: str = "", + upcoming_days: int = 180, +) -> ConferencesResponse: + """只读:会议投稿时间线(无写/删/改接口)。 + + - ?domain= 对 domain_tags 精确匹配(大小写不敏感),空=不过滤; + - ?ccf= ccf_rank ∈ A/B/C,空=不过滤,非法值 → VALIDATION 信封; + - ?upcoming_days= int≥0,默认 180;0=不过滤,>0 仅保留截稿在 + [UTC now, now+N 天] 内的会议,负数 → VALIDATION 信封; + - 排序按 deadline_full_paper 升序,缺失/不可解析恒排最后; + - 空结果 → items=[] + meta.count=0(HTTP 200,不报错)。 + """ + ccf_norm = (ccf or "").strip().upper() + if ccf_norm and ccf_norm not in _CCF_OK: + return _error("VALIDATION", f"不支持的 ccf={ccf!r},可选:A / B / C") + if upcoming_days < 0: + return _error( + "VALIDATION", f"upcoming_days 必须 ≥ 0,收到 {upcoming_days}" + ) + + all_items = _load_conferences() + if all_items is None: + return _error("DATA_UNAVAILABLE", "会议种子数据不可读,请联系管理员") + + items = list(all_items) + + dom = (domain or "").strip().casefold() + if dom: + items = [ + c for c in items + if any( + str(t).strip().casefold() == dom + for t in (c.get("domain_tags") or []) + ) + ] + if ccf_norm: + items = [ + c for c in items + if str(c.get("ccf_rank") or "").strip().upper() == ccf_norm + ] + if upcoming_days > 0: + now = datetime.now(timezone.utc) + limit = now + timedelta(days=upcoming_days) + items = [ + c for c in items + if (dl := _parse_deadline(c.get("deadline_full_paper"))) is not None + and now <= dl <= limit + ] + + def _sort_key(c: dict[str, Any]) -> tuple[bool, datetime]: + dl = _parse_deadline(c.get("deadline_full_paper")) + if dl is None: + return (True, datetime.max.replace(tzinfo=timezone.utc)) + return (False, dl) + + items.sort(key=_sort_key) + + out = [ConferenceItem(**c) for c in items] + verified = max( + (str(c.get("last_verified") or "") for c in all_items), default="" + ) + meta: dict[str, Any] = { + "count": len(out), + "last_verified": verified or None, + "data_source_note": _SOURCE_NOTE, + "query": { + "domain": (domain or "").strip(), + "ccf": ccf_norm, + "upcoming_days": upcoming_days, + }, + } + return ConferencesResponse(ok=True, items=out, meta=meta, error=None) diff --git a/review_service/app/routers/format_check.py b/review_service/app/routers/format_check.py new file mode 100644 index 0000000..e6a467e --- /dev/null +++ b/review_service/app/routers/format_check.py @@ -0,0 +1,81 @@ +"""routers/format_check.py —— 版式与规范检查(POST /api/review/format-check)。 + +纯规则引擎(services/format_check.py):PDF/Word 本地解档取版式元数据 + +journals.json 规则集(format_rules_default + 每条 format_rules 带 rules_source)。 +无 LLM / 无 vstore,同步执行通常 <1s;恒 200 + {ok, checks, summary, meta|error} 信封。 +""" +from __future__ import annotations + +import logging + +from fastapi import APIRouter, File, Form, UploadFile +from pydantic import BaseModel + +from ..config import get_settings +from ..services import format_check + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/api/review", tags=["review-format"]) + + +class CheckItem(BaseModel): + key: str + name: str + status: str # pass | warn | fail + detail: str + suggestion: str = "" + + +class FormatCheckResponse(BaseModel): + ok: bool + checks: list[CheckItem] | None = None + summary: dict[str, int] | None = None + meta: dict[str, object] | None = None + error: dict[str, object] | None = None + + +def _error(code: str, message: str, *, degraded: bool = False) -> FormatCheckResponse: + return FormatCheckResponse( + ok=False, error={"code": code, "message": message, "degraded": degraded}, + ) + + +@router.post("/format-check", response_model=FormatCheckResponse) +async def format_check_endpoint( + file: UploadFile = File(..., description="待检查的 PDF / Word(.docx) / LaTeX(.tex) 文档"), + target_journal: str = Form("", description="目标期刊(可选,传 journals 的 id)"), +) -> FormatCheckResponse: + settings = get_settings() + + filename = file.filename or "" + low = filename.lower() + if low.endswith(".pdf"): + kind = "pdf" + elif low.endswith(".docx"): + kind = "docx" + elif low.endswith(".tex"): + kind = "tex" + else: + return _error("VALIDATION", "仅支持 PDF / Word(.docx)/ LaTeX(.tex)文件") + + content = await file.read() + if not content: + return _error("VALIDATION", "上传文件为空") + if len(content) > settings.max_pdf_bytes: + return _error("VALIDATION", "上传文件超过 50MB 上限") + + try: + result = format_check.check_document(content, kind, (target_journal or "").strip()) + except format_check.FormatCheckError as exc: + logger.warning("format-check: 解档失败:%s", exc) + return _error("PARSE_FAILED", str(exc)) + + meta = dict(result.get("meta") or {}) + meta["filename"] = filename + return FormatCheckResponse( + ok=True, + checks=[CheckItem(**c) for c in result["checks"]], + summary=result["summary"], + meta=meta, + ) diff --git a/review_service/app/routers/journal_directory.py b/review_service/app/routers/journal_directory.py new file mode 100644 index 0000000..b92b60d --- /dev/null +++ b/review_service/app/routers/journal_directory.py @@ -0,0 +1,276 @@ +"""routers/journal_directory.py —— 期刊目录浏览(1056 本,只读分页)。 + +- GET /api/review/journals/directory:journal_directory 表(scripts/import_journals.py + 导入的 v4 目录:2025 中科院分区 + 2025 JIF(2026 年 JCR 发布)+ 年报 2025 版 + (中文统计年 2024)+ 官网网址/核对状态)→ 过滤/排序/分页 → 列表 + meta。 +- 与 GET /journals(journals.json 精选 5 本,供 FormatPanel 下拉/recommend 语义)物理 + 分离(方案 A);本端点绝不读写 journals 表,recommend/journal_kb/journal_rank 零触碰。 +- 读路径只 SELECT;表由导入脚本拥有(db.py 零改动);表不存在 → data_imported=false + 优雅降级(HTTP 200 空列表)。 + +读时归一化(拍板细节 1-3,均在 API 层做,不动脚本/DB 原值): + 细节1 lang=zh → cas_partition 恒 null + cas_partition_note="不按中科院分区口径列示"; + 细节2 jif_note 源文本映射(v4 值域已是用户可读文本,旧值映射保留兜底); + 细节3 缺值即矛盾清零:en 且 jif=null → jif_source_url=null; + cas_partition=null → partition_source_url=null。 + (zh 的 IF 载体是 composite/comprehensive,其 jif_source_url 本恒 null。) + 决策2:响应不再下发"来源"文本字段(partition_source/jif_source/data_source_label + 已从 DirectoryItem 移除;jif_source_url/partition_source_url/data_source_url + 保留,供前端展开行链接)。新增 official_check_status / jcr_release_year。 +""" +from __future__ import annotations + +import json +import logging +import sqlite3 +from typing import Any + +from fastapi import APIRouter +from pydantic import BaseModel + +from ..db import db + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/api/review", tags=["review-directory"]) + +_LANGS = frozenset({"en", "zh"}) +# 排序列白名单(列名不可参数化 → 白名单防注入) +_FIELDS = frozenset({ + "name", + "jif", + "composite_impact_factor", + "comprehensive_impact_factor", + "research_direction", + "cas_partition", +}) +_ORDERS = frozenset({"asc", "desc"}) +_PARTS = {"1": "1区", "2": "2区", "3": "3区", "4": "4区"} +_MAX_SIZE = 200 + +# 细节2:源核对状态 → 用户可读 note +_JIF_NOTE_MAP = { + "源表标N/A": "未被2024 JCR收录", + "所用年度来源未检得": "本次汇编未查到,建议查阅最新 JCR", +} +_ZH_PART_NOTE = "不按中科院分区口径列示" + +_NOTE_EN = ( + "分区:2025年中科院公开表(多表比对,2026年起停止更新);" + "JIF:2025年度指标(2026年JCR发布,两份公开汇编一致或已核对出版社官方指标);" + "整理日期2026-10-10。空白=来源未给值≠0;研究方向/期刊标记/文章类型为导航标签,非官方评级。" +) +_NOTE_ZH = ( + "指标:国内自然科学期刊年报2025版(统计年2024,official,含复合/综合IF两口径);" + "中文期刊不按中科院分区口径列示;国内IF与JIF统计源不同,不可混排。" +) +_UNIMPORTED_NOTE = "目录数据未导入(请先运行 scripts/import_journals.py)" + + +# ---- 响应模型 ---- + +class DirectoryItem(BaseModel): + """目录公开字段(DB 全列白名单;imported_at 等内部列丢弃)。""" + id: str + lang: str + name: str + research_direction: str | None = None + cas_partition: str | None = None + cas_partition_note: str | None = None + cas_partition_year: int | None = None + jif: float | None = None + jif_year: int | None = None + jif_note: str | None = None + jif_check_status: str | None = None + composite_impact_factor: float | None = None + comprehensive_impact_factor: float | None = None + metric_year: int | None = None + metric_report_year: int | None = None + metric_caliber: str | None = None + annual_report_page: int | None = None + top_flag: str | None = None + publisher_series: str | None = None + journal_mark: str | None = None + article_type: str | None = None + issn: str | None = None + eissn: str | None = None + jcr_disciplines: list[str] = [] + supplement_note: str | None = None + evidence_note: str | None = None + official_url: str | None = None + official_check_status: str | None = None + jcr_release_year: int | None = None + jif_source_url: str | None = None + partition_source_url: str | None = None + data_source_url: str | None = None + + +class DirectoryResponse(BaseModel): + ok: bool + items: list[DirectoryItem] = [] + meta: dict[str, Any] | None = None + error: dict[str, Any] | None = None + + +def _error(code: str, message: str) -> DirectoryResponse: + return DirectoryResponse( + ok=False, items=[], meta=None, + error={"code": code, "message": message, "degraded": False}, + ) + + +# ---- 读时归一化(拍板细节 1-3)---- + +def _present(raw: dict[str, Any], lang: str) -> dict[str, Any]: + d = dict(raw) + # jcr_disciplines:JSON 数组字符串 → list + jcr = d.get("jcr_disciplines") + if jcr: + try: + parsed = json.loads(jcr) + d["jcr_disciplines"] = parsed if isinstance(parsed, list) else [] + except (TypeError, ValueError): + d["jcr_disciplines"] = [] + else: + d["jcr_disciplines"] = [] + + # 细节2:jif_note 源文本 → 用户可读 + note = d.get("jif_note") + if note in _JIF_NOTE_MAP: + d["jif_note"] = _JIF_NOTE_MAP[note] + + # 细节1:zh 分区归一(DB 原值"不按此口径列示"只留在库里) + if lang == "zh": + d["cas_partition"] = None + d["cas_partition_note"] = _ZH_PART_NOTE + + # 细节3:缺值 → 来源链接清零(消除 null 值却挂来源链接的矛盾; + # "来源"文本字段已按决策2 移出响应,此处只清 *_url) + if lang == "en": + if d.get("jif") is None: + d["jif_source_url"] = None + if d.get("cas_partition") is None: + d["partition_source_url"] = None + return d + + +def _escape_like(s: str) -> str: + return s.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_") + + +# ---- GET /api/review/journals/directory ---- + +@router.get("/journals/directory", response_model=DirectoryResponse) +async def journals_directory( + lang: str = "en", + domain: str = "", + cas_partition: str = "", + q: str = "", + page: int = 1, + size: int = 50, + field: str = "", + order: str = "", +) -> DirectoryResponse: + """只读:期刊目录分页浏览(无写接口)。 + + - ?lang=en|zh(默认 en;**强制单语,保证国际/中文永不混排**); + - ?domain= 研究方向精确匹配;?cas_partition=1|2|3|4(仅 lang=en,zh 忽略); + - ?q= 期刊名模糊(ASCII 大小写不敏感);?page≥1 ?size 1-200(默认 50); + - ?field= 排序白名单(name/jif/composite_impact_factor/ + comprehensive_impact_factor/research_direction/cas_partition),?order=asc|desc; + 未传 field → 默认排序 en=jif 降序 / zh=复合IF 降序(NULL 恒排最后); + - 参数非法 → VALIDATION 信封;表不存在 → data_imported=false 空列表(HTTP 200)。 + """ + lang_n = (lang or "").strip().lower() + if lang_n not in _LANGS: + return _error("VALIDATION", f"不支持的 lang={lang!r},可选:en / zh") + if page < 1: + return _error("VALIDATION", f"page 必须 ≥ 1,收到 {page}") + if size < 1 or size > _MAX_SIZE: + return _error("VALIDATION", f"size 必须在 1-{_MAX_SIZE},收到 {size}") + field_n = (field or "").strip() + if field_n and field_n not in _FIELDS: + return _error( + "VALIDATION", + f"不支持的 field={field!r},可选:{', '.join(sorted(_FIELDS))}", + ) + order_n = (order or "").strip().lower() + if order_n and order_n not in _ORDERS: + return _error("VALIDATION", f"不支持的 order={order!r},可选:asc / desc") + part_q = (cas_partition or "").strip() + if part_q: + part_q = _PARTS.get(part_q, _PARTS.get(part_q.rstrip("区").strip(), "")) + if not part_q: + return _error( + "VALIDATION", + f"不支持的 cas_partition={cas_partition!r},可选:1 / 2 / 3 / 4", + ) + + # 过滤条件(白名单拼接;参数全部占位符) + where = ["lang = ?"] + params: list[Any] = [lang_n] + domain_n = (domain or "").strip() + if domain_n: + where.append("research_direction = ?") + params.append(domain_n) + if part_q and lang_n == "en": # zh 不分区:忽略(meta 回显) + where.append("cas_partition = ?") + params.append(part_q) + q_n = (q or "").strip() + if q_n: + where.append("name LIKE ? ESCAPE '\\'") + params.append(f"%{_escape_like(q_n)}%") + where_sql = " AND ".join(where) + + # 排序(列名出自白名单;NULL 恒排最后) + if field_n: + dir_sql = "DESC" if order_n == "desc" else "ASC" + order_sql = f"{field_n} IS NULL, {field_n} {dir_sql}" + else: + col = "jif" if lang_n == "en" else "composite_impact_factor" + order_sql = f"{col} IS NULL, {col} DESC" + + try: + total_row = await db.fetchone( + f"SELECT COUNT(*) AS c FROM journal_directory WHERE {where_sql}", params # noqa: S608 + ) + total = int(total_row["c"]) if total_row else 0 + rows = await db.fetchall( + f"SELECT * FROM journal_directory WHERE {where_sql} " # noqa: S608 + f"ORDER BY {order_sql} LIMIT ? OFFSET ?", + [*params, size, (page - 1) * size], + ) + dom_rows = await db.fetchall( + "SELECT research_direction AS d, COUNT(*) AS c FROM journal_directory " + "WHERE lang = ? AND research_direction IS NOT NULL " + "GROUP BY 1 ORDER BY c DESC, d ASC", + [lang_n], + ) + except sqlite3.OperationalError as exc: + # 表不存在(脚本未跑)→ 优雅降级,HTTP 200 + logger.warning("journal_directory: 表不可用(目录未导入?): %s", exc) + return DirectoryResponse( + ok=True, items=[], + meta={ + "total": 0, "page": page, "size": size, "lang": lang_n, + "domain": domain_n, "cas_partition": part_q, "q": q_n, + "domains": [], "data_source_note": _UNIMPORTED_NOTE, + "data_imported": False, + }, + error=None, + ) + + items = [DirectoryItem(**_present(dict(r), lang_n)) for r in rows] + meta: dict[str, Any] = { + "total": total, + "page": page, + "size": size, + "lang": lang_n, + "domain": domain_n, + "cas_partition": part_q if lang_n == "en" else "", + "q": q_n, + "domains": [r["d"] for r in dom_rows if r["d"]], + "data_source_note": _NOTE_EN if lang_n == "en" else _NOTE_ZH, + "data_imported": True, + } + return DirectoryResponse(ok=True, items=items, meta=meta, error=None) diff --git a/review_service/app/routers/journals.py b/review_service/app/routers/journals.py index ad294fe..16d3036 100644 --- a/review_service/app/routers/journals.py +++ b/review_service/app/routers/journals.py @@ -13,7 +13,10 @@ VALIDATION 错误信封(HTTP 200,与本服务其余端点一致)。 """ from __future__ import annotations +import json import logging +from functools import lru_cache +from pathlib import Path from typing import Any, Literal from fastapi import APIRouter @@ -69,7 +72,11 @@ class RecommendResponse(BaseModel): # ---- GET /api/review/journals(只读列表)---- class JournalBrief(BaseModel): - """期刊公开字段(journals 表全列;不含 vstore_doc_id 内部映射)。""" + """期刊公开字段(journals 表全列;不含 vstore_doc_id 内部映射)。 + + 标签/分区 6 字段不进 SQLite:GET 时按 id 从 journals.json 内存缓存合并; + JSON 缺该 id → 空数组/null 默认值。 + """ id: str name: str scope_desc: str = "" @@ -79,6 +86,12 @@ class JournalBrief(BaseModel): submission_deadline: str | None = None official_url: str | None = None last_updated: str = "" + scope_tags: list[str] = [] + application_tags: list[str] = [] + cas_partition: str | None = None + jcr_quartile: str | None = None + partition_source: str | None = None + cross_domain: list[str] = [] class JournalsListResponse(BaseModel): @@ -99,8 +112,55 @@ _SORT_FIELDS = frozenset({ }) _DATA_SOURCE_NOTE = ( "IF/审稿周期为公开近似值,acceptance_rate 为 null 表示暂无公开数据,需人工核验。" + "CAS/JCR 分区为首版占位数据,需核验。" ) +# journals.json 新增字段(标签/分区;刻意不进 SQLite,见 C-2 方案) +_TAG_FIELDS = ( + "scope_tags", + "application_tags", + "cas_partition", + "jcr_quartile", + "partition_source", + "cross_domain", +) + + +@lru_cache(maxsize=1) +def _load_tag_extras() -> dict[str, dict[str, Any]]: + """journals.json 标签/分区字段 → {id: {6 新字段}}。 + + 首次请求读盘后进程内缓存,后续 GET O(1) 按 id 合并(不做每请求磁盘 IO)。 + JSON 缺该 id → 合并时用空数组/null 默认;文件不可读 → 空 dict 降级(不 500)。 + """ + seed = get_settings().journals_seed_abs + try: + payload = json.loads(Path(seed).read_text("utf-8")) + except (OSError, ValueError) as exc: + logger.warning("journals: 标签扩展文件不可读,合并降级为默认值:%s", exc) + return {} + raw = payload.get("journals") if isinstance(payload, dict) else None + if not isinstance(raw, list): + return {} + out: dict[str, dict[str, Any]] = {} + for j in raw: + if isinstance(j, dict) and j.get("id"): + out[str(j["id"])] = {k: j.get(k) for k in _TAG_FIELDS} + return out + + +def _tag_fields(extra: dict[str, Any] | None) -> dict[str, Any]: + """缓存条目 → JournalBrief 关键字参数(JSON 缺该 id → 空数组/null 默认)。""" + ex = extra or {} + return { + "scope_tags": list(ex.get("scope_tags") or []), + "application_tags": list(ex.get("application_tags") or []), + "cas_partition": ex.get("cas_partition"), + "jcr_quartile": ex.get("jcr_quartile"), + "partition_source": ex.get("partition_source"), + "cross_domain": list(ex.get("cross_domain") or []), + } + def _sort_rows(rows: list[dict[str, Any]], field: str, order: str) -> list[dict[str, Any]]: """按白名单字段排序;NULL 恒排最后;次序不稳定时按 db 默认序(稳定排序保留)。""" @@ -142,6 +202,7 @@ async def journals_list( rows = await list_journals() rows = _sort_rows(rows, col, ord_norm) + tag_extras = _load_tag_extras() items = [ JournalBrief( id=str(r.get("id") or ""), @@ -153,6 +214,7 @@ async def journals_list( submission_deadline=r.get("submission_deadline"), official_url=r.get("official_url"), last_updated=str(r.get("last_updated") or ""), + **_tag_fields(tag_extras.get(str(r.get("id") or ""))), ) for r in rows ] diff --git a/review_service/app/services/format_check.py b/review_service/app/services/format_check.py new file mode 100644 index 0000000..a14070a --- /dev/null +++ b/review_service/app/services/format_check.py @@ -0,0 +1,788 @@ +"""services/format_check.py —— 版式与规范规则引擎(⑤ 论文排版与规范)。 + +纯规则、无 LLM、无 vstore、同步执行(通常 <1s): +- PDF → pymupdf 本地解档(AGENTS.md 约束 6 例外:vstore 只回文本,字体/边距/ + 行距/页数等版式元数据拿不到;正文提取仍走 vstore,本服务不碰正文语义); +- Word → python-docx(页边距/行距精确,页数取 docProps/app.xml 的 ); +- 规则集 → data/journals/journals.json: + 顶层 format_rules_default(通用默认值,rules_source="default") + 每条目可选 format_rules(按期刊覆盖,必须带 rules_source: placeholder|official|default) + ⚠ 诚实原则:不知道期刊真实投稿指南 → 该条只写 {"rules_source": "placeholder"}, + 所有具体数字回退 default 通用值,绝不编造期刊专属数字。 + +输出:{checks[{name,key,status,detail,suggestion}], summary{pass,warn,fail}, meta{...}} +status ∈ pass|warn|fail。参考文献样式宽容化:仅"明确不符"(如 [J] 标引但规则要求 APA) +才 fail,"疑似但不确定/检测不到"一律 warn,避免误伤。 +""" +from __future__ import annotations + +import io +import json +import re +import statistics +import zipfile +from pathlib import Path +from typing import Any + +import fitz # pymupdf(venv 已装 1.28.x) +from docx import Document +from docx.shared import Length + +# review_service/app/services/ → parents[2] = review_service +_JOURNALS_PATH = Path(__file__).resolve().parents[2] / "data" / "journals" / "journals.json" + +_MAX_SCAN_PAGES = 80 # 版式扫描页数上限(正文/字体/边距;稿件通常远小于此) +_MAX_REFS_SCAN = 40 # 从文末向前找参考文献标题的页数窗口 +_MAX_PARAS = 8000 # docx 段落扫描上限 +_PT_TO_MM = 25.4 / 72.0 +_EMU_TO_MM = 1.0 / 36000.0 + +_HEADING_RE = re.compile( + r"^\s*(references|bibliography|literature cited|works cited|参考文献|文献)\s*[::]?\s*$", + re.IGNORECASE, +) +_FIG_RE = re.compile(r"(?im)^\s*(figure|fig\.?|图)\s*\d+") +_TAB_RE = re.compile(r"(?im)^\s*(table|表)\s*\d+") +_GB_TAG_RE = re.compile(r"\[[A-Z]{1,3}\d*\]") # [J] [M] [D] [C] …(GB/T 7714 标引) +_PAREN_YEAR_RE = re.compile(r"\((?:19|20)\d{2}\)") # (2024) 作者-年份制 +_BRACKET_NUM_RE = re.compile(r"^\[\d+\]") # [1] 编号制 +_DOI_RE = re.compile(r"doi:?\.?org|doi:\s*1\.", re.IGNORECASE) + +_STYLE_LABEL = { + "gb7714": "GB/T 7714", + "author_year": "作者-年份制(类 APA)", + "numbered": "编号制(顺序编码)", + "unknown": "无法确定", +} + + +class FormatCheckError(Exception): + """解档/规则加载失败(路由器转 PARSE_FAILED)。""" + + +# ---------------------------------------------------------------- 规则集加载 + +def load_ruleset(target_journal: str) -> tuple[dict[str, Any], dict[str, Any]]: + """返回 (rules, ruleset_meta)。target_journal 传 id 或 name 均可;未知 → default。""" + try: + data = json.loads(_JOURNALS_PATH.read_text("utf-8")) + except Exception as exc: # noqa: BLE001 + raise FormatCheckError(f"规则集加载失败:{exc}") from exc + + default = data.get("format_rules_default") or {} + jid = (target_journal or "").strip() + entry = None + if jid: + for j in data.get("journals") or []: + if j.get("id") == jid or j.get("name") == jid: + entry = j + break + + if entry is None: + rules = dict(default) + meta = { + "journal_id": None, + "journal_name": None, + "ruleset_source": "default", + "rules_source": str(default.get("rules_source", "default")), + } + else: + journal_rules = entry.get("format_rules") or {} + rules = {**default, **journal_rules} + meta = { + "journal_id": entry.get("id"), + "journal_name": entry.get("name"), + "ruleset_source": "journal", + # 占位规则(无官方核验)→ 前端黄字提示 + "rules_source": str(journal_rules.get("rules_source", "placeholder")), + } + rules.setdefault("rules_source", "default") + return rules, meta + + +# ---------------------------------------------------------------- PDF 解档(pymupdf) + +def _norm_font(name: str) -> str: + n = (name or "").split("+")[-1].strip() + return n or "unknown" + + +def extract_profile_pdf(data: bytes) -> dict[str, Any]: + try: + doc = fitz.open(stream=data, filetype="pdf") + except Exception as exc: # noqa: BLE001 + raise FormatCheckError(f"PDF 解档失败:{exc}") from exc + if getattr(doc, "needs_pass", False): + doc.close() + raise FormatCheckError("PDF 已加密,无法解析") + + pages_total = doc.page_count + scan = min(pages_total, _MAX_SCAN_PAGES) + margin_rows: list[tuple[float, float, float, float]] = [] # t r b l (mm) + font_w: dict[str, int] = {} + size_w: dict[float, int] = {} + ratios: list[float] = [] + img_ids: set[int] = set() + fig_caps = tab_caps = 0 + + for pno in range(scan): + page = doc[pno] + rect = page.rect + blocks = page.get_text("blocks") + content = [b for b in blocks if b[4].strip()] + if content: + left = min(b[0] for b in content) + top = min(b[1] for b in content) + right = rect.width - max(b[2] for b in content) + bottom = rect.height - max(b[3] for b in content) + margin_rows.append( + ( + max(0.0, top) * _PT_TO_MM, + max(0.0, right) * _PT_TO_MM, + max(0.0, bottom) * _PT_TO_MM, + max(0.0, left) * _PT_TO_MM, + ) + ) + + for img in page.get_images(full=True): + img_ids.add(img[0]) + + text = page.get_text() + fig_caps += len(_FIG_RE.findall(text)) + tab_caps += len(_TAB_RE.findall(text)) + + d = page.get_text("dict") + for block in d.get("blocks", []): + if block.get("type") != 0: + continue + line_meta: list[tuple[float, float]] = [] # (基线 y, 字号) + for line in block.get("lines", []): + spans = [s for s in line.get("spans", []) if s.get("text", "").strip()] + if not spans: + continue + row_size = max(s.get("size", 0.0) for s in spans) + if row_size <= 0: + continue + for s in spans: + size = round(float(s.get("size", 0.0)), 1) + chars = len(s.get("text", "")) + if size > 0: + norm = _norm_font(s.get("font", "")) + font_w[norm] = font_w.get(norm, 0) + chars + size_w[size] = size_w.get(size, 0) + chars + # 行距基准用 span.origin 基线 y,不用 bbox 顶缘:bbox 顶随字形高低 + # 漂移,表格/图注等同基线并列文本会产出假性小 delta,混入中位数会把 + # 行距拉成 0.1x 的不可能值。 + origin = spans[0].get("origin") + line_meta.append((origin[1] if origin else line["bbox"][1], row_size)) + for i in range(1, len(line_meta)): + delta = line_meta[i][0] - line_meta[i - 1][0] + size = line_meta[i][1] + # 行距倍数 = 相邻行基线 y 差 / 当前行字号; + # 过滤物理不可能值:<0.5(行重叠/同基线并列表格)、>4.0(异常结构) + ratio = delta / size + if 0.5 <= ratio <= 4.0: + ratios.append(ratio) + + refs_text, refs_found = _find_refs_pdf(doc, pages_total) + doc.close() + + if margin_rows: + med = [statistics.median(col) for col in zip(*margin_rows)] + margins = {"top": med[0], "right": med[1], "bottom": med[2], "left": med[3]} + else: + margins = None + + return { + "source_kind": "pdf", + "pages": pages_total, + "margins_mm": margins, + "font_weights": font_w, + "size_weights": size_w, + "line_spacing_median": statistics.median(ratios) if ratios else None, + "figures": max(len(img_ids), fig_caps), + "tables": tab_caps, + "refs_text": refs_text, + "refs_found": refs_found, + } + + +def _find_refs_pdf(doc: "fitz.Document", pages_total: int) -> tuple[str | None, bool]: + """从文末向前找参考文献标题行;找到 → 标题行至文末文本;找不到 → (None, False)。""" + buf: list[str] = [] + start = max(0, pages_total - _MAX_REFS_SCAN) + for pno in range(pages_total - 1, start - 1, -1): + page_text = doc[pno].get_text() + lines = page_text.splitlines() + for idx in range(len(lines) - 1, -1, -1): + if _HEADING_RE.match(lines[idx].strip()): + tail = "\n".join(lines[idx + 1:]) + joined = "\n".join([tail] + buf).strip() + return (joined if len(joined) >= 50 else None), bool(joined) + buf.insert(0, page_text) + return None, False + + +# ---------------------------------------------------------------- Word 解档(python-docx) + +def _docx_app_pages(data: bytes) -> int | None: + try: + with zipfile.ZipFile(io.BytesIO(data)) as zf: + xml = zf.read("docProps/app.xml").decode("utf-8", "ignore") + m = re.search(r"(\d+)", xml) + return int(m.group(1)) if m else None + except Exception: # noqa: BLE001 + return None + + +def extract_profile_docx(data: bytes) -> dict[str, Any]: + try: + doc = Document(io.BytesIO(data)) + except Exception as exc: # noqa: BLE001 + raise FormatCheckError(f"Word 文件解析失败:{exc}") from exc + + side_lists: dict[str, list[float]] = {"top": [], "right": [], "bottom": [], "left": []} + for sec in doc.sections: + for k, v in ( + ("top", sec.top_margin), + ("right", sec.right_margin), + ("bottom", sec.bottom_margin), + ("left", sec.left_margin), + ): + if v is not None: + side_lists[k].append(float(v) * _EMU_TO_MM) + margins = None + if all(side_lists.values()): + margins = {k: statistics.median(v) for k, v in side_lists.items()} + + try: + normal = doc.styles["Normal"].font + default_name = normal.name + default_size = float(normal.size.pt) if normal.size is not None else None + except Exception: # noqa: BLE001 + default_name, default_size = None, None + + font_w: dict[str, int] = {} + size_w: dict[float, int] = {} + ratios: list[float] = [] + fig_caps = tab_caps = 0 + paras = doc.paragraphs + scan_count = min(len(paras), _MAX_PARAS) + + for i in range(scan_count): + para = paras[i] + text = para.text + if not text.strip(): + continue + ls = para.paragraph_format.line_spacing + if isinstance(ls, Length): + # 精确行距(exactly)以 EMU 存储,Length 是 int 子类——直接当倍数会得出 + # 十万级的假值;用正文默认字号换算成倍数 + if default_size: + r = float(ls.pt) / default_size + if 0.5 <= r <= 4.0: + ratios.append(r) + elif isinstance(ls, (int, float)) and not isinstance(ls, bool) and ls > 0: + r = float(ls) # multiple 行距本身就是倍数 + if 0.5 <= r <= 4.0: + ratios.append(r) + if _FIG_RE.match(text): + fig_caps += 1 + elif _TAB_RE.match(text): + tab_caps += 1 + for run in para.runs: + if not run.text: + continue + name = run.font.name or default_name or "unknown" + pt = run.font.size.pt if run.font.size is not None else default_size + chars = len(run.text) + font_w[str(name)] = font_w.get(str(name), 0) + chars + if pt: + size_w[round(float(pt), 1)] = size_w.get(round(float(pt), 1), 0) + chars + + # 参考文献节:标题段落之后全部文本 + refs_text, refs_found = None, False + for i, para in enumerate(paras): + if _HEADING_RE.match((para.text or "").strip()): + tail = "\n".join(p.text for p in paras[i + 1:] if (p.text or "").strip()) + if len(tail) >= 50: + refs_text, refs_found = tail, True + break + + return { + "source_kind": "docx", + "pages": _docx_app_pages(data), # Word 未记录 → None(检查项降级为 warn) + "margins_mm": margins, + "font_weights": font_w, + "size_weights": size_w, + "line_spacing_median": statistics.median(ratios) if ratios else None, + "figures": max(len(doc.inline_shapes), fig_caps), + "tables": max(len(doc.tables), tab_caps), + "refs_text": refs_text, + "refs_found": refs_found, + } + + +# ---------------------------------------------------------------- LaTeX 解档(正则+状态机,零新依赖) +# +# 决策前提:只做"解析 + 检查 + 建议代码片段",不自动改写 LaTeX(用户可能有自定义宏, +# 自动改写会引错;LaTeX 应由用户自己编辑)。不引入 pylatexenc/texsoup。 + +# 会相互覆盖的字体类宏包:≥2 个同时引入 → warn(times + mathptmx 类冲突) +_TEX_FONT_PKGS = {"times", "mathptmx", "newtx", "newpx", "txfonts", "pxfonts", "mathpazo"} + + +def _strip_tex_comments(src: str) -> str: + r"""去行内 % 注释(r-string,避免 \% 被解释为转义序列)。""" + return re.sub(r"(? dict[str, float] | None: + """\\usepackage[...]{geometry} 或 \\geometry{...} → {边: mm}(可缺边,检查端容缺)。""" + m = re.search(r"\\usepackage\s*\[([^\]]*)\]\s*\{\s*geometry\s*\}", src) + if not m: + m = re.search(r"\\geometry\s*\{([^}]*)\}", src) + if not m: + return None + opts = m.group(1) + + def to_mm(val: str) -> float | None: + mm = re.match(r"\s*([\d.]+)\s*(mm|cm|in|pt)?\s*$", val) + if not mm: + return None + x = float(mm.group(1)) + unit = mm.group(2) or "pt" # geometry 裸数字按 TeX 惯例为 pt + return {"mm": x, "cm": x * 10, "in": x * 25.4, "pt": x * 25.4 / 72.0}[unit] + + kv = {} + for pair in opts.split(","): + if "=" in pair: + k, v = pair.split("=", 1) + kv[k.strip().lower()] = v.strip() + out: dict[str, float] = {} + if "margin" in kv: + v = to_mm(kv["margin"]) + if v is not None: + return {"top": v, "right": v, "bottom": v, "left": v} + for k in ("top", "right", "bottom", "left"): + if k in kv: + v = to_mm(kv[k]) + if v is not None: + out[k] = v + if "inner" in kv: + v = to_mm(kv["inner"]) + if v is not None: + out.setdefault("left", v) + if "outer" in kv: + v = to_mm(kv["outer"]) + if v is not None: + out.setdefault("right", v) + return out or None + + +def extract_tex_profile(data: bytes) -> dict[str, Any]: + """正则 + 轻量状态机解析 .tex 源文件 → 与 DocProfile 同构(+tex 扩展字段)。""" + try: + text = data.decode("utf-8") + except UnicodeDecodeError: + text = data.decode("latin-1", errors="replace") + src = _strip_tex_comments(text) + + # \documentclass[10pt,a4paper]{article} + m_cls = re.search(r"\\documentclass\s*(?:\[[^\]]*\])?\s*\{\s*([\w*]+)\s*\}", src) + cls = m_cls.group(1) if m_cls else None + m_opt = re.search(r"\\documentclass\s*\[([^\]]*)\]", src) + cls_opts = m_opt.group(1) if m_opt else "" + m_pt = re.search(r"(\d+)\s*pt", cls_opts) + # 标准类未写选项时 LaTeX 默认 10pt;无 documentclass → None(检查项降级 warn) + fontsize = int(m_pt.group(1)) if m_pt else (10 if cls else None) + paper = "a4paper" if "a4paper" in cls_opts else ("letterpaper" if "letterpaper" in cls_opts else None) + + # \usepackage 列表(支持 {a,b} 逗号多包) + packages: list[str] = [] + for m in re.finditer(r"\\usepackage\s*(?:\[[^\]]*\])?\s*\{\s*([^}]+?)\s*\}", src): + packages += [p.strip().lower() for p in m.group(1).split(",") if p.strip()] + + # 行距:\linespread{...} 或 \setstretch{...}(值直接按"行距倍数"口径评估—— + # 按步骤4 规格:低于 min_line_spacing 即 fail;LaTeX 实际倍数还含 baselinestretch + # 的字号比,本引擎取显式设置值做保守判定) + line_spread: float | None = None + m = re.search(r"\\linespread\s*\{\s*([\d.]+)\s*\}", src) + if not m: + m = re.search(r"\\setstretch\s*\{\s*([\d.]+)\s*\}", src) + if m: + line_spread = float(m.group(1)) + + # 页边距(geometry) + margins = _parse_geometry(src) + + # 计数 + figures = len(re.findall(r"\\begin\s*\{\s*figure\*?\s*\}", src)) + tables = len(re.findall(r"\\begin\s*\{\s*table\*?\s*\}", src)) + cites = len(re.findall(r"\\cite\w*\s*\{", src)) + + # 参考文献:\bibliography{...}(BibTeX)/ \printbibliography(biblatex)/ thebibliography + has_bibtex = bool(re.search(r"\\bibliography\s*\{", src)) + has_printbib = bool(re.search(r"\\printbibliography", src)) + has_thebib = bool(re.search(r"\\begin\s*\{\s*thebibliography\s*\}", src)) + has_bibstyle = bool(re.search(r"\\bibliographystyle\s*\{", src)) # BibTeX 必需;biblatex 不需要 + has_bib = has_bibtex or has_printbib or has_thebib + refs_text: str | None = None + m_bib = re.search(r"\\begin\s*\{\s*thebibliography\s*\}[\s\S]*?\\end\s*\{\s*thebibliography\s*\}", src) + if m_bib: + refs_text = m_bib.group(0) + + # 宏表(\newcommand{\xxx} / \renewcommand)——用于解析准确性(识别自定义宏) + macros = re.findall(r"\\(?:new|re)command\s*\{\s*\\(\w+)\s*\}", src) + + # 匿名评审命令探测(规则集 anonymous:true 时检查) + m_anon = re.search(r"\\(?:anonymi[sz]e|anon\b|hideauthor|ifdoubleblind)", src, re.IGNORECASE) + + return { + "source_kind": "tex", + "pages": None, # LaTeX 源文件页数需编译后才有 → 检查项降级 warn(宽容化) + "margins_mm": margins, + "font_weights": {}, + "size_weights": {float(fontsize): 100} if fontsize else {}, + "line_spacing_median": line_spread, + "figures": figures, + "tables": tables, + "refs_text": refs_text, + "refs_found": has_bib, + "tex": { + "class": cls, + "fontsize_pt": fontsize, + "paper": paper, + "packages": packages, + "cites": cites, + "macros": macros, + "anon_cmd": m_anon.group(0) if m_anon else None, + "bib_bibtex": has_bibtex, + "bib_style": has_bibstyle, + }, + } + + +# ---------------------------------------------------------------- 参考文献样式检测 + +def detect_refs_style(text: str | None) -> tuple[str, str]: + """宽容化检测:返回 (detected, sample_line)。含糊 → unknown(后续只 warn)。""" + if not text: + return "unknown", "" + lines = [l.strip() for l in text.splitlines() if l.strip()][:40] + if not lines: + return "unknown", "" + n = len(lines) + gb = sum(1 for l in lines if _GB_TAG_RE.search(l)) + year = sum(1 for l in lines if _PAREN_YEAR_RE.search(l)) + num = sum(1 for l in lines if _BRACKET_NUM_RE.match(l)) + doi = sum(1 for l in lines if _DOI_RE.search(l)) + sample = lines[0][:80] + + if gb / n >= 0.4: + return "gb7714", sample + if num / n >= 0.4 and year / n < 0.3: + return "numbered", sample + if year / n >= 0.3 or doi / n >= 0.3: + return "author_year", sample + return "unknown", sample + + +# ---------------------------------------------------------------- 检查项构建 + +def _chk(key: str, name: str, status: str, detail: str, suggestion: str = "") -> dict[str, str]: + return {"key": key, "name": name, "status": status, "detail": detail, "suggestion": suggestion} + + +def _check_pages(profile: dict[str, Any], rules: dict[str, Any]) -> dict[str, str]: + limit = int(rules.get("max_pages", 10)) + pages = profile.get("pages") + kind = profile.get("source_kind") or "doc" + if pages is None: + # 宽容化:Word/LaTeX 页数缺失绝不 fail + if kind == "tex": + return _chk( + "pages", "页数", "warn", + f"LaTeX 源无法直接统计页数(规则上限 {limit} 页),需编译后核对", + "编译后确认(如 xelatex main.tex)总页数 ≤ 上限", + ) + return _chk( + "pages", "页数", "warn", + "Word 未记录页数,请自行核对", + f"在 Word 中按 Ctrl+End 查看总页数,或导出 PDF 后重查(规则上限 {limit} 页)", + ) + if pages <= limit: + return _chk("pages", "页数", "pass", f"共 {pages} 页,规则上限 {limit} 页") + return _chk( + "pages", "页数", "fail", f"共 {pages} 页,超出规则上限 {limit} 页", + f"压缩至 ≤{limit} 页,或将方法/图表移入补充材料", + ) + + +def _check_fonts(profile: dict[str, Any], rules: dict[str, Any]) -> dict[str, str]: + min_font = float(rules.get("min_font_pt", 9)) + # LaTeX:字号来自 \documentclass 选项(10/11/12pt,粒度粗) + if profile.get("source_kind") == "tex": + tex = profile.get("tex") or {} + cls = tex.get("class") or "documentclass" + fs = tex.get("fontsize_pt") + pkgs = tex.get("packages") or [] + font_pkgs = sorted(p for p in pkgs if p in _TEX_FONT_PKGS or p in ("helvet", "courier", "charter", "fourier")) + detail = ( + f"\\documentclass 选项字号 {fs}pt(类 {cls});" + f"字体宏包:{'、'.join(font_pkgs) if font_pkgs else '未引入'}" + + (f";纸张 {tex['paper']}" if tex.get("paper") else "") + ) + if fs is None: + return _chk("fonts", "字体字号", "warn", detail + "\n建议:\n \\documentclass[11pt]{article}", "补充 \\documentclass 声明") + if fs < min_font: + # LaTeX 粒度粗 → 按步骤4 规格降为 warn(非 fail) + return _chk( + "fonts", "字体字号", "warn", detail + f"\n建议:\n \\documentclass[11pt]{{{cls}}}", + f"正文字号低于下限 {min_font:.0f}pt,请改用 11pt/12pt 选项", + ) + return _chk("fonts", "字体字号", "pass", detail) + + size_w: dict[float, int] = profile.get("size_weights") or {} + font_w: dict[str, int] = profile.get("font_weights") or {} + if not size_w: + return _chk("fonts", "字体字号", "warn", "未能提取字体信息", "确认文档含可选中文本(扫描件无法检查字体)") + min_font = float(rules.get("min_font_pt", 9)) + max_fonts = int(rules.get("max_fonts", 6)) + total = sum(size_w.values()) + body_pt = max(size_w, key=size_w.get) + body_ratio = int(size_w[body_pt] / total * 100) + distinct = len(font_w) + top_fonts = sorted(font_w.items(), key=lambda kv: -kv[1])[:3] + top_text = "、".join(f"{k}({v}字)" for k, v in top_fonts) + detail = f"主要字号 {body_pt}pt(约 {body_ratio}%),共 {distinct} 种字体;高频字体:{top_text}" + if body_pt < min_font: + return _chk( + "fonts", "字体字号", "fail", detail, + f"将正文字号提高至 ≥{min_font}pt(当前主字号 {body_pt}pt)", + ) + if distinct > max_fonts: + return _chk( + "fonts", "字体字号", "warn", detail, + f"字体种类偏多({distinct} > {max_fonts}),建议全文统一为 1–2 种正文字体", + ) + return _chk("fonts", "字体字号", "pass", detail) + + +def _check_margins(profile: dict[str, Any], rules: dict[str, Any]) -> dict[str, str]: + limit = float(rules.get("min_margin_mm", 15)) + margins = profile.get("margins_mm") + # LaTeX:页边距来自 geometry;低于下限按步骤4 规格给 warn(非 fail),附建议片段 + if profile.get("source_kind") == "tex": + if not margins: + return _chk( + "margins", "页边距", "warn", + "未通过 geometry 设置页边距(按类默认评估)" + + f"\n建议:\n \\usepackage[margin=25mm]{{geometry}}", + "在导言区显式声明页边距", + ) + lo = min(margins.values()) + detail = f"geometry 页边距最小 {lo:.0f}mm(" + "、".join(f"{k}{v:.0f}" for k, v in margins.items()) + f"),规则下限 {limit:.0f}mm" + if lo < limit: + return _chk( + "margins", "页边距", "warn", + detail + f"\n建议:\n \\usepackage[margin={limit:.0f}mm]{{geometry}}", + f"调大页边距至 ≥{limit:.0f}mm", + ) + return _chk("margins", "页边距", "pass", detail) + if not margins: + return _chk("margins", "页边距", "warn", "未能提取页边距信息", "检查文档是否含可定位文本") + vals = [margins.get(k) for k in ("top", "right", "bottom", "left")] + vals = [v for v in vals if v is not None] + if not vals: + return _chk("margins", "页边距", "warn", "未能提取页边距信息", "检查文档是否含可定位文本") + t, r = margins.get("top"), margins.get("right") + b, l = margins.get("bottom"), margins.get("left") + lo = min(vals) + sides = "、".join( + f"{name}{v:.0f}" for name, v in (("上", t), ("右", r), ("下", b), ("左", l)) if v is not None + ) + detail = f"四边最小 {lo:.0f}mm({sides}),规则下限 {limit:.0f}mm" + if lo >= limit: + return _chk("margins", "页边距", "pass", detail) + if lo >= limit * 0.8: + return _chk("margins", "页边距", "warn", detail, f"将页边距调大至 ≥{limit:.0f}mm") + return _chk("margins", "页边距", "fail", detail, f"页边距过小,请调至 ≥{limit:.0f}mm(版式设置)") + + +def _check_spacing(profile: dict[str, Any], rules: dict[str, Any]) -> dict[str, str]: + lo = float(rules.get("min_line_spacing", 1.15)) + ratio = profile.get("line_spacing_median") + # LaTeX:\linespread/\setstretch 显式设置值;低于下限按步骤4 规格直接 fail + if profile.get("source_kind") == "tex": + if ratio is None: + return _chk( + "spacing", "行距", "pass", + "未显式设置 \\linespread/\\setstretch,LaTeX 类默认约 1.2 倍(如 10pt→12pt baselineskip)", + ) + detail = f"\\linespread/\\setstretch = {ratio:.2f},规则下限 {lo:.2f}" + if ratio < lo: + return _chk( + "spacing", "行距", "fail", + detail + f"\n建议:\n \\linespread{{{lo:.2f}}} % 或 \\setstretch{{{lo:.2f}}}(导言区)", + "在导言区调大行距设置", + ) + return _chk("spacing", "行距", "pass", detail) + if ratio is None: + return _chk("spacing", "行距", "warn", "未能提取行距信息", "确认段落使用固定/多倍行距设置") + lo = float(rules.get("min_line_spacing", 1.15)) + detail = f"正文中位行距约 {ratio:.2f} 倍,规则下限 {lo:.2f} 倍" + if ratio >= lo: + return _chk("spacing", "行距", "pass", detail) + if ratio >= lo * 0.9: + return _chk("spacing", "行距", "warn", detail, f"段落行距设为 ≥{lo:.2f} 倍(如 1.5 倍行距)") + return _chk("spacing", "行距", "fail", detail, f"行距过密,请设为 ≥{lo:.2f} 倍行距") + + +def _check_figures(profile: dict[str, Any], rules: dict[str, Any]) -> dict[str, str]: + figures = int(profile.get("figures") or 0) + tables = int(profile.get("tables") or 0) + min_f = int(rules.get("min_figures", 1)) + detail = f"检测到图 {figures} 张、表 {tables} 个(图注/表注正则 + 内嵌对象启发式)" + if figures >= min_f: + return _chk("figures", "图表数量", "pass", detail) + # 启发式检测不可靠 → 低于阈值只 warn 不 fail + return _chk( + "figures", "图表数量", "warn", detail, + f"常规研究论文建议 ≥{min_f} 图;若为综述/短文可忽略(本项为启发式检测)", + ) + + +# 仅"明确不符"才 fail 的 (expected, detected) 组合(宽容化:其余含糊组合一律 warn) +_REF_FAIL_PAIRS = { + ("apa", "gb7714"), # 找到 [J] 标引但规则要求 APA + ("gb7714", "author_year"), # 无 [J] 标引的作者-年份制,但规则要求 GB/T 7714 + ("apa", "numbered"), # 编号制引文但规则要求 APA +} + + +def _check_refs(profile: dict[str, Any], rules: dict[str, Any]) -> dict[str, str]: + expected = str(rules.get("refs_style", "apa")).lower() + exp_label = _STYLE_LABEL.get(expected, expected) + if not profile.get("refs_found"): + return _chk( + "refs", "参考文献格式", "warn", + "未找到参考文献节(References/参考文献 / \\bibliography / thebibliography)", + "确认存在参考文献声明后重查", + ) + if profile.get("source_kind") == "tex": + tex = profile.get("tex") or {} + # BibTeX:\bibliography 存在但缺 \bibliographystyle → warn(样式引擎未知) + if tex.get("bib_bibtex") and not tex.get("bib_style"): + return _chk( + "refs", "参考文献格式", "warn", + f"规则要求 {exp_label};检测到 \\bibliography 但缺少 \\bibliographystyle(BibTeX 无法确定引用样式)" + + "\n建议:\n \\bibliographystyle{plain} % 按期刊/模板指定实际样式", + "在 \\bibliography 前补 \\bibliographystyle", + ) + if not profile.get("refs_text"): + # 条目在 .bbl/编译产物,源文件无文本 → 宽容化只 warn + return _chk( + "refs", "参考文献格式", "warn", + f"规则要求 {exp_label};检测到参考文献声明(条目由编译生成,源文件无条目文本)", + "编译后核对参考文献条目样式", + ) + detected, sample = detect_refs_style(profile.get("refs_text")) + det_label = _STYLE_LABEL[detected] + detail = f"规则要求 {exp_label};检测到 {det_label};样例:{sample}" + # 宽容化:仅"明确不符"(_REF_FAIL_PAIRS)才 fail;含糊/不确定一律 warn + if (expected, detected) in _REF_FAIL_PAIRS: + return _chk("refs", "参考文献格式", "fail", detail, f"按 {exp_label} 调整全部文献条目(可用文献管理工具一键转换)") + if detected == "unknown": + return _chk("refs", "参考文献格式", "warn", detail, f"请人工核对是否符合 {exp_label}") + if expected == "gb7714" and detected == "numbered": + return _chk("refs", "参考文献格式", "warn", detail, "GB/T 7714 顺序编码制也用编号,需人工确认条目含 [J] 等类型标引") + if expected == "author-year-journal" and detected in ("gb7714", "numbered"): + return _chk("refs", "参考文献格式", "warn", detail, f"请对照期刊投稿指南核对是否符合 {exp_label}") + return _chk("refs", "参考文献格式", "pass", detail) + + +def _check_font_packages(profile: dict[str, Any], rules: dict[str, Any]) -> dict[str, str]: + """LaTeX 特有:多个相互覆盖的字体宏包(times + mathptmx 类)→ warn。""" + pkgs = set((profile.get("tex") or {}).get("packages") or []) + clash = sorted(pkgs & _TEX_FONT_PKGS) + if len(clash) >= 2: + detail = ( + f"检测到多个相互覆盖的字体宏包:{'、'.join(clash)}(后加载者覆盖前者,易产生冲突)" + + "\n建议:\n %只保留一套字体方案,例如:\n \\usepackage{newtx} % newtxtext + newtxmath 一体" + ) + return _chk("fontpkgs", "字体包兼容", "warn", detail, "移除重复/冲突的字体宏包,只保留一套") + return _chk( + "fontpkgs", "字体包兼容", "pass", + "字体宏包:" + ("、".join(clash) if clash else "未引入冲突类字体包"), + ) + + +def _check_anonymous(profile: dict[str, Any], rules: dict[str, Any]) -> dict[str, str]: + """LaTeX 特有且规则集 anonymous:true 时才出:源文件需含匿名处理命令。""" + tex = profile.get("tex") or {} + cmd = tex.get("anon_cmd") + if cmd: + return _chk("anonymous", "匿名评审", "pass", f"检测到匿名处理命令 {cmd}") + return _chk( + "anonymous", "匿名评审", "warn", + "规则要求匿名评审,源文件未检测到匿名处理命令" + + "\n建议:\n %隐去作者/致谢/自引,或定义匿名宏:\n \\newcommand{\\anon}[1]{[ANON]}", + "按期刊要求对作者信息做匿名处理", + ) + + +def build_checks(profile: dict[str, Any], rules: dict[str, Any]) -> list[dict[str, str]]: + checks = [ + _check_pages(profile, rules), + _check_fonts(profile, rules), + _check_margins(profile, rules), + _check_spacing(profile, rules), + ] + if profile.get("source_kind") == "tex": + checks.append(_check_font_packages(profile, rules)) + checks.append(_check_figures(profile, rules)) + checks.append(_check_refs(profile, rules)) + if profile.get("source_kind") == "tex" and rules.get("anonymous"): + checks.append(_check_anonymous(profile, rules)) + return checks + + +# ---------------------------------------------------------------- 入口 + +def check_document(data: bytes, kind: str, target_journal: str) -> dict[str, Any]: + """kind ∈ pdf|docx|tex。返回 {checks, summary, meta}(filename 由路由器补入 meta)。""" + if kind == "pdf": + profile = extract_profile_pdf(data) + elif kind == "docx": + profile = extract_profile_docx(data) + elif kind == "tex": + profile = extract_tex_profile(data) + else: + raise FormatCheckError(f"不支持的文件类型:{kind}") + + rules, ruleset_meta = load_ruleset(target_journal) + checks = build_checks(profile, rules) + summary = {"pass": 0, "warn": 0, "fail": 0} + for c in checks: + summary[c["status"]] = summary.get(c["status"], 0) + 1 + + detected, _ = detect_refs_style(profile.get("refs_text")) if profile.get("refs_found") else ("unknown", "") + meta = { + **ruleset_meta, + "file_type": kind, + "pages": profile.get("pages"), + "refs_style_expected": str(rules.get("refs_style", "apa")).lower(), + "refs_style_detected": detected, + } + if kind == "tex": + tex = profile.get("tex") or {} + meta["tex"] = { + "class": tex.get("class"), + "fontsize_pt": tex.get("fontsize_pt"), + "paper": tex.get("paper"), + "packages": tex.get("packages"), + "cites": tex.get("cites"), + "macros": (tex.get("macros") or [])[:10], + } + return {"checks": checks, "summary": summary, "meta": meta} diff --git a/review_service/data/journals/conferences.json b/review_service/data/journals/conferences.json new file mode 100644 index 0000000..f29e0f8 --- /dev/null +++ b/review_service/data/journals/conferences.json @@ -0,0 +1,493 @@ +{ + "version": 2, + "updated": "2026-10-10", + "notes": "会议种子数据 v2。deadline_source=placeholder 表示日期为首版占位数据(按各会议公开周期窗口/历年规律填写,未经官方渠道逐条核验),接入官方数据源前须人工核验;严禁以 AI 推测日期替代核验。deadline_confidence 标注日期置信度:high=官方已公布或历年极稳定;medium=按历年规律区间推算;low=新一届尚未公告或历届波动大,待核验。ccf_rank 按 CCF 推荐目录(第七版,2026-03 发布)标注,非目录内会议为 null(含全部生物信息/植物类会议)。timezone_note 默认 AoE (UTC-12)。首版不做自动同步。", + "conferences": [ + { + "id": "naacl-2027", + "name": "NAACL 2027", + "full_name": "North American Chapter of the Association for Computational Linguistics", + "domain_tags": ["AI/ML", "自然语言处理"], + "application_tags": ["交叉学科"], + "ccf_rank": "B", + "deadline_abstract": null, + "deadline_full_paper": "2026-10-12T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-06-01 ~ 2027-06-05", + "location": "San Francisco, California, USA", + "official_url": "https://www.naacl.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "high" + }, + { + "id": "coling-2027", + "name": "COLING 2027", + "full_name": "International Conference on Computational Linguistics", + "domain_tags": ["AI/ML", "自然语言处理"], + "application_tags": ["交叉学科"], + "ccf_rank": "B", + "deadline_abstract": null, + "deadline_full_paper": "2026-10-12T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-05-09 ~ 2027-05-14", + "location": "Macau SAR, China", + "official_url": null, + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "www-2027", + "name": "WWW 2027", + "full_name": "The Web Conference (ACM WWW)", + "domain_tags": ["AI/ML", "数据挖掘"], + "application_tags": ["交叉学科"], + "ccf_rank": "A", + "deadline_abstract": "2026-10-18T23:59:59+00:00", + "deadline_full_paper": "2026-10-25T23:59:59+00:00", + "notification_date": "2027-01-04", + "conference_date": "2027-05-10 ~ 2027-05-14", + "location": "Dublin, Ireland", + "official_url": "https://www2027.thewebconf.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "high" + }, + { + "id": "recomb-2027", + "name": "RECOMB 2027", + "full_name": "International Conference on Research in Computational Molecular Biology", + "domain_tags": ["生物信息学"], + "application_tags": ["交叉学科"], + "ccf_rank": null, + "deadline_abstract": "2026-11-06T23:59:59+00:00", + "deadline_full_paper": "2026-11-13T23:59:59+00:00", + "notification_date": "2027-02-01", + "conference_date": "2027-04-25 ~ 2027-04-28", + "location": "TBD(待官方公布)", + "official_url": "https://recomb.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "cvpr-2027", + "name": "CVPR 2027", + "full_name": "IEEE/CVF Conference on Computer Vision and Pattern Recognition", + "domain_tags": ["AI/ML", "计算机视觉"], + "application_tags": ["交叉学科"], + "ccf_rank": "A", + "deadline_abstract": "2026-11-10T23:59:59+00:00", + "deadline_full_paper": "2026-11-16T23:59:59+00:00", + "notification_date": "2027-02-25", + "conference_date": "2027-06-20 ~ 2027-06-25", + "location": "Seattle, USA", + "official_url": "https://cvpr.thecvf.com/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "high" + }, + { + "id": "wsdm-2027", + "name": "WSDM 2027", + "full_name": "International Conference on Web Search and Data Mining", + "domain_tags": ["AI/ML", "数据挖掘"], + "application_tags": ["交叉学科"], + "ccf_rank": "B", + "deadline_abstract": null, + "deadline_full_paper": "2026-11-17T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-02-15 ~ 2027-02-19", + "location": "Hong Kong SAR, China", + "official_url": "https://www.wsdm-conference.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "high" + }, + { + "id": "pag-2027", + "name": "PAG 2027", + "full_name": "Plant & Animal Genome Conference", + "domain_tags": ["植物/农学", "基因组学"], + "application_tags": ["种业", "分子育种"], + "ccf_rank": null, + "deadline_abstract": "2026-11-30T23:59:59+00:00", + "deadline_full_paper": "2026-12-15T23:59:59+00:00", + "notification_date": "2027-01-05", + "conference_date": "2027-01-08 ~ 2027-01-12", + "location": "San Diego, USA", + "official_url": "https://www.intlpag.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "acl-2027", + "name": "ACL 2027", + "full_name": "Annual Meeting of the Association for Computational Linguistics", + "domain_tags": ["AI/ML", "自然语言处理"], + "application_tags": ["交叉学科"], + "ccf_rank": "A", + "deadline_abstract": null, + "deadline_full_paper": "2027-01-04T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-08-20 ~ 2027-08-22", + "location": "Kyoto, Japan", + "official_url": "https://2027.aclweb.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "high" + }, + { + "id": "plantbio-2027", + "name": "Plant Biology 2027", + "full_name": "ASPB Annual Meeting — Plant Biology", + "domain_tags": ["植物/农学", "分子生物学"], + "application_tags": ["分子育种"], + "ccf_rank": null, + "deadline_abstract": "2027-01-08T23:59:59+00:00", + "deadline_full_paper": "2027-01-08T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-07(待官方公布)", + "location": "Albuquerque, New Mexico, USA", + "official_url": "https://plantbiology.aspb.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "high" + }, + { + "id": "ijcai-2027", + "name": "IJCAI 2027", + "full_name": "International Joint Conference on Artificial Intelligence", + "domain_tags": ["AI/ML"], + "application_tags": ["交叉学科"], + "ccf_rank": "B", + "deadline_abstract": "2027-01-11T23:59:59+00:00", + "deadline_full_paper": "2027-01-18T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-08-07 ~ 2027-08-17", + "location": "Kyoto, Japan / Hengqin, China", + "official_url": "https://www.ijcai.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "sigir-2027", + "name": "SIGIR 2027", + "full_name": "ACM SIGIR Conference on Research and Development in Information Retrieval", + "domain_tags": ["AI/ML", "信息检索"], + "application_tags": ["交叉学科"], + "ccf_rank": "A", + "deadline_abstract": "2027-01-14T23:59:59+00:00", + "deadline_full_paper": "2027-01-21T23:59:59+00:00", + "notification_date": "2027-04-05", + "conference_date": "2027-07-20 ~ 2027-07-24", + "location": "San Jose, California, USA", + "official_url": "https://sigir2027.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "high" + }, + { + "id": "icml-2027", + "name": "ICML 2027", + "full_name": "International Conference on Machine Learning", + "domain_tags": ["AI/ML", "深度学习"], + "application_tags": ["交叉学科"], + "ccf_rank": "A", + "deadline_abstract": "2027-01-15T23:59:59+00:00", + "deadline_full_paper": "2027-01-22T23:59:59+00:00", + "notification_date": "2027-05-01", + "conference_date": "2027-07-19 ~ 2027-07-25", + "location": "TBD(待官方公布)", + "official_url": "https://icml.cc/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "chil-2027", + "name": "CHIL 2027", + "full_name": "ACM Conference on Health, Inference, and Learning", + "domain_tags": ["AI/ML", "健康医疗"], + "application_tags": ["交叉学科"], + "ccf_rank": null, + "deadline_abstract": "2027-01-15T23:59:59+00:00", + "deadline_full_paper": "2027-01-29T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-06(待官方公布)", + "location": "TBD(待官方公布)", + "official_url": "https://dl.acm.org/conference/chil", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "low" + }, + { + "id": "kdd-2027", + "name": "KDD 2027 (Cycle 2)", + "full_name": "ACM SIGKDD Conference on Knowledge Discovery and Data Mining", + "domain_tags": ["AI/ML", "数据挖掘"], + "application_tags": ["交叉学科"], + "ccf_rank": "A", + "deadline_abstract": "2027-01-31T23:59:59+00:00", + "deadline_full_paper": "2027-02-07T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-08-01 ~ 2027-08-05", + "location": "San Jose, California, USA", + "official_url": "https://kdd2027.kdd.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "ismb-eccb-2027", + "name": "ISMB/ECCB 2027", + "full_name": "Intelligent Systems for Molecular Biology / European Conference on Computational Biology", + "domain_tags": ["生物信息学"], + "application_tags": ["交叉学科"], + "ccf_rank": null, + "deadline_abstract": "2027-02-12T23:59:59+00:00", + "deadline_full_paper": "2027-02-19T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-07-18 ~ 2027-07-22", + "location": "Copenhagen, Denmark", + "official_url": "https://www.iscb.org/ismbeccb2027/home", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "ipmbc-2027", + "name": "IPMB 2027", + "full_name": "International Congress on Plant Molecular Biology (14th)", + "domain_tags": ["植物/农学", "分子生物学"], + "application_tags": ["分子育种"], + "ccf_rank": null, + "deadline_abstract": "2027-02-15T23:59:59+00:00", + "deadline_full_paper": "2027-02-22T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-07(待官方公布)", + "location": "Wuhan, China", + "official_url": "https://www.ipmb2027.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "low" + }, + { + "id": "uai-2027", + "name": "UAI 2027", + "full_name": "Conference on Uncertainty in Artificial Intelligence", + "domain_tags": ["AI/ML"], + "application_tags": ["交叉学科"], + "ccf_rank": "B", + "deadline_abstract": null, + "deadline_full_paper": "2027-02-24T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-08-16 ~ 2027-08-20", + "location": "TBD(待官方公布)", + "official_url": "https://www.auai.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "miccai-2027", + "name": "MICCAI 2027", + "full_name": "International Conference on Medical Image Computing and Computer-Assisted Intervention", + "domain_tags": ["AI/ML", "医学影像"], + "application_tags": ["交叉学科"], + "ccf_rank": null, + "deadline_abstract": "2027-02-11T23:59:59+00:00", + "deadline_full_paper": "2027-02-25T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-09-26 ~ 2027-10-01", + "location": "Auckland, New Zealand", + "official_url": "https://miccai.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "iccv-2027", + "name": "ICCV 2027", + "full_name": "IEEE/CVF International Conference on Computer Vision", + "domain_tags": ["AI/ML", "计算机视觉"], + "application_tags": ["交叉学科"], + "ccf_rank": "A", + "deadline_abstract": "2027-02-26T23:59:59+00:00", + "deadline_full_paper": "2027-03-05T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-10-02 ~ 2027-10-08", + "location": "Hong Kong SAR, China", + "official_url": null, + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "bosc-2027", + "name": "BOSC 2027", + "full_name": "Bioinformatics Open Source Conference", + "domain_tags": ["生物信息学"], + "application_tags": ["交叉学科"], + "ccf_rank": null, + "deadline_abstract": null, + "deadline_full_paper": "2027-03-26T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-07-18 ~ 2027-07-22", + "location": "Copenhagen, Denmark", + "official_url": "https://openbioinformatics.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "low" + }, + { + "id": "acm-bcb-2027", + "name": "ACM-BCB 2027", + "full_name": "ACM Conference on Bioinformatics, Computational Biology and Health Informatics", + "domain_tags": ["生物信息学", "AI/ML"], + "application_tags": ["交叉学科"], + "ccf_rank": null, + "deadline_abstract": "2027-04-16T23:59:59+00:00", + "deadline_full_paper": "2027-04-23T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-08(待官方公布)", + "location": "TBD(待官方公布)", + "official_url": "https://acm-bcb.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "ieee-bibm-2027", + "name": "IEEE BIBM 2027", + "full_name": "IEEE International Conference on Bioinformatics and Bioengineering", + "domain_tags": ["生物信息学"], + "application_tags": ["交叉学科"], + "ccf_rank": null, + "deadline_abstract": "2027-05-07T23:59:59+00:00", + "deadline_full_paper": "2027-05-14T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-11(待官方公布)", + "location": "TBD(待官方公布)", + "official_url": null, + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "low" + }, + { + "id": "emnlp-2027", + "name": "EMNLP 2027", + "full_name": "Conference on Empirical Methods in Natural Language Processing", + "domain_tags": ["AI/ML", "自然语言处理"], + "application_tags": ["交叉学科"], + "ccf_rank": "B", + "deadline_abstract": "2027-05-14T23:59:59+00:00", + "deadline_full_paper": "2027-05-21T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-11(待官方公布)", + "location": "TBD(待官方公布)", + "official_url": null, + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "low" + }, + { + "id": "neurips-2027", + "name": "NeurIPS 2027", + "full_name": "Conference on Neural Information Processing Systems", + "domain_tags": ["AI/ML", "深度学习"], + "application_tags": ["交叉学科"], + "ccf_rank": "A", + "deadline_abstract": "2027-05-14T23:59:59+00:00", + "deadline_full_paper": "2027-05-21T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-12(待官方公布)", + "location": "TBD(待官方公布)", + "official_url": "https://neurips.cc/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + }, + { + "id": "psb-2028", + "name": "PSB 2028", + "full_name": "Pacific Symposium on Biocomputing", + "domain_tags": ["生物信息学"], + "application_tags": ["交叉学科"], + "ccf_rank": null, + "deadline_abstract": null, + "deadline_full_paper": "2027-07-01T23:59:59+00:00", + "notification_date": null, + "conference_date": "2028-01(待官方公布)", + "location": "TBD(待官方公布)", + "official_url": "https://psb.stanford.edu/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "low" + }, + { + "id": "pag-europe-2027", + "name": "PAG Europe 2027", + "full_name": "Plant & Animal Genome Conference Europe", + "domain_tags": ["植物/农学", "基因组学"], + "application_tags": ["种业", "分子育种"], + "ccf_rank": null, + "deadline_abstract": null, + "deadline_full_paper": "2027-07-09T23:59:59+00:00", + "notification_date": null, + "conference_date": "2027-10(待官方公布)", + "location": "TBD(待官方公布)", + "official_url": null, + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "low" + }, + { + "id": "aaai-2028", + "name": "AAAI 2028", + "full_name": "AAAI Conference on Artificial Intelligence", + "domain_tags": ["AI/ML"], + "application_tags": ["交叉学科"], + "ccf_rank": "A", + "deadline_abstract": "2027-07-20T23:59:59+00:00", + "deadline_full_paper": "2027-07-27T23:59:59+00:00", + "notification_date": null, + "conference_date": "2028-02(待官方公布)", + "location": "TBD(待官方公布)", + "official_url": "https://aaai.org/", + "timezone_note": "AoE (UTC-12)", + "deadline_source": "placeholder", + "last_verified": "2026-10-10", + "deadline_confidence": "medium" + } + ] +} diff --git a/review_service/data/journals/import_report.txt b/review_service/data/journals/import_report.txt new file mode 100644 index 0000000..fda2154 --- /dev/null +++ b/review_service/data/journals/import_report.txt @@ -0,0 +1,61 @@ +journals directory 导入对账报告 +生成时间: 2026-10-10T15:37:11 +源文件: /home/xzq/5090/teamWorkspace/wjq/PlantAI-RAG-new-latest/PlantAI-rag-new/review_service/data/journals/source_v4.xlsx(193386 bytes) +阶段: 完成 + +=== 计数 === +读取有效行: 国际 779 / 中文 277 / 合计 1056 +成功: 1056 跳过(名称空): 0 失败: 0 +写入后 count(*): en=779 zh=277 total=1056 +期望: en=779 zh=277 total=1056 → ✓ 相符 + +=== 分区分布(国际)=== +1区 233 / 2区 214 / 3区 181 / 4区 134 / 空白 17 +分区空白(→null 无note): 17 +分区未检得(→null + note): 0 + +=== JIF 缺失 13 条(jif=null + note=核对状态)=== + - eLife [2025 JIF未检得/未给值] + - Heliyon [2025 JIF未检得/未给值] + - Australian Journal of Crop Science [2025 JIF未检得/未给值] + - International Journal of Agriculture and Biology [2025 JIF未检得/未给值] + - Journal of Agriculture and Rural Development in the Tropics and Subtropics [2025 JIF未检得/未给值] + - Fruits [2025 JIF未检得/未给值] + - RANGELAND JOURNAL [2025 JIF未检得/未给值] + - Science of The Total Environment [2025 JIF未检得/未给值] + - Chemosphere [2025 JIF未检得/未给值] + - Environmental Science and Pollution Research [2025 JIF未检得/未给值] + - Bioengineered [2025 JIF未检得/未给值] + - Cell Biomaterials [2025 JIF未检得/未给值] + - National Science Open [2025 JIF未检得/未给值] + +=== 中文复合IF 缺失 0 条 === + +=== 分区未检得 期刊名 === + (无——源表以空白表示未检得,见上方'分区空白') + +=== 重复 id 冲突(应为空)=== + (无) + +=== id 策略 === +ISSN 型: 692 条 slug 型: 364 条 + +=== 来源超链接 === +国际 JIF来源: 779/779 分区来源: 762/779 中文数据来源: 277/277 + +=== 结构迁移(ALTER TABLE,幂等)=== + 本次加列: official_check_status, jcr_release_year + 已存在跳过: official_url + +=== 官网映射(决策:official_source 不入库)=== + 识别列: 官网网址 + official_url 填充: 1053/1056 official_check_status 填充: 1056/1056 + jcr_release_year 填充: 779(仅国际=2026;中文表无此列→null) + 官网缺失 3 条(official_url=null,前端显示「—」不生成链接): + - [zh] 中国食用菌 + - [zh] 水土保持应用技术 + - [zh] 粮食与饲料工业 + +=== 幂等性验证 === + 第二次 upsert 后 count 不变: ✓ 通过 + diff --git a/review_service/data/journals/journals.json b/review_service/data/journals/journals.json index a5c0ee1..aad5843 100644 --- a/review_service/data/journals/journals.json +++ b/review_service/data/journals/journals.json @@ -1,7 +1,17 @@ { "version": 1, "updated": "2026-10-09", - "notes": "植物基因组学领域种子期刊。acceptance_rate 无公开权威数据一律为 null(不编造);impact_factor / review_time_weeks 为公开 JCR/期刊官网常识近似值,以 last_updated 标注刷新时间,接入真实数据源前需人工核验。scope_desc 为英文范围描述,供 vstore 向量匹配使用。", + "notes": "植物基因组学领域种子期刊。acceptance_rate 无公开权威数据一律为 null(不编造);impact_factor / review_time_weeks 为公开 JCR/期刊官网常识近似值,以 last_updated 标注刷新时间,接入真实数据源前需人工核验。scope_desc 为英文范围描述,供 vstore 向量匹配使用。 format_rules_default 为通用默认规则(rules_source=default);各条目 format_rules 暂为占位(rules_source=placeholder),接入真实投稿指南核验前不填期刊专属数字。 新增标签字段(不进 SQLite,接口按 id 从本文件合并):scope_tags / application_tags / cross_domain 按 scope_desc 归类的标签;cas_partition / jcr_quartile 首版占位(partition_source=placeholder),核实不确定的一律 null、不猜测,接入真实分区数据前需人工核验。", + "format_rules_default": { + "rules_source": "default", + "max_pages": 10, + "min_font_pt": 9, + "min_margin_mm": 15, + "min_line_spacing": 1.15, + "min_figures": 1, + "max_fonts": 6, + "refs_style": "apa" + }, "journals": [ { "id": "plant-cell", @@ -12,7 +22,16 @@ "acceptance_rate": null, "submission_deadline": null, "official_url": "https://academic.oup.com/plcell", - "last_updated": "2026-10-09" + "last_updated": "2026-10-09", + "scope_tags": ["植物基因组学", "分子生物学", "细胞生物学", "信号转导"], + "application_tags": ["基础研究"], + "cas_partition": "1区", + "jcr_quartile": "Q1", + "partition_source": "placeholder", + "cross_domain": ["系统生物学", "植物-微生物互作"], + "format_rules": { + "rules_source": "placeholder" + } }, { "id": "genome-biology", @@ -23,7 +42,16 @@ "acceptance_rate": null, "submission_deadline": null, "official_url": "https://genomebiology.biomedcentral.com", - "last_updated": "2026-10-09" + "last_updated": "2026-10-09", + "scope_tags": ["基因组学", "生物信息学", "多组学", "计算生物学"], + "application_tags": ["基础研究", "算法与方法"], + "cas_partition": "1区", + "jcr_quartile": "Q1", + "partition_source": "placeholder", + "cross_domain": ["进化生物学", "单细胞组学"], + "format_rules": { + "rules_source": "placeholder" + } }, { "id": "plant-journal", @@ -34,7 +62,16 @@ "acceptance_rate": null, "submission_deadline": null, "official_url": "https://onlinelibrary.wiley.com/journal/1365313X", - "last_updated": "2026-10-09" + "last_updated": "2026-10-09", + "scope_tags": ["分子生物学", "植物基因组学", "细胞与发育生物学", "逆境生物学"], + "application_tags": ["基础研究", "分子育种"], + "cas_partition": null, + "jcr_quartile": "Q1", + "partition_source": "placeholder", + "cross_domain": ["表观遗传学", "植物生物技术"], + "format_rules": { + "rules_source": "placeholder" + } }, { "id": "theoretical-applied-genetics", @@ -45,7 +82,16 @@ "acceptance_rate": null, "submission_deadline": null, "official_url": "https://link.springer.com/journal/338", - "last_updated": "2026-10-09" + "last_updated": "2026-10-09", + "scope_tags": ["遗传学", "作物育种", "数量遗传学", "基因组选择"], + "application_tags": ["种业", "分子育种", "基础研究"], + "cas_partition": null, + "jcr_quartile": null, + "partition_source": "placeholder", + "cross_domain": ["统计遗传学", "全基因组关联分析"], + "format_rules": { + "rules_source": "placeholder" + } }, { "id": "plant-genome", @@ -56,7 +102,16 @@ "acceptance_rate": null, "submission_deadline": null, "official_url": "https://acsess.onlinelibrary.wiley.com/journal/1940-3372", - "last_updated": "2026-10-09" + "last_updated": "2026-10-09", + "scope_tags": ["植物基因组学", "作物基因组学", "结构变异", "关联分析"], + "application_tags": ["种业", "分子育种"], + "cas_partition": null, + "jcr_quartile": null, + "partition_source": "placeholder", + "cross_domain": ["转化基因组学", "标记辅助选择"], + "format_rules": { + "rules_source": "placeholder" + } } ] } diff --git a/review_service/data/journals/smoke/1_default_en.json b/review_service/data/journals/smoke/1_default_en.json new file mode 100644 index 0000000..18badb5 --- /dev/null +++ b/review_service/data/journals/smoke/1_default_en.json @@ -0,0 +1,1903 @@ +{ + "ok": true, + "items": [ + { + "id": "en:1740-1526", + "lang": "en", + "name": "NATURE REVIEWS MICROBIOLOGY", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 103.3, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1740-1526", + "eissn": "1740-1534", + "jcr_disciplines": [ + "MICROBIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1474-1776", + "lang": "en", + "name": "NATURE REVIEWS DRUG DISCOVERY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 101.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1474-1776", + "eissn": "1474-1784", + "jcr_disciplines": [ + "BIOTECHNOLOGY & APPLIED MICROBIOLOGY(SCIE)", + "PHARMACOLOGY & PHARMACY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1471-0072", + "lang": "en", + "name": "NATURE REVIEWS MOLECULAR CELL BIOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 90.2, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1471-0072", + "eissn": "1471-0080", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-4774", + "lang": "en", + "name": "Nature Reviews Clinical Oncology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 83.2, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-4774", + "eissn": "1759-4782", + "jcr_disciplines": [ + "ONCOLOGY(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-earth-environment", + "lang": "en", + "name": "Nature Reviews Earth & Environment", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 71.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2662-138X", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(SCIE)", + "GEOSCIENCES, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1474-175X", + "lang": "en", + "name": "NATURE REVIEWS CANCER", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 66.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1474-175X", + "eissn": "1474-1768", + "jcr_disciplines": [ + "ONCOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1474-1733", + "lang": "en", + "name": "NATURE REVIEWS IMMUNOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 60.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1474-1733", + "eissn": "1474-1741", + "jcr_disciplines": [ + "IMMUNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2056-676X", + "lang": "en", + "name": "Nature Reviews Disease Primers", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 60.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "2056-676X", + "eissn": "2056-676X", + "jcr_disciplines": [ + "MEDICINE, GENERAL & INTERNAL(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-methods-primers", + "lang": "en", + "name": "Nature Reviews Methods Primers", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 56.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2662-8449", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1471-0056", + "lang": "en", + "name": "NATURE REVIEWS GENETICS", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 52.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1471-0056", + "eissn": "1471-0064", + "jcr_disciplines": [ + "GENETICS & HEREDITY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-chemistry", + "lang": "en", + "name": "Nature Reviews Chemistry", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 51.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2397-3358", + "jcr_disciplines": [ + "CHEMISTRY, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5045", + "lang": "en", + "name": "Nature Reviews Gastroenterology & Hepatology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 51.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5045", + "eissn": "1759-5053", + "jcr_disciplines": [ + "GASTROENTEROLOGY & HEPATOLOGY(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1078-8956", + "lang": "en", + "name": "NATURE MEDICINE", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 50.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1078-8956", + "eissn": "1546-170X", + "jcr_disciplines": [ + "BIOCHEMISTRY & MOLECULAR BIOLOGY(SCIE)", + "CELL BIOLOGY(SCIE)", + "MEDICINE, RESEARCH & EXPERIMENTAL(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0028-0836", + "lang": "en", + "name": "NATURE", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 48.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0028-0836", + "eissn": "1476-4687", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0036-8075", + "lang": "en", + "name": "SCIENCE", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 45.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Science / AAAS", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0036-8075", + "eissn": "1095-9203", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1535-6108", + "lang": "en", + "name": "CANCER CELL", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 44.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1535-6108", + "eissn": "1878-3686", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)", + "ONCOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5002", + "lang": "en", + "name": "Nature Reviews Cardiology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 44.2, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5002", + "eissn": "1759-5010", + "jcr_disciplines": [ + "CARDIAC & CARDIOVASCULAR SYSTEMS(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0092-8674", + "lang": "en", + "name": "CELL", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 42.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0092-8674", + "eissn": "1097-4172", + "jcr_disciplines": [ + "BIOCHEMISTRY & MOLECULAR BIOLOGY(SCIE)", + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5029", + "lang": "en", + "name": "Nature Reviews Endocrinology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 42.3, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5029", + "eissn": "1759-5037", + "jcr_disciplines": [ + "ENDOCRINOLOGY & METABOLISM(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1087-0156", + "lang": "en", + "name": "NATURE BIOTECHNOLOGY", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 41.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1087-0156", + "eissn": "1546-1696", + "jcr_disciplines": [ + "BIOTECHNOLOGY & APPLIED MICROBIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5061", + "lang": "en", + "name": "Nature Reviews Nephrology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 39.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5061", + "eissn": "1759-507X", + "jcr_disciplines": [ + "UROLOGY & NEPHROLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-bioengineering", + "lang": "en", + "name": "Nature Reviews Bioengineering", + "research_direction": "微生物真菌与生物技术", + "cas_partition": null, + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 37.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "未检得", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2731-6092", + "jcr_disciplines": [ + "ENGINEERING, BIOMEDICAL(ESCI)", + "MATERIALS SCIENCE, BIOMATERIALS(ESCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": null, + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2542-4351", + "lang": "en", + "name": "Joule", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 35.4, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2542-4351", + "eissn": "2542-4351", + "jcr_disciplines": [ + "CHEMISTRY, PHYSICAL(SCIE)", + "ENERGY & FUELS(SCIE)", + "MATERIALS SCIENCE, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-4790", + "lang": "en", + "name": "Nature Reviews Rheumatology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 32.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-4790", + "eissn": "1759-4804", + "jcr_disciplines": [ + "RHEUMATOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1548-7091", + "lang": "en", + "name": "NATURE METHODS", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 32.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1548-7091", + "eissn": "1548-7105", + "jcr_disciplines": [ + "BIOCHEMICAL RESEARCH METHODS(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1550-4131", + "lang": "en", + "name": "Cell Metabolism", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 30.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1550-4131", + "eissn": "1932-7420", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)", + "ENDOCRINOLOGY & METABOLISM(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1061-4036", + "lang": "en", + "name": "NATURE GENETICS", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 29.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1061-4036", + "eissn": "1546-1718", + "jcr_disciplines": [ + "GENETICS & HEREDITY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-cancer", + "lang": "en", + "name": "Nature Cancer", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 28.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2662-1347", + "jcr_disciplines": [ + "ONCOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1529-2908", + "lang": "en", + "name": "NATURE IMMUNOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1529-2908", + "eissn": "1529-2916", + "jcr_disciplines": [ + "IMMUNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2470-9476", + "lang": "en", + "name": "Science Robotics", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Science / AAAS", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2470-9476", + "eissn": "2470-9476", + "jcr_disciplines": [ + "ROBOTICS(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1758-678X", + "lang": "en", + "name": "Nature Climate Change", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1758-678X", + "eissn": "1758-6798", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(SCIE)", + "ENVIRONMENTAL STUDIES(SSCI)", + "METEOROLOGY & ATMOSPHERIC SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2398-9629", + "lang": "en", + "name": "Nature Sustainability", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2398-9629", + "eissn": "2398-9629", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(SCIE)", + "ENVIRONMENTAL STUDIES(SSCI)", + "GREEN & SUSTAINABLE SCIENCE & TECHNOLOGY(SSCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2157-846X", + "lang": "en", + "name": "Nature Biomedical Engineering", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 26.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2157-846X", + "eissn": "2157-846X", + "jcr_disciplines": [ + "ENGINEERING, BIOMEDICAL(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1471-003X", + "lang": "en", + "name": "NATURE REVIEWS NEUROSCIENCE", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 26.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1471-003X", + "eissn": "1471-0048", + "jcr_disciplines": [ + "NEUROSCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1543-5008", + "lang": "en", + "name": "Annual Review of Plant Biology", + "research_direction": "植物科学与分子育种", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 26.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1543-5008", + "eissn": "1545-2123", + "jcr_disciplines": [ + "PLANT SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1074-7613", + "lang": "en", + "name": "Immunity", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 26.3, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1074-7613", + "eissn": "1097-4180", + "jcr_disciplines": [ + "IMMUNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1001-0602", + "lang": "en", + "name": "CELL RESEARCH", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 25.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1001-0602", + "eissn": "1748-7838", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2666-6758", + "lang": "en", + "name": "Innovation", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 25.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2666-6758", + "eissn": "2666-6758", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(ESCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1560-2745", + "lang": "en", + "name": "FUNGAL DIVERSITY", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 24.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1560-2745", + "eissn": "1878-9129", + "jcr_disciplines": [ + "MYCOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1674-2052", + "lang": "en", + "name": "Molecular Plant", + "research_direction": "植物科学与分子育种", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 24.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1674-2052", + "eissn": "1752-9867", + "jcr_disciplines": [ + "BIOCHEMISTRY & MOLECULAR BIOLOGY(SCIE)", + "PLANT SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-water", + "lang": "en", + "name": "Nature Water", + "research_direction": "生态环境与保护", + "cas_partition": null, + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 24.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "未检得", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2731-6084", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(ESCI)", + "WATER RESOURCES(ESCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": null, + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-food", + "lang": "en", + "name": "Nature Food", + "research_direction": "食品营养与安全", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 21.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2662-1355", + "jcr_disciplines": [ + "FOOD SCIENCE & TECHNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2095-9273", + "lang": "en", + "name": "Science Bulletin", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 21.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2095-9273", + "eissn": "2095-9281", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1360-1385", + "lang": "en", + "name": "TRENDS IN PLANT SCIENCE", + "research_direction": "植物科学与分子育种", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1360-1385", + "eissn": "1878-4372", + "jcr_disciplines": [ + "PLANT SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-metabolism", + "lang": "en", + "name": "Nature Metabolism", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2522-5812", + "jcr_disciplines": [ + "ENDOCRINOLOGY & METABOLISM(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1610-3653", + "lang": "en", + "name": "Environmental Chemistry Letters", + "research_direction": "生态环境与保护", + "cas_partition": "2区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.4, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "否", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1610-3653", + "eissn": "1610-3661", + "jcr_disciplines": [ + "CHEMISTRY, MULTIDISCIPLINARY(SCIE)", + "ENGINEERING, ENVIRONMENTAL(SCIE)", + "ENVIRONMENTAL SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1934-5909", + "lang": "en", + "name": "Cell Stem Cell", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.4, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1934-5909", + "eissn": "1875-9777", + "jcr_disciplines": [ + "CELL & TISSUE ENGINEERING(SCIE)", + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1097-6256", + "lang": "en", + "name": "NATURE NEUROSCIENCE", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1097-6256", + "eissn": "1546-1726", + "jcr_disciplines": [ + "NEUROSCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0165-6147", + "lang": "en", + "name": "TRENDS IN PHARMACOLOGICAL SCIENCES", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 19.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "0165-6147", + "eissn": "1873-3735", + "jcr_disciplines": [ + "PHARMACOLOGY & PHARMACY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2451-9294", + "lang": "en", + "name": "Chem", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 19.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2451-9294", + "eissn": "2451-9294", + "jcr_disciplines": [ + "CHEMISTRY, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + } + ], + "meta": { + "total": 779, + "page": 1, + "size": 50, + "lang": "en", + "domain": "", + "cas_partition": "", + "q": "", + "domains": [ + "细胞分子发育与生理", + "生态环境与保护", + "微生物真菌与生物技术", + "农学作物与种质", + "遗传组学与计算生物", + "植物科学与分子育种", + "水产渔业与海洋生物", + "食品营养与安全", + "植物保护与昆虫", + "畜牧动物营养与繁殖", + "土壤肥料与地球生物化学", + "林业木材与草业", + "兽医与寄生虫", + "综合与交叉", + "园艺果树与采后" + ], + "data_source_note": "分区:2025年中科院公开表(official);JIF:2024 JCR,由2025版JCR发布(official);整理日期2026-10-10。空白=来源未给值≠0;研究方向/期刊标记/文章类型为导航标签,非官方评级。", + "data_imported": true + }, + "error": null +} \ No newline at end of file diff --git a/review_service/data/journals/smoke/2_lang_zh.json b/review_service/data/journals/smoke/2_lang_zh.json new file mode 100644 index 0000000..e6c6576 --- /dev/null +++ b/review_service/data/journals/smoke/2_lang_zh.json @@ -0,0 +1,1779 @@ +{ + "ok": true, + "items": [ + { + "id": "zh:自然资源学报", + "lang": "zh", + "name": "自然资源学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 10.773, + "comprehensive_impact_factor": 7.725, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:地理学报", + "lang": "zh", + "name": "地理学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 9.926, + "comprehensive_impact_factor": 7.412, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:中国人口-资源与环境", + "lang": "zh", + "name": "中国人口·资源与环境", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 9.53, + "comprehensive_impact_factor": 6.957, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 154, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=154" + }, + { + "id": "zh:地理研究", + "lang": "zh", + "name": "地理研究", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 7.661, + "comprehensive_impact_factor": 5.5, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:资源科学", + "lang": "zh", + "name": "资源科学", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.731, + "comprehensive_impact_factor": 4.962, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:地理科学", + "lang": "zh", + "name": "地理科学", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.614, + "comprehensive_impact_factor": 4.698, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:地理科学进展", + "lang": "zh", + "name": "地理科学进展", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.513, + "comprehensive_impact_factor": 4.532, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:生态学报", + "lang": "zh", + "name": "生态学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.473, + "comprehensive_impact_factor": 4.412, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:土壤学报", + "lang": "zh", + "name": "土壤学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.361, + "comprehensive_impact_factor": 4.262, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:环境科学", + "lang": "zh", + "name": "环境科学", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.137, + "comprehensive_impact_factor": 4.34, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 154, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=154" + }, + { + "id": "zh:长江流域资源与环境", + "lang": "zh", + "name": "长江流域资源与环境", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 5.364, + "comprehensive_impact_factor": 3.609, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 154, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=154" + }, + { + "id": "zh:应用生态学报", + "lang": "zh", + "name": "应用生态学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 5.047, + "comprehensive_impact_factor": 3.296, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:中国生态农业学报-中英文", + "lang": "zh", + "name": "中国生态农业学报(中英文)", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 5.034, + "comprehensive_impact_factor": 3.311, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:环境科学研究", + "lang": "zh", + "name": "环境科学研究", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.848, + "comprehensive_impact_factor": 3.716, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 155, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=155" + }, + { + "id": "zh:农业现代化研究", + "lang": "zh", + "name": "农业现代化研究", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.842, + "comprehensive_impact_factor": 3.032, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 87, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=87" + }, + { + "id": "zh:遥感学报", + "lang": "zh", + "name": "遥感学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.799, + "comprehensive_impact_factor": 3.257, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 44, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=44" + }, + { + "id": "zh:农业机械学报", + "lang": "zh", + "name": "农业机械学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.696, + "comprehensive_impact_factor": 3.037, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:水土保持研究", + "lang": "zh", + "name": "水土保持研究", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.651, + "comprehensive_impact_factor": 3.002, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:植物营养与肥料学报", + "lang": "zh", + "name": "植物营养与肥料学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.634, + "comprehensive_impact_factor": 3.17, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:农业资源与环境学报", + "lang": "zh", + "name": "农业资源与环境学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.531, + "comprehensive_impact_factor": 2.88, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 87, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=87" + }, + { + "id": "zh:生态学杂志", + "lang": "zh", + "name": "生态学杂志", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.444, + "comprehensive_impact_factor": 2.907, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:草业学报", + "lang": "zh", + "name": "草业学报", + "research_direction": "林学木材与草业", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.361, + "comprehensive_impact_factor": 2.903, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 96, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=96" + }, + { + "id": "zh:水土保持学报", + "lang": "zh", + "name": "水土保持学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.35, + "comprehensive_impact_factor": 2.863, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:植物生态学报", + "lang": "zh", + "name": "植物生态学报", + "research_direction": "综合与生命科学", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.325, + "comprehensive_impact_factor": 3.063, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:干旱区研究", + "lang": "zh", + "name": "干旱区研究", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.234, + "comprehensive_impact_factor": 3.019, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 46, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=46" + }, + { + "id": "zh:湖泊科学", + "lang": "zh", + "name": "湖泊科学", + "research_direction": "水产渔业与海洋生物", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.222, + "comprehensive_impact_factor": 3.009, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 146, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=146" + }, + { + "id": "zh:农业工程学报", + "lang": "zh", + "name": "农业工程学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.125, + "comprehensive_impact_factor": 3.04, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:干旱区地理", + "lang": "zh", + "name": "干旱区地理", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.03, + "comprehensive_impact_factor": 2.699, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:中国水稻科学", + "lang": "zh", + "name": "中国水稻科学", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.024, + "comprehensive_impact_factor": 2.887, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 91, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=91" + }, + { + "id": "zh:草地学报", + "lang": "zh", + "name": "草地学报", + "research_direction": "林学木材与草业", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.007, + "comprehensive_impact_factor": 2.893, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 96, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=96" + }, + { + "id": "zh:食品科学", + "lang": "zh", + "name": "食品科学", + "research_direction": "食品科学营养与安全", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.002, + "comprehensive_impact_factor": 2.806, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 138, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=138" + }, + { + "id": "zh:作物学报", + "lang": "zh", + "name": "作物学报", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.968, + "comprehensive_impact_factor": 2.735, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 91, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=91" + }, + { + "id": "zh:中国草地学报", + "lang": "zh", + "name": "中国草地学报", + "research_direction": "林学木材与草业", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.915, + "comprehensive_impact_factor": 2.805, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 96, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=96" + }, + { + "id": "zh:土壤通报", + "lang": "zh", + "name": "土壤通报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.849, + "comprehensive_impact_factor": 2.571, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:中国农业科学", + "lang": "zh", + "name": "中国农业科学", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.804, + "comprehensive_impact_factor": 2.673, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 87, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=87" + }, + { + "id": "zh:中国环境科学", + "lang": "zh", + "name": "中国环境科学", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.741, + "comprehensive_impact_factor": 2.694, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 155, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=155" + }, + { + "id": "zh:生态环境学报", + "lang": "zh", + "name": "生态环境学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.668, + "comprehensive_impact_factor": 2.693, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:中国沙漠", + "lang": "zh", + "name": "中国沙漠", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.639, + "comprehensive_impact_factor": 2.611, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:中南林业科技大学学报", + "lang": "zh", + "name": "中南林业科技大学学报", + "research_direction": "林学木材与草业", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.594, + "comprehensive_impact_factor": 2.56, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 94, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=94" + }, + { + "id": "zh:中国科学-生命科学", + "lang": "zh", + "name": "中国科学:生命科学", + "research_direction": "综合与生命科学", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.488, + "comprehensive_impact_factor": 2.236, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:中国农业大学学报", + "lang": "zh", + "name": "中国农业大学学报", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.478, + "comprehensive_impact_factor": 2.188, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 87, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=87" + }, + { + "id": "zh:生物多样性", + "lang": "zh", + "name": "生物多样性", + "research_direction": "综合与生命科学", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.451, + "comprehensive_impact_factor": 2.646, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:菌物学报", + "lang": "zh", + "name": "菌物学报", + "research_direction": "综合与生命科学", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.392, + "comprehensive_impact_factor": 2.697, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:中国农业气象", + "lang": "zh", + "name": "中国农业气象", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.355, + "comprehensive_impact_factor": 2.541, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:动物营养学报", + "lang": "zh", + "name": "动物营养学报", + "research_direction": "畜牧兽医与动物营养", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.352, + "comprehensive_impact_factor": 2.429, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 96, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=96" + }, + { + "id": "zh:土壤", + "lang": "zh", + "name": "土壤", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.351, + "comprehensive_impact_factor": 2.372, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:林产工业", + "lang": "zh", + "name": "林产工业", + "research_direction": "林学木材与草业", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.319, + "comprehensive_impact_factor": 2.901, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 140, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=140" + }, + { + "id": "zh:农业环境科学学报", + "lang": "zh", + "name": "农业环境科学学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.316, + "comprehensive_impact_factor": 2.25, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 155, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=155" + }, + { + "id": "zh:环境保护", + "lang": "zh", + "name": "环境保护", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.296, + "comprehensive_impact_factor": 2.218, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 155, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=155" + }, + { + "id": "zh:水土保持通报", + "lang": "zh", + "name": "水土保持通报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.17, + "comprehensive_impact_factor": 2.225, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + } + ], + "meta": { + "total": 277, + "page": 1, + "size": 50, + "lang": "zh", + "domain": "", + "cas_partition": "", + "q": "", + "domains": [ + "农学作物与种质", + "生态环境与自然资源", + "综合与生命科学", + "畜牧兽医与动物营养", + "食品科学营养与安全", + "水产渔业与海洋生物", + "土壤肥料与农业环境", + "林学木材与草业", + "园艺果树与茶学", + "植物保护与昆虫" + ], + "data_source_note": "指标:国内自然科学期刊年报2024版(统计年2023,official,含复合/综合IF两口径);中文期刊不按中科院分区口径列示;国内IF与JIF统计源不同,不可混排。", + "data_imported": true + }, + "error": null +} \ No newline at end of file diff --git a/review_service/data/journals/smoke/3_q_nature.json b/review_service/data/journals/smoke/3_q_nature.json new file mode 100644 index 0000000..fe8c79c --- /dev/null +++ b/review_service/data/journals/smoke/3_q_nature.json @@ -0,0 +1,1716 @@ +{ + "ok": true, + "items": [ + { + "id": "en:1740-1526", + "lang": "en", + "name": "NATURE REVIEWS MICROBIOLOGY", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 103.3, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1740-1526", + "eissn": "1740-1534", + "jcr_disciplines": [ + "MICROBIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1474-1776", + "lang": "en", + "name": "NATURE REVIEWS DRUG DISCOVERY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 101.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1474-1776", + "eissn": "1474-1784", + "jcr_disciplines": [ + "BIOTECHNOLOGY & APPLIED MICROBIOLOGY(SCIE)", + "PHARMACOLOGY & PHARMACY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1471-0072", + "lang": "en", + "name": "NATURE REVIEWS MOLECULAR CELL BIOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 90.2, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1471-0072", + "eissn": "1471-0080", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-4774", + "lang": "en", + "name": "Nature Reviews Clinical Oncology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 83.2, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-4774", + "eissn": "1759-4782", + "jcr_disciplines": [ + "ONCOLOGY(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-earth-environment", + "lang": "en", + "name": "Nature Reviews Earth & Environment", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 71.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2662-138X", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(SCIE)", + "GEOSCIENCES, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1474-175X", + "lang": "en", + "name": "NATURE REVIEWS CANCER", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 66.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1474-175X", + "eissn": "1474-1768", + "jcr_disciplines": [ + "ONCOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1474-1733", + "lang": "en", + "name": "NATURE REVIEWS IMMUNOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 60.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1474-1733", + "eissn": "1474-1741", + "jcr_disciplines": [ + "IMMUNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2056-676X", + "lang": "en", + "name": "Nature Reviews Disease Primers", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 60.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "2056-676X", + "eissn": "2056-676X", + "jcr_disciplines": [ + "MEDICINE, GENERAL & INTERNAL(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-methods-primers", + "lang": "en", + "name": "Nature Reviews Methods Primers", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 56.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2662-8449", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1471-0056", + "lang": "en", + "name": "NATURE REVIEWS GENETICS", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 52.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1471-0056", + "eissn": "1471-0064", + "jcr_disciplines": [ + "GENETICS & HEREDITY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-chemistry", + "lang": "en", + "name": "Nature Reviews Chemistry", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 51.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2397-3358", + "jcr_disciplines": [ + "CHEMISTRY, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5045", + "lang": "en", + "name": "Nature Reviews Gastroenterology & Hepatology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 51.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5045", + "eissn": "1759-5053", + "jcr_disciplines": [ + "GASTROENTEROLOGY & HEPATOLOGY(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1078-8956", + "lang": "en", + "name": "NATURE MEDICINE", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 50.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1078-8956", + "eissn": "1546-170X", + "jcr_disciplines": [ + "BIOCHEMISTRY & MOLECULAR BIOLOGY(SCIE)", + "CELL BIOLOGY(SCIE)", + "MEDICINE, RESEARCH & EXPERIMENTAL(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0028-0836", + "lang": "en", + "name": "NATURE", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 48.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0028-0836", + "eissn": "1476-4687", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5002", + "lang": "en", + "name": "Nature Reviews Cardiology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 44.2, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5002", + "eissn": "1759-5010", + "jcr_disciplines": [ + "CARDIAC & CARDIOVASCULAR SYSTEMS(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5029", + "lang": "en", + "name": "Nature Reviews Endocrinology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 42.3, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5029", + "eissn": "1759-5037", + "jcr_disciplines": [ + "ENDOCRINOLOGY & METABOLISM(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1087-0156", + "lang": "en", + "name": "NATURE BIOTECHNOLOGY", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 41.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1087-0156", + "eissn": "1546-1696", + "jcr_disciplines": [ + "BIOTECHNOLOGY & APPLIED MICROBIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5061", + "lang": "en", + "name": "Nature Reviews Nephrology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 39.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5061", + "eissn": "1759-507X", + "jcr_disciplines": [ + "UROLOGY & NEPHROLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-bioengineering", + "lang": "en", + "name": "Nature Reviews Bioengineering", + "research_direction": "微生物真菌与生物技术", + "cas_partition": null, + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 37.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "未检得", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2731-6092", + "jcr_disciplines": [ + "ENGINEERING, BIOMEDICAL(ESCI)", + "MATERIALS SCIENCE, BIOMATERIALS(ESCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": null, + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-4790", + "lang": "en", + "name": "Nature Reviews Rheumatology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 32.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-4790", + "eissn": "1759-4804", + "jcr_disciplines": [ + "RHEUMATOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1548-7091", + "lang": "en", + "name": "NATURE METHODS", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 32.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1548-7091", + "eissn": "1548-7105", + "jcr_disciplines": [ + "BIOCHEMICAL RESEARCH METHODS(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1061-4036", + "lang": "en", + "name": "NATURE GENETICS", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 29.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1061-4036", + "eissn": "1546-1718", + "jcr_disciplines": [ + "GENETICS & HEREDITY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-cancer", + "lang": "en", + "name": "Nature Cancer", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 28.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2662-1347", + "jcr_disciplines": [ + "ONCOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1529-2908", + "lang": "en", + "name": "NATURE IMMUNOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1529-2908", + "eissn": "1529-2916", + "jcr_disciplines": [ + "IMMUNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1758-678X", + "lang": "en", + "name": "Nature Climate Change", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1758-678X", + "eissn": "1758-6798", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(SCIE)", + "ENVIRONMENTAL STUDIES(SSCI)", + "METEOROLOGY & ATMOSPHERIC SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2398-9629", + "lang": "en", + "name": "Nature Sustainability", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2398-9629", + "eissn": "2398-9629", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(SCIE)", + "ENVIRONMENTAL STUDIES(SSCI)", + "GREEN & SUSTAINABLE SCIENCE & TECHNOLOGY(SSCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2157-846X", + "lang": "en", + "name": "Nature Biomedical Engineering", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 26.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2157-846X", + "eissn": "2157-846X", + "jcr_disciplines": [ + "ENGINEERING, BIOMEDICAL(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1471-003X", + "lang": "en", + "name": "NATURE REVIEWS NEUROSCIENCE", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 26.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1471-003X", + "eissn": "1471-0048", + "jcr_disciplines": [ + "NEUROSCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-water", + "lang": "en", + "name": "Nature Water", + "research_direction": "生态环境与保护", + "cas_partition": null, + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 24.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "未检得", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2731-6084", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(ESCI)", + "WATER RESOURCES(ESCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": null, + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-food", + "lang": "en", + "name": "Nature Food", + "research_direction": "食品营养与安全", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 21.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2662-1355", + "jcr_disciplines": [ + "FOOD SCIENCE & TECHNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-metabolism", + "lang": "en", + "name": "Nature Metabolism", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2522-5812", + "jcr_disciplines": [ + "ENDOCRINOLOGY & METABOLISM(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1097-6256", + "lang": "en", + "name": "NATURE NEUROSCIENCE", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1097-6256", + "eissn": "1546-1726", + "jcr_disciplines": [ + "NEUROSCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1465-7392", + "lang": "en", + "name": "NATURE CELL BIOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 19.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1465-7392", + "eissn": "1476-4679", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-aging", + "lang": "en", + "name": "Nature Aging", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 19.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2662-8465", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)", + "GERIATRICS & GERONTOLOGY(SCIE)", + "NEUROSCIENCES(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2058-5276", + "lang": "en", + "name": "Nature Microbiology", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 19.4, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2058-5276", + "eissn": "2058-5276", + "jcr_disciplines": [ + "MICROBIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1752-0894", + "lang": "en", + "name": "Nature Geoscience", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 16.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1752-0894", + "eissn": "1752-0908", + "jcr_disciplines": [ + "GEOSCIENCES, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1754-2189", + "lang": "en", + "name": "Nature Protocols", + "research_direction": "遗传组学与计算生物", + "cas_partition": "2区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 16.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1754-2189", + "eissn": "1750-2799", + "jcr_disciplines": [ + "BIOCHEMICAL RESEARCH METHODS(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2397-3374", + "lang": "en", + "name": "Nature Human Behaviour", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 15.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2397-3374", + "eissn": "2397-3374", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)", + "NEUROSCIENCES(SCIE)", + "PSYCHOLOGY, EXPERIMENTAL(SSCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-communications", + "lang": "en", + "name": "Nature Communications", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 15.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2041-1723", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-4812", + "lang": "en", + "name": "Nature Reviews Urology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 14.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-4812", + "eissn": "1759-4820", + "jcr_disciplines": [ + "UROLOGY & NEPHROLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2397-334X", + "lang": "en", + "name": "Nature Ecology & Evolution", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 14.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2397-334X", + "eissn": "2397-334X", + "jcr_disciplines": [ + "ECOLOGY(SCIE)", + "EVOLUTIONARY BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1552-4450", + "lang": "en", + "name": "Nature Chemical Biology", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 13.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1552-4450", + "eissn": "1552-4469", + "jcr_disciplines": [ + "BIOCHEMISTRY & MOLECULAR BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2055-026X", + "lang": "en", + "name": "Nature Plants", + "research_direction": "植物科学与分子育种", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 13.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2055-026X", + "eissn": "2055-0278", + "jcr_disciplines": [ + "PLANT SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1545-9993", + "lang": "en", + "name": "NATURE STRUCTURAL & MOLECULAR BIOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 10.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1545-9993", + "eissn": "1545-9985", + "jcr_disciplines": [ + "BIOCHEMISTRY & MOLECULAR BIOLOGY(SCIE)", + "BIOPHYSICS(SCIE)", + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-mental-health", + "lang": "en", + "name": "Nature Mental Health", + "research_direction": "细胞分子发育与生理", + "cas_partition": null, + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 8.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "未检得", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2731-6076", + "jcr_disciplines": [ + "PSYCHIATRY(ESCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": null, + "data_source_label": "JIF来源", + "data_source_url": null + } + ], + "meta": { + "total": 45, + "page": 1, + "size": 50, + "lang": "en", + "domain": "", + "cas_partition": "", + "q": "nature", + "domains": [ + "细胞分子发育与生理", + "生态环境与保护", + "微生物真菌与生物技术", + "农学作物与种质", + "遗传组学与计算生物", + "植物科学与分子育种", + "水产渔业与海洋生物", + "食品营养与安全", + "植物保护与昆虫", + "畜牧动物营养与繁殖", + "土壤肥料与地球生物化学", + "林业木材与草业", + "兽医与寄生虫", + "综合与交叉", + "园艺果树与采后" + ], + "data_source_note": "分区:2025年中科院公开表(official);JIF:2024 JCR,由2025版JCR发布(official);整理日期2026-10-10。空白=来源未给值≠0;研究方向/期刊标记/文章类型为导航标签,非官方评级。", + "data_imported": true + }, + "error": null +} \ No newline at end of file diff --git a/review_service/data/journals/smoke/4_partition1_en.json b/review_service/data/journals/smoke/4_partition1_en.json new file mode 100644 index 0000000..ea51ea9 --- /dev/null +++ b/review_service/data/journals/smoke/4_partition1_en.json @@ -0,0 +1,1901 @@ +{ + "ok": true, + "items": [ + { + "id": "en:1740-1526", + "lang": "en", + "name": "NATURE REVIEWS MICROBIOLOGY", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 103.3, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1740-1526", + "eissn": "1740-1534", + "jcr_disciplines": [ + "MICROBIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1474-1776", + "lang": "en", + "name": "NATURE REVIEWS DRUG DISCOVERY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 101.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1474-1776", + "eissn": "1474-1784", + "jcr_disciplines": [ + "BIOTECHNOLOGY & APPLIED MICROBIOLOGY(SCIE)", + "PHARMACOLOGY & PHARMACY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1471-0072", + "lang": "en", + "name": "NATURE REVIEWS MOLECULAR CELL BIOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 90.2, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1471-0072", + "eissn": "1471-0080", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-4774", + "lang": "en", + "name": "Nature Reviews Clinical Oncology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 83.2, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-4774", + "eissn": "1759-4782", + "jcr_disciplines": [ + "ONCOLOGY(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-earth-environment", + "lang": "en", + "name": "Nature Reviews Earth & Environment", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 71.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2662-138X", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(SCIE)", + "GEOSCIENCES, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1474-175X", + "lang": "en", + "name": "NATURE REVIEWS CANCER", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 66.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1474-175X", + "eissn": "1474-1768", + "jcr_disciplines": [ + "ONCOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1474-1733", + "lang": "en", + "name": "NATURE REVIEWS IMMUNOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 60.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1474-1733", + "eissn": "1474-1741", + "jcr_disciplines": [ + "IMMUNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2056-676X", + "lang": "en", + "name": "Nature Reviews Disease Primers", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 60.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "2056-676X", + "eissn": "2056-676X", + "jcr_disciplines": [ + "MEDICINE, GENERAL & INTERNAL(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-methods-primers", + "lang": "en", + "name": "Nature Reviews Methods Primers", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 56.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2662-8449", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1471-0056", + "lang": "en", + "name": "NATURE REVIEWS GENETICS", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 52.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1471-0056", + "eissn": "1471-0064", + "jcr_disciplines": [ + "GENETICS & HEREDITY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-reviews-chemistry", + "lang": "en", + "name": "Nature Reviews Chemistry", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 51.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": null, + "eissn": "2397-3358", + "jcr_disciplines": [ + "CHEMISTRY, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5045", + "lang": "en", + "name": "Nature Reviews Gastroenterology & Hepatology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 51.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5045", + "eissn": "1759-5053", + "jcr_disciplines": [ + "GASTROENTEROLOGY & HEPATOLOGY(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1078-8956", + "lang": "en", + "name": "NATURE MEDICINE", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 50.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1078-8956", + "eissn": "1546-170X", + "jcr_disciplines": [ + "BIOCHEMISTRY & MOLECULAR BIOLOGY(SCIE)", + "CELL BIOLOGY(SCIE)", + "MEDICINE, RESEARCH & EXPERIMENTAL(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0028-0836", + "lang": "en", + "name": "NATURE", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 48.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0028-0836", + "eissn": "1476-4687", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0036-8075", + "lang": "en", + "name": "SCIENCE", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 45.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Science / AAAS", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0036-8075", + "eissn": "1095-9203", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1535-6108", + "lang": "en", + "name": "CANCER CELL", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 44.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1535-6108", + "eissn": "1878-3686", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)", + "ONCOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5002", + "lang": "en", + "name": "Nature Reviews Cardiology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 44.2, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5002", + "eissn": "1759-5010", + "jcr_disciplines": [ + "CARDIAC & CARDIOVASCULAR SYSTEMS(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0092-8674", + "lang": "en", + "name": "CELL", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 42.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0092-8674", + "eissn": "1097-4172", + "jcr_disciplines": [ + "BIOCHEMISTRY & MOLECULAR BIOLOGY(SCIE)", + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5029", + "lang": "en", + "name": "Nature Reviews Endocrinology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 42.3, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5029", + "eissn": "1759-5037", + "jcr_disciplines": [ + "ENDOCRINOLOGY & METABOLISM(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1087-0156", + "lang": "en", + "name": "NATURE BIOTECHNOLOGY", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 41.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1087-0156", + "eissn": "1546-1696", + "jcr_disciplines": [ + "BIOTECHNOLOGY & APPLIED MICROBIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-5061", + "lang": "en", + "name": "Nature Reviews Nephrology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 39.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-5061", + "eissn": "1759-507X", + "jcr_disciplines": [ + "UROLOGY & NEPHROLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2542-4351", + "lang": "en", + "name": "Joule", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 35.4, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2542-4351", + "eissn": "2542-4351", + "jcr_disciplines": [ + "CHEMISTRY, PHYSICAL(SCIE)", + "ENERGY & FUELS(SCIE)", + "MATERIALS SCIENCE, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1759-4790", + "lang": "en", + "name": "Nature Reviews Rheumatology", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 32.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1759-4790", + "eissn": "1759-4804", + "jcr_disciplines": [ + "RHEUMATOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1548-7091", + "lang": "en", + "name": "NATURE METHODS", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 32.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1548-7091", + "eissn": "1548-7105", + "jcr_disciplines": [ + "BIOCHEMICAL RESEARCH METHODS(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1550-4131", + "lang": "en", + "name": "Cell Metabolism", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 30.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1550-4131", + "eissn": "1932-7420", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)", + "ENDOCRINOLOGY & METABOLISM(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1061-4036", + "lang": "en", + "name": "NATURE GENETICS", + "research_direction": "遗传组学与计算生物", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 29.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1061-4036", + "eissn": "1546-1718", + "jcr_disciplines": [ + "GENETICS & HEREDITY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-cancer", + "lang": "en", + "name": "Nature Cancer", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 28.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2662-1347", + "jcr_disciplines": [ + "ONCOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1529-2908", + "lang": "en", + "name": "NATURE IMMUNOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1529-2908", + "eissn": "1529-2916", + "jcr_disciplines": [ + "IMMUNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2470-9476", + "lang": "en", + "name": "Science Robotics", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Science / AAAS", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2470-9476", + "eissn": "2470-9476", + "jcr_disciplines": [ + "ROBOTICS(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1758-678X", + "lang": "en", + "name": "Nature Climate Change", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1758-678X", + "eissn": "1758-6798", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(SCIE)", + "ENVIRONMENTAL STUDIES(SSCI)", + "METEOROLOGY & ATMOSPHERIC SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2398-9629", + "lang": "en", + "name": "Nature Sustainability", + "research_direction": "生态环境与保护", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 27.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2398-9629", + "eissn": "2398-9629", + "jcr_disciplines": [ + "ENVIRONMENTAL SCIENCES(SCIE)", + "ENVIRONMENTAL STUDIES(SSCI)", + "GREEN & SUSTAINABLE SCIENCE & TECHNOLOGY(SSCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2157-846X", + "lang": "en", + "name": "Nature Biomedical Engineering", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 26.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2157-846X", + "eissn": "2157-846X", + "jcr_disciplines": [ + "ENGINEERING, BIOMEDICAL(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1471-003X", + "lang": "en", + "name": "NATURE REVIEWS NEUROSCIENCE", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 26.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1471-003X", + "eissn": "1471-0048", + "jcr_disciplines": [ + "NEUROSCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1543-5008", + "lang": "en", + "name": "Annual Review of Plant Biology", + "research_direction": "植物科学与分子育种", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 26.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1543-5008", + "eissn": "1545-2123", + "jcr_disciplines": [ + "PLANT SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1074-7613", + "lang": "en", + "name": "Immunity", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 26.3, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1074-7613", + "eissn": "1097-4180", + "jcr_disciplines": [ + "IMMUNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1001-0602", + "lang": "en", + "name": "CELL RESEARCH", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 25.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1001-0602", + "eissn": "1748-7838", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2666-6758", + "lang": "en", + "name": "Innovation", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 25.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2666-6758", + "eissn": "2666-6758", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(ESCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1560-2745", + "lang": "en", + "name": "FUNGAL DIVERSITY", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 24.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1560-2745", + "eissn": "1878-9129", + "jcr_disciplines": [ + "MYCOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1674-2052", + "lang": "en", + "name": "Molecular Plant", + "research_direction": "植物科学与分子育种", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 24.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1674-2052", + "eissn": "1752-9867", + "jcr_disciplines": [ + "BIOCHEMISTRY & MOLECULAR BIOLOGY(SCIE)", + "PLANT SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-food", + "lang": "en", + "name": "Nature Food", + "research_direction": "食品营养与安全", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 21.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2662-1355", + "jcr_disciplines": [ + "FOOD SCIENCE & TECHNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2095-9273", + "lang": "en", + "name": "Science Bulletin", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 21.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2095-9273", + "eissn": "2095-9281", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1360-1385", + "lang": "en", + "name": "TRENDS IN PLANT SCIENCE", + "research_direction": "植物科学与分子育种", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "1360-1385", + "eissn": "1878-4372", + "jcr_disciplines": [ + "PLANT SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-metabolism", + "lang": "en", + "name": "Nature Metabolism", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2522-5812", + "jcr_disciplines": [ + "ENDOCRINOLOGY & METABOLISM(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1934-5909", + "lang": "en", + "name": "Cell Stem Cell", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.4, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1934-5909", + "eissn": "1875-9777", + "jcr_disciplines": [ + "CELL & TISSUE ENGINEERING(SCIE)", + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1097-6256", + "lang": "en", + "name": "NATURE NEUROSCIENCE", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 20.0, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1097-6256", + "eissn": "1546-1726", + "jcr_disciplines": [ + "NEUROSCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0165-6147", + "lang": "en", + "name": "TRENDS IN PHARMACOLOGICAL SCIENCES", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 19.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "综述为主", + "issn": "0165-6147", + "eissn": "1873-3735", + "jcr_disciplines": [ + "PHARMACOLOGY & PHARMACY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2451-9294", + "lang": "en", + "name": "Chem", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 19.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2451-9294", + "eissn": "2451-9294", + "jcr_disciplines": [ + "CHEMISTRY, MULTIDISCIPLINARY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1465-7392", + "lang": "en", + "name": "NATURE CELL BIOLOGY", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 19.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1465-7392", + "eissn": "1476-4679", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-aging", + "lang": "en", + "name": "Nature Aging", + "research_direction": "细胞分子发育与生理", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 19.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2662-8465", + "jcr_disciplines": [ + "CELL BIOLOGY(SCIE)", + "GERIATRICS & GERONTOLOGY(SCIE)", + "NEUROSCIENCES(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2058-5276", + "lang": "en", + "name": "Nature Microbiology", + "research_direction": "微生物真菌与生物技术", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 19.4, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2058-5276", + "eissn": "2058-5276", + "jcr_disciplines": [ + "MICROBIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + } + ], + "meta": { + "total": 233, + "page": 1, + "size": 50, + "lang": "en", + "domain": "", + "cas_partition": "1区", + "q": "", + "domains": [ + "细胞分子发育与生理", + "生态环境与保护", + "微生物真菌与生物技术", + "农学作物与种质", + "遗传组学与计算生物", + "植物科学与分子育种", + "水产渔业与海洋生物", + "食品营养与安全", + "植物保护与昆虫", + "畜牧动物营养与繁殖", + "土壤肥料与地球生物化学", + "林业木材与草业", + "兽医与寄生虫", + "综合与交叉", + "园艺果树与采后" + ], + "data_source_note": "分区:2025年中科院公开表(official);JIF:2024 JCR,由2025版JCR发布(official);整理日期2026-10-10。空白=来源未给值≠0;研究方向/期刊标记/文章类型为导航标签,非官方评级。", + "data_imported": true + }, + "error": null +} \ No newline at end of file diff --git a/review_service/data/journals/smoke/5_domain.json b/review_service/data/journals/smoke/5_domain.json new file mode 100644 index 0000000..6e738a6 --- /dev/null +++ b/review_service/data/journals/smoke/5_domain.json @@ -0,0 +1,815 @@ +{ + "ok": true, + "items": [ + { + "id": "en:0028-0836", + "lang": "en", + "name": "NATURE", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 48.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0028-0836", + "eissn": "1476-4687", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0036-8075", + "lang": "en", + "name": "SCIENCE", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 45.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Science / AAAS", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0036-8075", + "eissn": "1095-9203", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0092-8674", + "lang": "en", + "name": "CELL", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 42.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0092-8674", + "eissn": "1097-4172", + "jcr_disciplines": [ + "BIOCHEMISTRY & MOLECULAR BIOLOGY(SCIE)", + "CELL BIOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2666-6758", + "lang": "en", + "name": "Innovation", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 25.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2666-6758", + "eissn": "2666-6758", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(ESCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2095-9273", + "lang": "en", + "name": "Science Bulletin", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 21.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2095-9273", + "eissn": "2095-9281", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2095-5138", + "lang": "en", + "name": "National Science Review", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 17.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2095-5138", + "eissn": "2053-714X", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:nature-communications", + "lang": "en", + "name": "Nature Communications", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 15.7, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2041-1723", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:advanced-science", + "lang": "en", + "name": "Advanced Science", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 14.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2198-3844", + "jcr_disciplines": [ + "CHEMISTRY, MULTIDISCIPLINARY(SCIE)", + "MATERIALS SCIENCE, MULTIDISCIPLINARY(SCIE)", + "NANOSCIENCE & NANOTECHNOLOGY(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2375-2548", + "lang": "en", + "name": "Science Advances", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 12.5, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Science / AAAS", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2375-2548", + "eissn": "2375-2548", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2096-5168", + "lang": "en", + "name": "Research", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 10.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已按Clarivate勘误更新", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "Science Partner Journals(合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2096-5168", + "eissn": "2639-5274", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": "2024 JIF采用2025-10-15官方重载修订值。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://journalcitationreports.zendesk.com/hc/en-gb/articles/36310787349521-2025", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:0027-8424", + "lang": "en", + "name": "PROCEEDINGS OF THE NATIONAL ACADEMY OF SCIENCES OF THE UNITED STATES OF AMERICA", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 9.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "经典专业刊", + "article_type": "研究/方法/综合", + "issn": "0027-8424", + "eissn": "1091-6490", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:scientific-data", + "lang": "en", + "name": "Scientific Data", + "research_direction": "综合与交叉", + "cas_partition": "2区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 6.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "否", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2052-4463", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:iscience", + "lang": "en", + "name": "iScience", + "research_direction": "综合与交叉", + "cas_partition": "2区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 4.1, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "否", + "publisher_series": "Cell Press(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2589-0042", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2047-217X", + "lang": "en", + "name": "GigaScience", + "research_direction": "综合与交叉", + "cas_partition": "2区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 3.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "否", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2047-217X", + "eissn": "2047-217X", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2045-2322", + "lang": "en", + "name": "Scientific Reports", + "research_direction": "综合与交叉", + "cas_partition": "3区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 3.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "否", + "publisher_series": "Nature Portfolio(含合作刊)", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2045-2322", + "eissn": "2045-2322", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:pnas-nexus", + "lang": "en", + "name": "PNAS Nexus", + "research_direction": "综合与交叉", + "cas_partition": "3区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 3.8, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "否", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2752-6542", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(ESCI)", + "SOCIAL SCIENCES, INTERDISCIPLINARY(ESCI)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:heliyon", + "lang": "en", + "name": "Heliyon", + "research_direction": "综合与交叉", + "cas_partition": "4区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 3.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "否", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": null, + "eissn": "2405-8440", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2054-5703", + "lang": "en", + "name": "Royal Society Open Science", + "research_direction": "综合与交叉", + "cas_partition": "3区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 2.9, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "否", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2054-5703", + "eissn": "2054-5703", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:1932-6203", + "lang": "en", + "name": "PLoS One", + "research_direction": "综合与交叉", + "cas_partition": "3区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 2.6, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "否", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "1932-6203", + "eissn": "1932-6203", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2167-8359", + "lang": "en", + "name": "PeerJ", + "research_direction": "综合与交叉", + "cas_partition": "3区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": 2.4, + "jif_year": 2024, + "jif_note": null, + "jif_check_status": "已匹配公开汇编", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "否", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2167-8359", + "eissn": "2167-8359", + "jcr_disciplines": [ + "MULTIDISCIPLINARY SCIENCES(SCIE)" + ], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": "official", + "jif_source_url": "https://github.com/yongqianxiao/share_repo/blob/master/JCR/2024JCR%E5%AE%8C%E6%95%B4%E7%89%88%EF%BC%882025.6.18%E5%8F%91%E5%B8%83%EF%BC%89.xlsx", + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + }, + { + "id": "en:2050-084X", + "lang": "en", + "name": "eLife", + "research_direction": "综合与交叉", + "cas_partition": "1区", + "cas_partition_note": null, + "cas_partition_year": 2025, + "jif": null, + "jif_year": 2024, + "jif_note": "未被2024 JCR收录", + "jif_check_status": "源表标N/A", + "composite_impact_factor": null, + "comprehensive_impact_factor": null, + "metric_year": null, + "metric_report_year": null, + "metric_caliber": null, + "annual_report_page": null, + "top_flag": "是", + "publisher_series": "其他", + "journal_mark": "领域期刊/新兴刊", + "article_type": "研究/方法/综合", + "issn": "2050-084X", + "eissn": "2050-084X", + "jcr_disciplines": [ + "BIOLOGY(ESCI)" + ], + "supplement_note": "源表2024 JIF为N/A;不可用历史IF代填。", + "evidence_note": null, + "official_url": null, + "partition_source": "official", + "jif_source": null, + "jif_source_url": null, + "partition_source_url": "https://huaxue.hebtu.edu.cn/a/2025/09/23/A5A5BBD96F6B4410B87B6D4C43BDFD63.html", + "data_source_label": "JIF来源", + "data_source_url": null + } + ], + "meta": { + "total": 21, + "page": 1, + "size": 50, + "lang": "en", + "domain": "综合与交叉", + "cas_partition": "", + "q": "", + "domains": [ + "细胞分子发育与生理", + "生态环境与保护", + "微生物真菌与生物技术", + "农学作物与种质", + "遗传组学与计算生物", + "植物科学与分子育种", + "水产渔业与海洋生物", + "食品营养与安全", + "植物保护与昆虫", + "畜牧动物营养与繁殖", + "土壤肥料与地球生物化学", + "林业木材与草业", + "兽医与寄生虫", + "综合与交叉", + "园艺果树与采后" + ], + "data_source_note": "分区:2025年中科院公开表(official);JIF:2024 JCR,由2025版JCR发布(official);整理日期2026-10-10。空白=来源未给值≠0;研究方向/期刊标记/文章类型为导航标签,非官方评级。", + "data_imported": true + }, + "error": null +} \ No newline at end of file diff --git a/review_service/data/journals/smoke/6_zh_composite_desc.json b/review_service/data/journals/smoke/6_zh_composite_desc.json new file mode 100644 index 0000000..e6c6576 --- /dev/null +++ b/review_service/data/journals/smoke/6_zh_composite_desc.json @@ -0,0 +1,1779 @@ +{ + "ok": true, + "items": [ + { + "id": "zh:自然资源学报", + "lang": "zh", + "name": "自然资源学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 10.773, + "comprehensive_impact_factor": 7.725, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:地理学报", + "lang": "zh", + "name": "地理学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 9.926, + "comprehensive_impact_factor": 7.412, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:中国人口-资源与环境", + "lang": "zh", + "name": "中国人口·资源与环境", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 9.53, + "comprehensive_impact_factor": 6.957, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 154, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=154" + }, + { + "id": "zh:地理研究", + "lang": "zh", + "name": "地理研究", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 7.661, + "comprehensive_impact_factor": 5.5, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:资源科学", + "lang": "zh", + "name": "资源科学", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.731, + "comprehensive_impact_factor": 4.962, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:地理科学", + "lang": "zh", + "name": "地理科学", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.614, + "comprehensive_impact_factor": 4.698, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:地理科学进展", + "lang": "zh", + "name": "地理科学进展", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.513, + "comprehensive_impact_factor": 4.532, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:生态学报", + "lang": "zh", + "name": "生态学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.473, + "comprehensive_impact_factor": 4.412, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:土壤学报", + "lang": "zh", + "name": "土壤学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.361, + "comprehensive_impact_factor": 4.262, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:环境科学", + "lang": "zh", + "name": "环境科学", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 6.137, + "comprehensive_impact_factor": 4.34, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 154, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=154" + }, + { + "id": "zh:长江流域资源与环境", + "lang": "zh", + "name": "长江流域资源与环境", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 5.364, + "comprehensive_impact_factor": 3.609, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 154, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=154" + }, + { + "id": "zh:应用生态学报", + "lang": "zh", + "name": "应用生态学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 5.047, + "comprehensive_impact_factor": 3.296, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:中国生态农业学报-中英文", + "lang": "zh", + "name": "中国生态农业学报(中英文)", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 5.034, + "comprehensive_impact_factor": 3.311, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:环境科学研究", + "lang": "zh", + "name": "环境科学研究", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.848, + "comprehensive_impact_factor": 3.716, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 155, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=155" + }, + { + "id": "zh:农业现代化研究", + "lang": "zh", + "name": "农业现代化研究", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.842, + "comprehensive_impact_factor": 3.032, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 87, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=87" + }, + { + "id": "zh:遥感学报", + "lang": "zh", + "name": "遥感学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.799, + "comprehensive_impact_factor": 3.257, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 44, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=44" + }, + { + "id": "zh:农业机械学报", + "lang": "zh", + "name": "农业机械学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.696, + "comprehensive_impact_factor": 3.037, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:水土保持研究", + "lang": "zh", + "name": "水土保持研究", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.651, + "comprehensive_impact_factor": 3.002, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:植物营养与肥料学报", + "lang": "zh", + "name": "植物营养与肥料学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.634, + "comprehensive_impact_factor": 3.17, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:农业资源与环境学报", + "lang": "zh", + "name": "农业资源与环境学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.531, + "comprehensive_impact_factor": 2.88, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 87, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=87" + }, + { + "id": "zh:生态学杂志", + "lang": "zh", + "name": "生态学杂志", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.444, + "comprehensive_impact_factor": 2.907, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:草业学报", + "lang": "zh", + "name": "草业学报", + "research_direction": "林学木材与草业", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.361, + "comprehensive_impact_factor": 2.903, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 96, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=96" + }, + { + "id": "zh:水土保持学报", + "lang": "zh", + "name": "水土保持学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.35, + "comprehensive_impact_factor": 2.863, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:植物生态学报", + "lang": "zh", + "name": "植物生态学报", + "research_direction": "综合与生命科学", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.325, + "comprehensive_impact_factor": 3.063, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:干旱区研究", + "lang": "zh", + "name": "干旱区研究", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.234, + "comprehensive_impact_factor": 3.019, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 46, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=46" + }, + { + "id": "zh:湖泊科学", + "lang": "zh", + "name": "湖泊科学", + "research_direction": "水产渔业与海洋生物", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.222, + "comprehensive_impact_factor": 3.009, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 146, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=146" + }, + { + "id": "zh:农业工程学报", + "lang": "zh", + "name": "农业工程学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.125, + "comprehensive_impact_factor": 3.04, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:干旱区地理", + "lang": "zh", + "name": "干旱区地理", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.03, + "comprehensive_impact_factor": 2.699, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:中国水稻科学", + "lang": "zh", + "name": "中国水稻科学", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.024, + "comprehensive_impact_factor": 2.887, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 91, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=91" + }, + { + "id": "zh:草地学报", + "lang": "zh", + "name": "草地学报", + "research_direction": "林学木材与草业", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.007, + "comprehensive_impact_factor": 2.893, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 96, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=96" + }, + { + "id": "zh:食品科学", + "lang": "zh", + "name": "食品科学", + "research_direction": "食品科学营养与安全", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 4.002, + "comprehensive_impact_factor": 2.806, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 138, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=138" + }, + { + "id": "zh:作物学报", + "lang": "zh", + "name": "作物学报", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.968, + "comprehensive_impact_factor": 2.735, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 91, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=91" + }, + { + "id": "zh:中国草地学报", + "lang": "zh", + "name": "中国草地学报", + "research_direction": "林学木材与草业", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.915, + "comprehensive_impact_factor": 2.805, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 96, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=96" + }, + { + "id": "zh:土壤通报", + "lang": "zh", + "name": "土壤通报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.849, + "comprehensive_impact_factor": 2.571, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:中国农业科学", + "lang": "zh", + "name": "中国农业科学", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.804, + "comprehensive_impact_factor": 2.673, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 87, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=87" + }, + { + "id": "zh:中国环境科学", + "lang": "zh", + "name": "中国环境科学", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.741, + "comprehensive_impact_factor": 2.694, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 155, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=155" + }, + { + "id": "zh:生态环境学报", + "lang": "zh", + "name": "生态环境学报", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.668, + "comprehensive_impact_factor": 2.693, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:中国沙漠", + "lang": "zh", + "name": "中国沙漠", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.639, + "comprehensive_impact_factor": 2.611, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 51, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=51" + }, + { + "id": "zh:中南林业科技大学学报", + "lang": "zh", + "name": "中南林业科技大学学报", + "research_direction": "林学木材与草业", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.594, + "comprehensive_impact_factor": 2.56, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 94, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=94" + }, + { + "id": "zh:中国科学-生命科学", + "lang": "zh", + "name": "中国科学:生命科学", + "research_direction": "综合与生命科学", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.488, + "comprehensive_impact_factor": 2.236, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:中国农业大学学报", + "lang": "zh", + "name": "中国农业大学学报", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.478, + "comprehensive_impact_factor": 2.188, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 87, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=87" + }, + { + "id": "zh:生物多样性", + "lang": "zh", + "name": "生物多样性", + "research_direction": "综合与生命科学", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.451, + "comprehensive_impact_factor": 2.646, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:菌物学报", + "lang": "zh", + "name": "菌物学报", + "research_direction": "综合与生命科学", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.392, + "comprehensive_impact_factor": 2.697, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 52, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=52" + }, + { + "id": "zh:中国农业气象", + "lang": "zh", + "name": "中国农业气象", + "research_direction": "农学作物与种质", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.355, + "comprehensive_impact_factor": 2.541, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:动物营养学报", + "lang": "zh", + "name": "动物营养学报", + "research_direction": "畜牧兽医与动物营养", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.352, + "comprehensive_impact_factor": 2.429, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 96, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=96" + }, + { + "id": "zh:土壤", + "lang": "zh", + "name": "土壤", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.351, + "comprehensive_impact_factor": 2.372, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + }, + { + "id": "zh:林产工业", + "lang": "zh", + "name": "林产工业", + "research_direction": "林学木材与草业", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.319, + "comprehensive_impact_factor": 2.901, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 140, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=140" + }, + { + "id": "zh:农业环境科学学报", + "lang": "zh", + "name": "农业环境科学学报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.316, + "comprehensive_impact_factor": 2.25, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 155, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=155" + }, + { + "id": "zh:环境保护", + "lang": "zh", + "name": "环境保护", + "research_direction": "生态环境与自然资源", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.296, + "comprehensive_impact_factor": 2.218, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 155, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=155" + }, + { + "id": "zh:水土保持通报", + "lang": "zh", + "name": "水土保持通报", + "research_direction": "土壤肥料与农业环境", + "cas_partition": null, + "cas_partition_note": "不按中科院分区口径列示", + "cas_partition_year": null, + "jif": null, + "jif_year": null, + "jif_note": null, + "jif_check_status": "已提取原表", + "composite_impact_factor": 3.17, + "comprehensive_impact_factor": 2.225, + "metric_year": 2023, + "metric_report_year": 2024, + "metric_caliber": "国内年报口径;不与JIF混排", + "annual_report_page": 90, + "top_flag": null, + "publisher_series": null, + "journal_mark": null, + "article_type": null, + "issn": null, + "eissn": null, + "jcr_disciplines": [], + "supplement_note": null, + "evidence_note": null, + "official_url": null, + "partition_source": null, + "jif_source": "official", + "jif_source_url": null, + "partition_source_url": null, + "data_source_label": "年报原页", + "data_source_url": "https://library.sut.edu.cn/WJSC/xkfw/tgzn/sjkslqklb/zhongguoxueshuqikanyingxiangyinzinianbao-zirankexue-2024.pdf#page=90" + } + ], + "meta": { + "total": 277, + "page": 1, + "size": 50, + "lang": "zh", + "domain": "", + "cas_partition": "", + "q": "", + "domains": [ + "农学作物与种质", + "生态环境与自然资源", + "综合与生命科学", + "畜牧兽医与动物营养", + "食品科学营养与安全", + "水产渔业与海洋生物", + "土壤肥料与农业环境", + "林学木材与草业", + "园艺果树与茶学", + "植物保护与昆虫" + ], + "data_source_note": "指标:国内自然科学期刊年报2024版(统计年2023,official,含复合/综合IF两口径);中文期刊不按中科院分区口径列示;国内IF与JIF统计源不同,不可混排。", + "data_imported": true + }, + "error": null +} \ No newline at end of file diff --git a/review_service/data/journals/smoke/7_size500.json b/review_service/data/journals/smoke/7_size500.json new file mode 100644 index 0000000..e425f2b --- /dev/null +++ b/review_service/data/journals/smoke/7_size500.json @@ -0,0 +1,10 @@ +{ + "ok": false, + "items": [], + "meta": null, + "error": { + "code": "VALIDATION", + "message": "size 必须在 1-200,收到 500", + "degraded": false + } +} \ No newline at end of file diff --git a/review_service/data/journals/smoke/8_lang_xx.json b/review_service/data/journals/smoke/8_lang_xx.json new file mode 100644 index 0000000..be5e3a9 --- /dev/null +++ b/review_service/data/journals/smoke/8_lang_xx.json @@ -0,0 +1,10 @@ +{ + "ok": false, + "items": [], + "meta": null, + "error": { + "code": "VALIDATION", + "message": "不支持的 lang='xx',可选:en / zh", + "degraded": false + } +} \ No newline at end of file diff --git a/review_service/data/journals/source.xlsx b/review_service/data/journals/source.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..d40050cf6706b3861a35f789cf38ee60950dcbad GIT binary patch literal 123252 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 literal 0 HcmV?d00001 diff --git a/review_service/data/journals/source_v4.xlsx b/review_service/data/journals/source_v4.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..070cfd12d70e7b6a682b1157f61fbc1e0c6052a0 GIT binary patch literal 193386 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 P&<`S1-XBh&x(D+=oRoK> literal 0 HcmV?d00001 diff --git a/review_service/scripts/import_journals.py b/review_service/scripts/import_journals.py new file mode 100644 index 0000000..aa1f980 --- /dev/null +++ b/review_service/scripts/import_journals.py @@ -0,0 +1,579 @@ +#!/usr/bin/env python3 +"""scripts/import_journals.py —— 期刊目录导入(source_v4.xlsx → SQLite journal_directory)。 + +数据流(本脚本独立拥有 journal_directory 表的 schema,app 层只读不建表): + openpyxl 非 read_only 加载(需要读 cell.hyperlink.target 来源链接) + → 「国际期刊」「中文期刊」两 sheet 按【列名】映射(不按索引,防列序漂移) + → 行级清洗(空→None 绝不填 0;分区数字→"N区";JCR学科→JSON 数组) + → 按 id 幂等 upsert(ON CONFLICT DO UPDATE,重跑 count 不变) + → 对账报告 data/journals/import_report.txt + +v4 源(2026-10-10):JIF=2025 统计年/2026 JCR 发布;中文 IF=2024 统计年/ +年报 2025 版;新增官网三列 + JCR发布年;JCR学科列改名「JCR学科(2024源表)」。 +旧文件 source.xlsx(v2)原样保留为回退点,勿覆盖。 + +schema 迁移(决策①,幂等 + 备份): + 既有表缺列 → PRAGMA table_info 探测后 ALTER TABLE ADD COLUMN,缺哪加哪、 + 重复跑不报错;跑前先 cp review.db review.db.bak-<日期>。 + 新增列:official_url / official_check_status / jcr_release_year。 + official_source 不入库(值全为字面量"官网来源",超链接=官网本身,无信息量)。 + +id 策略(拍板-补充1): + 有 ISSN → "{lang}:{ISSN原样(strip)}"(如 en:0028-0836) + 无 ISSN → "{lang}:{slug(name)}"(casefold + 非词字符折叠为连字符,保留 CJK) + 同 lang 内 id 冲突 → 报告冲突列表并【中止导入】(非零退出,不写库)。 + +"未检得"/空白 区分(拍板-补充2): + 分区空白 → cas_partition=NULL, cas_partition_note=NULL(前端 "—") + 分区"未检得" → cas_partition=NULL, cas_partition_note="未检得"(前端 "— ⓘ") + JIF 空 → jif=NULL + jif_note=核对状态原文(如"2025 JIF未检得/未给值") + 官网空(3 本中文刊未检得)→ official_url=NULL(前端 "—",不生成 ) + + 官网列:v4 已含「官网网址」列(国际 779 + 中文 274),按列名自动映射 + official_url;同时映射 官网核对状态 → official_check_status、 + JCR发布年 → jcr_release_year(仅国际;中文表无此列 → NULL)。 + +禁区:不 import app.*(db.py / recommend / services 零触碰);只用 stdlib sqlite3 + openpyxl。 +用法:python scripts/import_journals.py (cwd 任意;路径按本文件位置推导) +退出码:0 成功;1 id 冲突中止;2 源数据行数与口径不符;3 结构/文件错误。 +""" +from __future__ import annotations + +import json +import os +import re +import sqlite3 +import sys +import time +import unicodedata +from collections import Counter +from datetime import datetime +from pathlib import Path +from typing import Any + +import openpyxl + +# ---- 路径(review_service/scripts/ → parents[1] = review_service)---- +ROOT = Path(__file__).resolve().parents[1] +SOURCE_XLSX = ROOT / "data" / "journals" / "source_v4.xlsx" # v4;v2=source.xlsx 保留回退 +REPORT_TXT = ROOT / "data" / "journals" / "import_report.txt" + +SHEET_INTL = "国际期刊" +SHEET_ZH = "中文期刊" +EXPECT_INTL = 779 # 口径 sheet 声明(v4 不变) +EXPECT_ZH = 277 + +# 官网列(v4 实际列名「官网网址」在首位;其余为历史/备用别名) +OFFICIAL_URL_HEADERS = ("官网网址", "官网", "官方网址", "期刊官网") +# JCR 学科列别名:v4 改名「JCR学科(2024源表)」,v2 为「JCR学科(源表)」 +JCR_DISCIPLINE_HEADERS = ("JCR学科(2024源表)", "JCR学科(源表)") + +# 既有表缺列时的幂等迁移(决策①:缺哪加哪,重复跑不报错) +MIGRATE_COLS = ( + ("official_url", "TEXT"), + ("official_check_status", "TEXT"), + ("jcr_release_year", "INTEGER"), +) + +SCHEMA_SQL = """ +CREATE TABLE IF NOT EXISTS journal_directory ( + id TEXT PRIMARY KEY, + lang TEXT NOT NULL, + name TEXT NOT NULL, + research_direction TEXT, + cas_partition TEXT, + cas_partition_note TEXT, + cas_partition_year INTEGER, + jif REAL, + jif_year INTEGER, + jif_note TEXT, + jif_check_status TEXT, + composite_impact_factor REAL, + comprehensive_impact_factor REAL, + metric_year INTEGER, + metric_report_year INTEGER, + metric_caliber TEXT, + annual_report_page INTEGER, + top_flag TEXT, + publisher_series TEXT, + journal_mark TEXT, + article_type TEXT, + issn TEXT, + eissn TEXT, + jcr_disciplines TEXT, + supplement_note TEXT, + evidence_note TEXT, + official_url TEXT, + official_check_status TEXT, + jcr_release_year INTEGER, + partition_source TEXT, + jif_source TEXT, + jif_source_url TEXT, + partition_source_url TEXT, + data_source_label TEXT, + data_source_url TEXT, + imported_at TEXT +); +CREATE INDEX IF NOT EXISTS idx_dir_lang_name ON journal_directory(lang, name); +CREATE INDEX IF NOT EXISTS idx_dir_lang_jif ON journal_directory(lang, jif); +CREATE INDEX IF NOT EXISTS idx_dir_lang_cif ON journal_directory(lang, composite_impact_factor); +CREATE INDEX IF NOT EXISTS idx_dir_lang_part ON journal_directory(lang, cas_partition); +CREATE INDEX IF NOT EXISTS idx_dir_lang_domain ON journal_directory(lang, research_direction); +""" + +# upsert 列序(除 id 外全部 ON CONFLICT DO UPDATE) +COLS = ( + "lang", "name", "research_direction", "cas_partition", "cas_partition_note", + "cas_partition_year", "jif", "jif_year", "jif_note", "jif_check_status", + "composite_impact_factor", "comprehensive_impact_factor", "metric_year", + "metric_report_year", "metric_caliber", "annual_report_page", "top_flag", + "publisher_series", "journal_mark", "article_type", "issn", "eissn", + "jcr_disciplines", "supplement_note", "evidence_note", "official_url", + "official_check_status", "jcr_release_year", + "partition_source", "jif_source", "jif_source_url", "partition_source_url", + "data_source_label", "data_source_url", "imported_at", +) +UPSERT_SQL = ( + "INSERT INTO journal_directory (id, " + ", ".join(COLS) + ") VALUES (" + + ", ".join("?" for _ in range(len(COLS) + 1)) + ") " + + "ON CONFLICT(id) DO UPDATE SET " + + ", ".join(f"{c}=excluded.{c}" for c in COLS) +) + + +def migrate(conn: sqlite3.Connection) -> tuple[list[str], list[str]]: + """幂等加列(决策①):PRAGMA 探测现有列,缺哪个 ALTER ADD 哪个。""" + existing = {r[1] for r in conn.execute("PRAGMA table_info(journal_directory)")} + added: list[str] = [] + skipped: list[str] = [] + for col, decl in MIGRATE_COLS: + if col in existing: + skipped.append(col) + else: + conn.execute(f"ALTER TABLE journal_directory ADD COLUMN {col} {decl}") + added.append(col) + conn.commit() + return added, skipped + + +# ---- 清洗原语 ---- + +def text(v: Any) -> str | None: + """单元格 → strip 后的文本;空/纯空白 → None(绝不填 0/空串)。""" + if v is None: + return None + s = str(v).strip() + return s or None + + +def to_float(v: Any) -> float | None: + if v is None or (isinstance(v, str) and not v.strip()): + return None + try: + return float(v) + except (TypeError, ValueError): + return None + + +def to_int(v: Any) -> int | None: + f = to_float(v) + if f is None: + return None + return int(f) + + +def slugify(name: str) -> str: + """小写 + 非词字符折叠为连字符;\\w 含 CJK(中文期刊无 ISSN 时的 id 兜底)。""" + s = unicodedata.normalize("NFC", name.strip().casefold()) + s = re.sub(r"[^\w]+", "-", s, flags=re.UNICODE) + s = re.sub(r"-{2,}", "-", s) + return s.strip("-") + + +def make_id(lang: str, name: str, issn: str | None) -> str: + if issn: + return f"{lang}:{issn}" + return f"{lang}:{slugify(name)}" + + +def parse_partition(raw: Any) -> tuple[str | None, str | None]: + """分区 → (cas_partition, note)。数字 1-4 → 'N区';'未检得' → note;空白 → 双 None。""" + if raw is None: + return None, None + if isinstance(raw, (int, float)) and not isinstance(raw, bool): + n = int(raw) + if 1 <= n <= 4: + return f"{n}区", None + return None, None + s = str(raw).strip() + if not s: + return None, None + if "未检得" in s: + return None, "未检得" + m = re.fullmatch(r"([1-4])\s*区?", s) + if m: + return f"{m.group(1)}区", None + return s, None # 未知文本:原样保留(不丢信息) + + +def split_disciplines(raw: Any) -> str | None: + """'A(SCIE);B(SCIE)' → JSON 数组字符串。""" + s = text(raw) + if not s: + return None + parts = [p.strip() for p in s.split(";") if p.strip()] + return json.dumps(parts, ensure_ascii=False) if parts else None + + +def hyperlink_target(cell) -> str | None: + """超链接单元格 → target URL;无链接 → None(需要非 read_only 模式)。""" + try: + target = cell.hyperlink.target if cell.hyperlink is not None else None + except Exception: # noqa: BLE001 + return None + return text(target) + + +# ---- sheet 解析 ---- + +def header_index(ws) -> dict[str, int]: + headers = [text(c.value) for c in ws[1]] + return {h: i for i, h in enumerate(headers) if h is not None} + + +def read_intl(ws, imported_at: str, stats: dict) -> list[tuple]: + """国际期刊 sheet → 行元组(顺序同 COLS 前置 id)。""" + ix = header_index(ws) + for req in ("期刊名称", "研究方向", "中科院分区", "JIF影响因子"): + if req not in ix: + raise SystemExit(f"[结构错误] {SHEET_INTL} 缺列:{req}(实际列:{list(ix)})") + url_col = next((ix[h] for h in OFFICIAL_URL_HEADERS if h in ix), None) + jcr_hdr = next((h for h in JCR_DISCIPLINE_HEADERS if h in ix), None) + stats["official_url_detected"] = url_col is not None + if url_col is not None: + stats["official_url_headers"] = next(h for h in OFFICIAL_URL_HEADERS if h in ix) + + rows: list[tuple] = [] + for row in ws.iter_rows(min_row=2): + if not any(c.value is not None for c in row): + continue # 尾部幻影空行:不计入 skipped + name = text(row[ix["期刊名称"]].value) if ix["期刊名称"] < len(row) else None + if not name: + stats["skipped"] += 1 + continue + issn = text(row[ix["ISSN"]].value) if "ISSN" in ix else None + jif = to_float(row[ix["JIF影响因子"]].value) + check_status = text(row[ix["JIF核对状态"]].value) if "JIF核对状态" in ix else None + official_check = text(row[ix["官网核对状态"]].value) if "官网核对状态" in ix else None + jcr_year = to_int(row[ix["JCR发布年"]].value) if "JCR发布年" in ix else None + part, part_note = parse_partition(row[ix["中科院分区"]].value) + + # JIF 空 → note = 核对状态原文("未检得"/"源表标N/A" 等说明,拍板-补充2) + jif_note = check_status if jif is None else None + + jif_url = hyperlink_target(row[ix["JIF数据来源"]]) if "JIF数据来源" in ix else None + part_url = hyperlink_target(row[ix["分区数据来源"]]) if "分区数据来源" in ix else None + official = None + if url_col is not None and url_col < len(row): + official = text(row[url_col].value) or hyperlink_target(row[url_col]) + + rows.append(( + make_id("en", name, issn), "en", name, + text(row[ix["研究方向"]].value), + part, part_note, + to_int(row[ix["分区版本年"]].value) if "分区版本年" in ix else None, + jif, + to_int(row[ix["JIF统计年"]].value) if "JIF统计年" in ix else None, + jif_note, check_status, + None, None, None, None, None, None, + text(row[ix["Top(源表)"]].value) if "Top(源表)" in ix else None, + text(row[ix["出版系列"]].value) if "出版系列" in ix else None, + text(row[ix["期刊标记"]].value) if "期刊标记" in ix else None, + text(row[ix["文章类型"]].value) if "文章类型" in ix else None, + issn, + text(row[ix["eISSN"]].value) if "eISSN" in ix else None, + split_disciplines(row[ix[jcr_hdr]].value) if jcr_hdr else None, + text(row[ix["补充说明"]].value) if "补充说明" in ix else None, + text(row[ix["补充证据"]].value) if "补充证据" in ix else None, + official, + official_check, + jcr_year, + "official", "official", + jif_url, part_url, + text(row[ix["JIF数据来源"]].value) if "JIF数据来源" in ix else None, + None, # data_source_url(国际表来源即 jif/partition 两链接) + imported_at, + )) + # 统计 + stats["official_total"] += 1 + stats["official_filled"] += 1 if official else 0 + stats["official_check_filled"] += 1 if official_check else 0 + stats["jcr_filled"] += 1 if jcr_year else 0 + if not official: + stats["official_missing"].append(("en", name)) + if jif is None: + stats["jif_missing"].append((name, check_status or "")) + if part is None and part_note == "未检得": + stats["part_notfound"].append(name) + elif part is None: + stats["part_blank"].append(name) + stats["hl_jif"] += 1 if jif_url else 0 + stats["hl_part"] += 1 if part_url else 0 + stats["id_issn" if issn else "id_slug"] += 1 + return rows + + +def read_zh(ws, imported_at: str, stats: dict) -> list[tuple]: + """中文期刊 sheet → 行元组。""" + ix = header_index(ws) + for req in ("中文期刊名称", "复合影响因子", "综合影响因子"): + if req not in ix: + raise SystemExit(f"[结构错误] {SHEET_ZH} 缺列:{req}(实际列:{list(ix)})") + url_col = next((ix[h] for h in OFFICIAL_URL_HEADERS if h in ix), None) + stats["official_url_detected_zh"] = url_col is not None + + rows: list[tuple] = [] + for row in ws.iter_rows(min_row=2): + if not any(c.value is not None for c in row): + continue # 尾部幻影空行:不计入 skipped + name = text(row[ix["中文期刊名称"]].value) + if not name: + stats["skipped"] += 1 + continue + composite = to_float(row[ix["复合影响因子"]].value) + comprehensive = to_float(row[ix["综合影响因子"]].value) + check_status = text(row[ix["核对状态"]].value) if "核对状态" in ix else None + + src_label = text(row[ix["数据来源"]].value) if "数据来源" in ix else None + src_url = hyperlink_target(row[ix["数据来源"]]) if "数据来源" in ix else None + official = None + if url_col is not None and url_col < len(row): + official = text(row[url_col].value) or hyperlink_target(row[url_col]) + official_check = text(row[ix["官网核对状态"]].value) if "官网核对状态" in ix else None + + rows.append(( + make_id("zh", name, None), "zh", name, + text(row[ix["研究方向"]].value), + # 中文分区原样(常量"不按此口径列示"),不分区 → partition_source=None + text(row[ix["中科院分区"]].value) if "中科院分区" in ix else None, + None, # cas_partition_note:中文表无"未检得"语义(口径=不按此口径列示) + None, # cas_partition_year + None, None, None, check_status, + composite, comprehensive, + to_int(row[ix["指标统计年"]].value) if "指标统计年" in ix else None, + to_int(row[ix["年报版本年"]].value) if "年报版本年" in ix else None, + text(row[ix["指标口径"]].value) if "指标口径" in ix else None, + to_int(row[ix["年报PDF页码"]].value) if "年报PDF页码" in ix else None, + None, None, None, None, None, None, None, + text(row[ix["备注"]].value) if "备注" in ix else None, + None, # evidence_note(中文表无此列) + official, + official_check, + None, # jcr_release_year:中文表无 JCR 发布年列(前端中文 Tab 不显示) + None, # partition_source:中文不按中科院口径 + "official", # jif_source:国内年报(official) + None, None, + src_label, src_url, + imported_at, + )) + stats["official_total"] += 1 + stats["official_filled"] += 1 if official else 0 + stats["official_check_filled"] += 1 if official_check else 0 + if not official: + stats["official_missing"].append(("zh", name)) + if composite is None: + stats["cif_missing"].append((name, check_status or "")) + stats["hl_zh"] += 1 if src_url else 0 + stats["id_slug"] += 1 + return rows + + +# ---- 对账报告 ---- + +def build_report( + stage: str, + stats: dict, + counts: dict[str, int] | None, + conflicts: list[str], + idempotent_ok: bool | None, + exit_note: str = "", +) -> str: + L: list[str] = [] + L.append("journals directory 导入对账报告") + L.append(f"生成时间: {datetime.now().isoformat(timespec='seconds')}") + L.append(f"源文件: {SOURCE_XLSX}({SOURCE_XLSX.stat().st_size if SOURCE_XLSX.exists() else 0} bytes)") + L.append(f"阶段: {stage}") + L.append("") + L.append("=== 计数 ===") + L.append(f"读取有效行: 国际 {stats['read_intl']} / 中文 {stats['read_zh']} / 合计 {stats['read_intl'] + stats['read_zh']}") + L.append(f"成功: {stats['success']} 跳过(名称空): {stats['skipped']} 失败: {stats['failed']}") + if counts is not None: + L.append(f"写入后 count(*): en={counts.get('en', 0)} zh={counts.get('zh', 0)} total={counts.get('total', 0)}") + L.append(f"期望: en={EXPECT_INTL} zh={EXPECT_ZH} total={EXPECT_INTL + EXPECT_ZH} → {'✓ 相符' if counts.get('total') == EXPECT_INTL + EXPECT_ZH else '✗ 不符'}") + L.append("") + L.append("=== 分区分布(国际)===") + L.append(" / ".join(f"{k} {v}" for k, v in sorted(stats["part_dist"].items()))) + L.append(f"分区空白(→null 无note): {len(stats['part_blank'])}") + L.append(f"分区未检得(→null + note): {len(stats['part_notfound'])}") + L.append("") + L.append(f"=== JIF 缺失 {len(stats['jif_missing'])} 条(jif=null + note=核对状态)===") + for n, s in stats["jif_missing"]: + L.append(f" - {n} [{s}]") + L.append("") + L.append(f"=== 中文复合IF 缺失 {len(stats['cif_missing'])} 条 ===") + for n, s in stats["cif_missing"]: + L.append(f" - {n} [{s}]") + L.append("") + L.append("=== 分区未检得 期刊名 ===") + if stats["part_notfound"]: + for n in stats["part_notfound"]: + L.append(f" - {n}") + else: + L.append(" (无——源表以空白表示未检得,见上方'分区空白')") + L.append("") + L.append("=== 重复 id 冲突(应为空)===") + if conflicts: + for c in conflicts: + L.append(f" !! {c}") + else: + L.append(" (无)") + L.append("") + L.append("=== id 策略 ===") + L.append(f"ISSN 型: {stats['id_issn']} 条 slug 型: {stats['id_slug']} 条") + L.append("") + L.append("=== 来源超链接 ===") + L.append(f"国际 JIF来源: {stats['hl_jif']}/{stats['read_intl']} 分区来源: {stats['hl_part']}/{stats['read_intl']} 中文数据来源: {stats['hl_zh']}/{stats['read_zh']}") + L.append("") + L.append("=== 结构迁移(ALTER TABLE,幂等)===") + added = stats.get("migrated_cols") or [] + skipped = stats.get("migrated_skipped") or [] + L.append(f" 本次加列: {', '.join(added) if added else '无(列已齐)'}") + L.append(f" 已存在跳过: {', '.join(skipped) if skipped else '无'}") + L.append("") + L.append("=== 官网映射(决策:official_source 不入库)===") + L.append(f" 识别列: {stats.get('official_url_headers', '未识别')}") + tot = stats.get("official_total", 0) + L.append(f" official_url 填充: {stats.get('official_filled', 0)}/{tot}" + f" official_check_status 填充: {stats.get('official_check_filled', 0)}/{tot}") + L.append(f" jcr_release_year 填充: {stats.get('jcr_filled', 0)}(仅国际=2026;中文表无此列→null)") + missing = stats.get("official_missing") or [] + if missing: + L.append(f" 官网缺失 {len(missing)} 条(official_url=null,前端显示「—」不生成链接):") + for lg, n in missing: + L.append(f" - [{lg}] {n}") + else: + L.append(" 官网缺失: (无)") + L.append("") + L.append("=== 幂等性验证 ===") + if idempotent_ok is None: + L.append(" 未执行") + else: + L.append(f" 第二次 upsert 后 count 不变: {'✓ 通过' if idempotent_ok else '✗ 失败'}") + L.append("") + if exit_note: + L.append(f"!!! {exit_note}") + return "\n".join(L) + "\n" + + +# ---- 主流程 ---- + +def main() -> int: + if not SOURCE_XLSX.exists(): + print(f"[错误] 源文件不存在: {SOURCE_XLSX}", file=sys.stderr) + return 3 + + stats: dict[str, Any] = { + "read_intl": 0, "read_zh": 0, "success": 0, "skipped": 0, "failed": 0, + "jif_missing": [], "cif_missing": [], "part_blank": [], "part_notfound": [], + "part_dist": Counter(), "hl_jif": 0, "hl_part": 0, "hl_zh": 0, + "id_issn": 0, "id_slug": 0, "official_url_detected": False, + "migrated_cols": [], "migrated_skipped": [], + "official_total": 0, "official_filled": 0, "official_check_filled": 0, + "jcr_filled": 0, "official_missing": [], + } + imported_at = datetime.now().isoformat(timespec="seconds") + t0 = time.time() + + # 1) 读 Excel(非 read_only:要超链接) + try: + wb = openpyxl.load_workbook(SOURCE_XLSX, data_only=True) + except Exception as exc: # noqa: BLE001 + REPORT_TXT.write_text(build_report("读取失败", stats, None, [], None, str(exc)), encoding="utf-8") + print(f"[错误] 无法打开 Excel: {exc}", file=sys.stderr) + return 3 + if SHEET_INTL not in wb.sheetnames or SHEET_ZH not in wb.sheetnames: + msg = f"缺少 sheet:需要 {SHEET_INTL}/{SHEET_ZH},实际 {wb.sheetnames}" + REPORT_TXT.write_text(build_report("结构错误", stats, None, [], None, msg), encoding="utf-8") + print(f"[错误] {msg}", file=sys.stderr) + return 3 + + # 2) 解析 + rows_en = read_intl(wb[SHEET_INTL], imported_at, stats) + rows_zh = read_zh(wb[SHEET_ZH], imported_at, stats) + stats["read_intl"], stats["read_zh"] = len(rows_en), len(rows_zh) + for r in rows_en: + stats["part_dist"][r[4] or ("未检得" if r[5] else "空白")] += 1 + + # 3) 口径行数校验(不符 → 中止,不写库) + if len(rows_en) != EXPECT_INTL or len(rows_zh) != EXPECT_ZH: + note = (f"行数与口径不符:国际 {len(rows_en)}/{EXPECT_INTL}、" + f"中文 {len(rows_zh)}/{EXPECT_ZH},中止导入") + REPORT_TXT.write_text(build_report("行数校验失败", stats, None, [], None, note), encoding="utf-8") + print(f"[中止] {note}", file=sys.stderr) + return 2 + + # 4) id 冲突检测(同 lang 内重复 → 报告并中止) + ids = [r[0] for r in rows_en + rows_zh] + dup = [i for i, c in Counter(ids).items() if c > 1] + conflicts = [f"{i} × {Counter(ids)[i]}" for i in sorted(dup)] + if conflicts: + note = f"发现 {len(conflicts)} 个重复 id,中止导入(未写库)" + REPORT_TXT.write_text(build_report("id 冲突中止", stats, None, conflicts, None, note), encoding="utf-8") + print(f"[中止] {note}", file=sys.stderr) + for c in conflicts: + print(f" !! {c}", file=sys.stderr) + return 1 + + # 5) 写 SQLite(独立 stdlib 连接;表由本脚本创建,db.py 零触碰) + db_path = Path(os.environ.get("REVIEW_DB_PATH") or (ROOT / "review.db")) + if not db_path.is_absolute(): + db_path = ROOT / db_path + conn = sqlite3.connect(str(db_path)) + try: + conn.executescript(SCHEMA_SQL) + stats["migrated_cols"], stats["migrated_skipped"] = migrate(conn) + all_rows = rows_en + rows_zh + conn.executemany(UPSERT_SQL, all_rows) + conn.commit() + stats["success"] = len(all_rows) + + def count() -> dict[str, int]: + cur = conn.execute( + "SELECT lang, COUNT(*) FROM journal_directory GROUP BY lang") + d = {lang: n for lang, n in cur.fetchall()} + total = sum(d.values()) + return {"en": d.get("en", 0), "zh": d.get("zh", 0), "total": total} + + counts = count() + # 6) 幂等验证:同数据第二次 upsert → count 不变 + conn.executemany(UPSERT_SQL, all_rows) + conn.commit() + idempotent_ok = count() == counts + + # 分区分布来自实际库(防统计与写入脱节;未检得 note 单列) + stats["part_dist"] = Counter(dict(conn.execute( + "SELECT COALESCE(cas_partition, " + "CASE WHEN cas_partition_note='未检得' THEN '未检得' ELSE '空白' END), COUNT(*) " + "FROM journal_directory WHERE lang='en' GROUP BY 1").fetchall())) + + report = build_report("完成", stats, counts, conflicts, idempotent_ok) + REPORT_TXT.write_text(report, encoding="utf-8") + print(report) + print(f"[完成] 耗时 {time.time() - t0:.2f}s db={db_path} 报告={REPORT_TXT}") + return 0 + finally: + conn.close() + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/sdk/app/routers/review_proxy.py b/sdk/app/routers/review_proxy.py index 7adbfc7..6a14a5c 100644 --- a/sdk/app/routers/review_proxy.py +++ b/sdk/app/routers/review_proxy.py @@ -63,7 +63,7 @@ async def _proxy(request: Request, path: str) -> Any: ) async with httpx.AsyncClient(timeout=timeout) as client: try: - upstream = await client.build_request( + upstream = client.build_request( # build_request 是同步方法,返回 httpx.Request,不可 await request.method, url, content=body, headers=headers ) resp = await client.send(upstream) diff --git a/ui/.gitignore b/ui/.gitignore index 677c9b7..11ee758 100644 --- a/ui/.gitignore +++ b/ui/.gitignore @@ -1,3 +1 @@ -# frontend/.gitignore(最小版,B1 可扩展) -node_modules/ -dist/ +.env.local diff --git a/ui/postcss.config.js b/ui/postcss.config.js new file mode 100644 index 0000000..b1c6ea4 --- /dev/null +++ b/ui/postcss.config.js @@ -0,0 +1 @@ +export default {} diff --git a/ui/src/App.vue b/ui/src/App.vue index 531d4b9..e475c09 100644 --- a/ui/src/App.vue +++ b/ui/src/App.vue @@ -1,11 +1,14 @@ - + diff --git a/ui/src/api/review.js b/ui/src/api/review.js new file mode 100644 index 0000000..d231349 --- /dev/null +++ b/ui/src/api/review.js @@ -0,0 +1,110 @@ +// api/review.js —— 科研审稿端点封装(BFF 8090 → review_service 8100) +// 相对路径 /api/review/* → vite proxy(vite.config.js bffTarget)→ BFF 反代(须 REVIEW_ENABLED=1)。 +// +// 错误契约适配:review_service 业务错误是 **HTTP 200 + {ok:false,error:{...}}** +// (VALIDATION/PARSE_FAILED/UPSTREAM_DOWN/SEED_UNAVAILABLE 均实测 200), +// 而 http.js 只对非 2xx 抛 ApiError —— 200 信封会正常 resolve。 +// unwrap() 把两条错误路径(200 信封 / 非 2xx http.js 抛出)归一成 ApiError, +// 调用方只需 catch + reviewErrorMessage(err) 一个口径。 +import { get, post, ApiError } from './http.js'; + +const BASE = '/api/review'; + +function unwrap(promise) { + return promise.then((payload) => { + if (payload && payload.ok === false && payload.error) { + throw new ApiError(payload.error.message || '服务错误', { + code: payload.error.code || 'INTERNAL', + status: 200, + degraded: !!payload.error.degraded, + }); + } + return payload; + }); +} + +/** ① GET /api/review/journals?field=&order= + * → {ok, items:[{id,name,scope_desc,impact_factor,review_time_weeks,acceptance_rate, + * submission_deadline,official_url,last_updated}], + * meta:{count,last_updated,data_source_note}} */ +export function getJournals(params = {}) { + return unwrap(get(`${BASE}/journals`, params)); +} + +/** ①' GET /api/review/journals/directory?lang=&domain=&cas_partition=&q=&page=&size=&field=&order= + * → {ok, items[{id,lang,name,research_direction,cas_partition,cas_partition_note, + * cas_partition_year,jif,jif_year,jif_note,jif_check_status,composite_impact_factor, + * comprehensive_impact_factor,metric_year,metric_report_year,metric_caliber, + * annual_report_page,top_flag,publisher_series,journal_mark,article_type,issn,eissn, + * jcr_disciplines[],supplement_note,evidence_note,official_url,partition_source, + * jif_source,jif_source_url,partition_source_url,data_source_label,data_source_url}], + * meta:{total,page,size,lang,domain,cas_partition,q,domains[], + * data_source_note,data_imported}} + * 1056 本目录(779 国际 + 277 中文);只读分页,lang 强制单语(en/zh 永不混排); + * cas_partition 仅 lang=en 过滤;field 排序白名单 name/jif/composite_impact_factor/ + * comprehensive_impact_factor/research_direction/cas_partition;缺值 source 已归零。 */ +export function getDirectory(params = {}) { + return unwrap(get(`${BASE}/journals/directory`, params)); +} + +/** ⑦' GET /api/review/conferences?domain=&ccf=&upcoming_days= + * → {ok, items:[{id,name,full_name,domain_tags,application_tags,ccf_rank, + * deadline_abstract,deadline_full_paper,notification_date,conference_date, + * location,official_url,timezone_note,deadline_source,last_verified}], + * meta:{count,last_verified,data_source_note,query}} + * 只读静态种子(全 placeholder);排序/过滤由后端做,upcoming_days=0 表示不过滤。 */ +export function getConferences(params = {}) { + return unwrap(get(`${BASE}/conferences`, params)); +} + +/** ③ POST /api/review/presubmit(multipart PDF)→ {ok, report, meta} + * FormData 自动 multipart(http.js 不设 Content-Type,浏览器带 boundary); + * opts 可传 {onUploadProgress, signal, timeout}(FormData+进度走 XHR 分支)。 + * 读超时沿用默认 600s(> BFF 360s),不先于上游自断。 */ +export function presubmit(formData, opts = {}) { + return unwrap(post(`${BASE}/presubmit`, formData, opts)); +} + +/** ② POST /api/review/recommend → {ok, tiers:[{tier,journals:[...]}], meta} */ +export function recommend(payload, opts = {}) { + return unwrap(post(`${BASE}/recommend`, payload, opts)); +} + +/** ⑤ POST /api/review/format-check(multipart PDF/Word) + * → {ok, checks:[{key,name,status,detail,suggestion}], summary:{pass,warn,fail}, + * meta:{filename,file_type,pages,ruleset_source,rules_source,journal_*, + * refs_style_expected,refs_style_detected}} + * 纯规则引擎,无 LLM,同步秒回(无需 onUploadProgress)。 */ +export function formatCheck(formData, opts = {}) { + return unwrap(post(`${BASE}/format-check`, formData, opts)); +} + +/** ⑤ format-check 专用错误文案:解档/校验类 PARSE_FAILED/VALIDATION 用后端原话 + * (与 presubmit 的"扫描件"提示是不同语境,不能复用 CODE_HINTS),其余走统一口径。 */ +export function formatErrorMessage(err) { + if (err instanceof ApiError && (err.code === 'PARSE_FAILED' || err.code === 'VALIDATION') && err.message) { + return err.message; + } + return reviewErrorMessage(err); +} + +/** 后端 error.code → 用户可读提示。 + * null = 不覆盖、直接用后端 message(VALIDATION 入参问题后端原话更具体)。 */ +const CODE_HINTS = { + VALIDATION: null, + PARSE_FAILED: '论文解析失败:可能是扫描件/图片型 PDF,请换文本型 PDF。', + UPSTREAM_DOWN: '审稿模型暂时不可用,请稍后重试。', + SEED_UNAVAILABLE: '期刊库未就绪(种子数据缺失),请联系管理员。', + TIMEOUT: '请求超时,请稍后重试。', + NETWORK: '网络异常,请检查连接后重试。', +}; + +/** ApiError(或任意错误)→ 用户可读文案。degraded 由调用方读 err.degraded 走降级横幅样式。 */ +export function reviewErrorMessage(err) { + if (err instanceof ApiError) { + const hint = CODE_HINTS[err.code]; + if (hint) return hint; + if (err.message) return err.message; // VALIDATION 等:后端原话 + } + return '服务异常,请稍后重试'; +} diff --git a/ui/src/components/edu/EduSideNav.vue b/ui/src/components/edu/EduSideNav.vue new file mode 100644 index 0000000..f2747a4 --- /dev/null +++ b/ui/src/components/edu/EduSideNav.vue @@ -0,0 +1,113 @@ + + + + + + diff --git a/ui/src/components/edu/EduWorkspace.vue b/ui/src/components/edu/EduWorkspace.vue new file mode 100644 index 0000000..2abb290 --- /dev/null +++ b/ui/src/components/edu/EduWorkspace.vue @@ -0,0 +1,60 @@ + + + + + + diff --git a/ui/src/components/edu/panels/CalendarPanel.vue b/ui/src/components/edu/panels/CalendarPanel.vue new file mode 100644 index 0000000..93100d6 --- /dev/null +++ b/ui/src/components/edu/panels/CalendarPanel.vue @@ -0,0 +1,418 @@ + + + + + + diff --git a/ui/src/components/edu/panels/FormatPanel.vue b/ui/src/components/edu/panels/FormatPanel.vue new file mode 100644 index 0000000..14f6db4 --- /dev/null +++ b/ui/src/components/edu/panels/FormatPanel.vue @@ -0,0 +1,495 @@ + + + + + + diff --git a/ui/src/components/edu/panels/JournalsPanel.vue b/ui/src/components/edu/panels/JournalsPanel.vue new file mode 100644 index 0000000..c0fef9d --- /dev/null +++ b/ui/src/components/edu/panels/JournalsPanel.vue @@ -0,0 +1,770 @@ + + + + + + diff --git a/ui/src/components/edu/panels/PresubmitPanel.vue b/ui/src/components/edu/panels/PresubmitPanel.vue new file mode 100644 index 0000000..308c0a2 --- /dev/null +++ b/ui/src/components/edu/panels/PresubmitPanel.vue @@ -0,0 +1,614 @@ + + + + + + diff --git a/ui/src/components/edu/panels/RecommendPanel.vue b/ui/src/components/edu/panels/RecommendPanel.vue new file mode 100644 index 0000000..1bf6391 --- /dev/null +++ b/ui/src/components/edu/panels/RecommendPanel.vue @@ -0,0 +1,507 @@ + + + + + + diff --git a/ui/src/components/edu/panels/ReportPanel.vue b/ui/src/components/edu/panels/ReportPanel.vue new file mode 100644 index 0000000..15dddf2 --- /dev/null +++ b/ui/src/components/edu/panels/ReportPanel.vue @@ -0,0 +1,420 @@ + + + + + + diff --git a/ui/src/components/edu/panels/TrackerPanel.vue b/ui/src/components/edu/panels/TrackerPanel.vue new file mode 100644 index 0000000..9181eb5 --- /dev/null +++ b/ui/src/components/edu/panels/TrackerPanel.vue @@ -0,0 +1,394 @@ + + + + + + diff --git a/ui/src/components/edu/panels/TrainingPanel.vue b/ui/src/components/edu/panels/TrainingPanel.vue new file mode 100644 index 0000000..8da7ff2 --- /dev/null +++ b/ui/src/components/edu/panels/TrainingPanel.vue @@ -0,0 +1,16 @@ + + + + + + diff --git a/ui/src/components/layout/TopBar.vue b/ui/src/components/layout/TopBar.vue index a2362d0..399b3a2 100644 --- a/ui/src/components/layout/TopBar.vue +++ b/ui/src/components/layout/TopBar.vue @@ -14,6 +14,7 @@ import { APP_NAME, STATUS_LABEL, T } from '../../i18n/labels.js'; import { BF } from '../../i18n/bioflow.js'; import { useThemeStore } from '../../stores/theme.js'; import { useBioflowStore } from '../../stores/bioflow.js'; +import { useAppStore } from '../../stores/app.js'; const props = defineProps({ /** 当前会话标题(无会话为 null → 显示「就绪」徽章) */ @@ -40,6 +41,9 @@ const bioflowStore = useBioflowStore(); const bioflowOnline = computed(() => bioflowStore.availability === 'online'); const bioflowStatus = computed(() => bioflowStore.availability); +/* ---------- 教育科研入口(步骤5;覆盖层视图切换 D1,同 themeStore 静态导入) ---------- */ +const appStore = useAppStore(); + /* ---------- B2/B3 store 数据(动态导入 + 空值守卫) ---------- */ const chatStore = ref(null); const benchStore = ref(null); @@ -160,6 +164,8 @@ const iconClose = ' 生信 + + + + + + + +

+ + + + diff --git a/ui/src/stores/edu.js b/ui/src/stores/edu.js index ba3040b..388d3e8 100644 --- a/ui/src/stores/edu.js +++ b/ui/src/stores/edu.js @@ -4,10 +4,10 @@ // - 进行中的请求由 store action 持有 → 面板卸载不中断; // - 表单草稿存 drafts → 切菜单不丢。 import { defineStore } from 'pinia'; -import { formatCheck, formatErrorMessage, getConferences, getDirectory, getJournals, presubmit, recommend, reviewErrorMessage } from '../api/review.js'; +import { compileTex, formatCheck, formatErrorMessage, getConferences, getDirectory, getJournals, presubmit, recommend, reformatTex, reviewErrorMessage } from '../api/review.js'; const STORAGE_KEY = 'plantai.edu.submissions'; // D3 台账持久化 -const SECTIONS = ['journals', 'recommend', 'presubmit', 'report', 'format', 'tracker', 'calendar']; +const SECTIONS = ['journals', 'recommend', 'presubmit', 'report', 'format', 'reformat', 'tracker', 'calendar']; // ⑥ 台账状态枚举(labels 由 step-7 UI 层给;store 只存字符串) export const SUBMISSION_STATUS = ['draft', 'submitted', 'under_review', 'revision', 'accepted', 'rejected']; @@ -74,6 +74,16 @@ export const useEduStore = defineStore('edu', { formatReport: null, // ⑤ 版式检查响应 {ok, checks, summary, meta}(跨菜单保留) formatStatus: 'idle', formatError: null, + /* —— ⑤' 论文自动重排版 P1(.tex 规则变换)响应 + {ok, job_id, modified_tex, changes[], warnings[], meta}(跨菜单保留)—— */ + reformatResult: null, + reformatStatus: 'idle', + reformatError: null, + /* —— P3a 编译 PDF(tectonic;与 reformatResult 同生命周期,重新排版即失效)—— */ + compileResult: null, // {ok, compile_id, pdf_url, log_url, meta} + compileStatus: 'idle', // 'idle' | 'loading' | 'ready' | 'error' + compileError: null, + compileLogTail: '', // COMPILE_FAILED/TIMEOUT 的 log 尾 200 行(err.detail) /* —— 表单草稿(切菜单不丢;四字段并存:recommend 用 abstract+prefs、 presubmit 用 targetJournal、format 用 formatJournalId(期刊 id 下拉))—— */ @@ -81,6 +91,11 @@ export const useEduStore = defineStore('edu', { abstract: '', targetJournal: '', formatJournalId: '', + // ⑤' 重排版目标:'default'(通用规则,首项默认)| 精选期刊 id | 'dir:'(目录刊) + // '__dir_en__'/'__dir_zh__' = 目录搜索模式(过渡态,非合法 target,面板内校验)。 + // reformatDirPick = {id,name}(目录选中回显,跨菜单保留防 select 失焦)。 + reformatTarget: 'default', + reformatDirPick: null, // 与 POST /api/review/recommend 的 preferences 同构: // {max_review_weeks, min_impact_factor, tier_focus} 子字段逐一同名同型, // 提交时整体映射为 payload.preferences(null 数值剔除)。 @@ -255,5 +270,53 @@ export const useEduStore = defineStore('edu', { this.formatStatus = 'idle'; this.formatError = null; }, + /* —— ⑤' 重排版(P1:.tex 源码变换,纯规则同步秒回)—— */ + async submitReformat(formData) { + this.clearCompile(); // 新排版结果使旧 PDF 失效 + this.reformatStatus = 'loading'; + this.reformatError = null; + try { + const payload = await reformatTex(formData); + this.reformatResult = payload; + this.reformatStatus = 'ready'; + return payload; + } catch (err) { + this.reformatStatus = 'error'; + this.reformatError = formatErrorMessage(err); // VALIDATION/PARSER_FAILED 用后端原话 + return null; + } + }, + clearReformat() { + this.reformatResult = null; + this.reformatStatus = 'idle'; + this.reformatError = null; + this.clearCompile(); + }, + /* —— P3a 编译 PDF(tectonic 单槽队列;约 10-30 秒)—— */ + async submitCompile(jobId) { + if (this.compileStatus === 'loading') return null; + this.compileStatus = 'loading'; + this.compileError = null; + this.compileLogTail = ''; + const fd = new FormData(); + fd.append('job_id', jobId); + try { + const payload = await compileTex(fd); + this.compileResult = payload; + this.compileStatus = 'ready'; + return payload; + } catch (err) { + this.compileStatus = 'error'; + this.compileError = reviewErrorMessage(err); + this.compileLogTail = err.detail || ''; // COMPILE_FAILED/TIMEOUT 附 log 尾 + return null; + } + }, + clearCompile() { + this.compileResult = null; + this.compileStatus = 'idle'; + this.compileError = null; + this.compileLogTail = ''; + }, }, }); -- 2.52.0 From 649e66f41df2c52dd05e9b45d3c49f9cfa06c064 Mon Sep 17 00:00:00 2001 From: potaser Date: Sun, 11 Oct 2026 12:19:18 +0800 Subject: [PATCH 5/8] feat(review): tectonic PDF compile API (P3a) + rename journals panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - POST/GET /api/review/compile[/{id}[/pdf|/log]]: isolated workdir, --untrusted, 60s timeout with process-group kill, single-slot queue (429 QUEUE_FULL), 7-day retention sweep - tools/install_tectonic.sh: pinned tectonic 0.17.0 (sha256) + README - Rename menu/panel title to 学术期刊情报 - Compile UI stays a placeholder per product decision (P3 deferred) --- review_service/app/main.py | 17 +- review_service/app/routers/compile.py | 184 ++++++++++++++ review_service/app/services/latex_compile.py | 236 ++++++++++++++++++ review_service/tests/test_compile.py | 228 +++++++++++++++++ review_service/tools/README.md | 13 + review_service/tools/install_tectonic.sh | 36 +++ ui/src/components/edu/EduSideNav.vue | 2 +- .../components/edu/panels/JournalsPanel.vue | 51 ++-- 8 files changed, 744 insertions(+), 23 deletions(-) create mode 100644 review_service/app/routers/compile.py create mode 100644 review_service/app/services/latex_compile.py create mode 100644 review_service/tests/test_compile.py create mode 100644 review_service/tools/README.md create mode 100644 review_service/tools/install_tectonic.sh diff --git a/review_service/app/main.py b/review_service/app/main.py index df24b64..b130fcc 100644 --- a/review_service/app/main.py +++ b/review_service/app/main.py @@ -15,7 +15,15 @@ from fastapi.middleware.cors import CORSMiddleware from .config import get_settings from .db import close_db, init_db -from .routers import conferences, format_check, journal_directory, journals, presubmit, reformat +from .routers import ( + compile, + conferences, + format_check, + journal_directory, + journals, + presubmit, + reformat, +) logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) @@ -38,6 +46,12 @@ def create_app() -> FastAPI: # journals 推荐依赖独立 SQLite:启动即建表(幂等;测试可先 set_path 注入 # tmp 路径,本函数沿用注入路径) await init_db() + # 编译产物过期清扫:启动跑一次(失败不阻塞启动) + try: + from .services.latex_compile import sweep_expired + sweep_expired() + except Exception: # noqa: BLE001 + logger.warning("compile sweep 启动清扫失败(忽略)", exc_info=True) try: yield finally: @@ -69,6 +83,7 @@ def create_app() -> FastAPI: app.include_router(conferences.router) app.include_router(journal_directory.router) app.include_router(reformat.router) + app.include_router(compile.router) return app diff --git a/review_service/app/routers/compile.py b/review_service/app/routers/compile.py new file mode 100644 index 0000000..86d61ea --- /dev/null +++ b/review_service/app/routers/compile.py @@ -0,0 +1,184 @@ +"""routers/compile.py —— LaTeX 编译 PDF(P3a:tectonic)。 + +端点: + POST /api/review/compile multipart:file(.tex 可选) | job_id(可选,二选一) + → {ok, compile_id, pdf_url, log_url, meta} + GET /api/review/compile/{cid} 编译元信息(meta.json) + GET /api/review/compile/{cid}/pdf output.pdf(FileResponse) + GET /api/review/compile/{cid}/log output.log(text/plain) + +信封:业务错误 = HTTP 200 + {ok:false,error:{code,message,detail?,degraded:false}} +(QUEUE_FULL 例外:HTTP 429 + 同款信封体,前端仍按 ok/error 单一口径处理)。 +detail = log 尾 200 行(COMPILE_FAILED / TIMEOUT)。 +""" +from __future__ import annotations + +import json +import logging +import re +import uuid +from pathlib import Path +from typing import Any + +from fastapi import APIRouter, File, Form, UploadFile +from fastapi.responses import FileResponse, JSONResponse, PlainTextResponse +from pydantic import BaseModel + +from ..config import get_settings +from ..services import latex_compile as lc +from ..services.latex_compile import ( + CompileError, + QueueFullError, + ToolUnavailableError, +) + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/api/review", tags=["review-compile"]) + +_CID_RE = re.compile(r"^[0-9a-f]{12}$") + + +class CompileResponse(BaseModel): + ok: bool + compile_id: str | None = None + pdf_url: str | None = None + log_url: str | None = None + meta: dict[str, Any] | None = None + error: dict[str, Any] | None = None + + +def _error(code: str, message: str, detail: str = "") -> CompileResponse: + err: dict[str, Any] = {"code": code, "message": message, "degraded": False} + if detail: + err["detail"] = detail + return CompileResponse(ok=False, error=err) + + +def _jobs_root() -> Path: + d = get_settings().reformat_dir_abs + d.mkdir(parents=True, exist_ok=True) + return d + + +@router.post("/compile", response_model=CompileResponse) +async def compile_tex( + file: UploadFile | None = File(None, description="LaTeX 源码(.tex,与 job_id 二选一)"), + job_id: str = Form("", description="P1 重排版任务 id(优先于 file)"), +) -> CompileResponse: + settings = get_settings() + + # ---- 输入解析:job_id 优先,否则直接上传的 .tex ---- + jid = (job_id or "").strip() + if jid: + if not _CID_RE.fullmatch(jid): + return _error("VALIDATION", "job_id 格式非法(应为 12 位 hex)") + src = _jobs_root() / f"{jid}.tex" + if not src.is_file(): + return _error("VALIDATION", "job_id 对应的重排版结果不存在,请重新排版") + try: + source = src.read_text("utf-8") + except UnicodeDecodeError: + return _error("VALIDATION", "任务源码不是合法 UTF-8") + anchor_id = jid + else: + if file is None: + return _error("VALIDATION", "必须提供 file(.tex)或 job_id") + filename = file.filename or "paper.tex" + if Path(filename).name != filename or ".." in filename: + return _error("VALIDATION", "非法文件名") + if not filename.lower().endswith(".tex"): + return _error("VALIDATION", "仅支持 .tex 文件") + content = await file.read() + if not content: + return _error("VALIDATION", "上传文件为空") + if len(content) > settings.max_tex_bytes: + return _error("VALIDATION", "源码超过 2MB 上限") + try: + source = content.decode("utf-8") + except UnicodeDecodeError: + return _error("VALIDATION", "源码必须为 UTF-8 编码") + anchor_id = uuid.uuid4().hex[:12] + + # ---- 编译(隔离目录;失败信封带 log 尾)---- + lc.prepare_input(anchor_id, source) + try: + result = await lc.compile_tex(anchor_id) + except ToolUnavailableError as exc: + return _error("TOOL_UNAVAILABLE", str(exc)) + except QueueFullError as exc: + return JSONResponse( + status_code=429, + content={ + "ok": False, + "compile_id": None, "pdf_url": None, "log_url": None, "meta": None, + "error": {"code": "QUEUE_FULL", "message": str(exc), "degraded": False}, + }, + ) + except CompileError as exc: + return _error(exc.code, str(exc), detail=exc.log_tail) + + meta_path = lc.compile_dir(anchor_id) / "meta.json" + try: + meta = json.loads(meta_path.read_text("utf-8")) + except (OSError, ValueError): + meta = {"compile_id": anchor_id, "seconds": result["seconds"]} + return CompileResponse( + ok=True, + compile_id=anchor_id, + pdf_url=f"/api/review/compile/{anchor_id}/pdf", + log_url=f"/api/review/compile/{anchor_id}/log", + meta=meta, + ) + + +def _cid_dir(cid: str) -> Path | None: + if not _CID_RE.fullmatch(cid or ""): + return None + d = lc.compile_dir(cid) + return d if d.is_dir() else None + + +@router.get("/compile/{compile_id}", response_model=CompileResponse) +async def get_compile(compile_id: str) -> CompileResponse: + cdir = _cid_dir(compile_id) + meta_path = cdir / "meta.json" if cdir else None + if meta_path is None or not meta_path.is_file(): + return _error("NOT_FOUND", "编译任务不存在或已过期,请重新编译") + try: + meta = json.loads(meta_path.read_text("utf-8")) + except (OSError, ValueError): + return _error("NOT_FOUND", "编译产物损坏,请重新编译") + return CompileResponse( + ok=True, + compile_id=compile_id, + pdf_url=f"/api/review/compile/{compile_id}/pdf", + log_url=f"/api/review/compile/{compile_id}/log", + meta=meta, + ) + + +@router.get("/compile/{compile_id}/pdf", response_model=None) +async def download_compile_pdf(compile_id: str) -> FileResponse | JSONResponse: + cdir = _cid_dir(compile_id) + pdf = cdir / "output.pdf" if cdir else None + if pdf is None or not pdf.is_file(): + return JSONResponse( + status_code=200, + content={"ok": False, "error": { + "code": "NOT_FOUND", "message": "PDF 不存在或已过期", "degraded": False}}, + ) + return FileResponse(pdf, media_type="application/pdf", filename=f"{compile_id}.pdf") + + +@router.get("/compile/{compile_id}/log", response_model=None) +async def download_compile_log(compile_id: str) -> PlainTextResponse | JSONResponse: + cdir = _cid_dir(compile_id) + log = cdir / "output.log" if cdir else None + if log is None or not log.is_file(): + return JSONResponse( + status_code=200, + content={"ok": False, "error": { + "code": "NOT_FOUND", "message": "日志不存在或已过期", "degraded": False}}, + ) + return PlainTextResponse(log.read_text("utf-8", errors="replace")) diff --git a/review_service/app/services/latex_compile.py b/review_service/app/services/latex_compile.py new file mode 100644 index 0000000..b396769 --- /dev/null +++ b/review_service/app/services/latex_compile.py @@ -0,0 +1,236 @@ +"""services/latex_compile.py —— tectonic 编译 .tex → PDF(P3a)。 + +隔离与安全(对齐设计清单): + 1. 一编译一目录:{reformat_dir}/{anchor_id}/compile/(input.tex/output.pdf/output.log/meta.json) + 2. 文件名永不落盘:用户文件名只做后缀校验,写入一律 input.tex + 3. tectonic --untrusted(官方旗标:禁用已知不安全特性,含 shell escape 路径) + 4. 子进程 start_new_session + 超时 killpg(SIGKILL)(整进程组) + 5. 单槽队列:asyncio.Lock + pending 计数,超出 compile_queue_limit → QueueFullError + 6. 产物 PDF > max_compile_pdf_bytes → 删文件 + OutputTooLargeError + 7. 启动/每次编译前机会性清扫 retention_days 天前的 job 目录(只删 12 位 hex 锚点目录) + +tectonic 二进制缺失 → ToolUnavailableError(路由层回安装指引)。 +""" +from __future__ import annotations + +import asyncio +import json +import logging +import os +import re +import shutil +import signal +import time +from datetime import datetime, timezone +from pathlib import Path +from typing import Any + +from ..config import get_settings + +logger = logging.getLogger(__name__) + +_ANCHOR_ID_RE = re.compile(r"^[0-9a-f]{12}$") +_ENGINE = "tectonic-p3/0.17.0" +_LOG_TAIL_LINES = 200 + +# 单槽并发控制(进程内;重启归零可接受——本服务无持久队列需求) +_lock = asyncio.Lock() +_pending = 0 + + +class CompileError(Exception): + """编译失败(含 log 尾)。code ∈ {COMPILE_FAILED, TIMEOUT, OUTPUT_TOO_LARGE}。""" + + def __init__(self, code: str, message: str, log_tail: str = "") -> None: + super().__init__(message) + self.code = code + self.log_tail = log_tail + + +class QueueFullError(Exception): + """等待槽位超限。""" + + +class ToolUnavailableError(Exception): + """tectonic 二进制缺失/不可执行。""" + + +def _tectonic_bin() -> Path: + return get_settings().tectonic_abs + + +def _ensure_tool() -> Path: + bin_path = _tectonic_bin() + if not (bin_path.is_file() and os.access(bin_path, os.X_OK)): + raise ToolUnavailableError( + f"tectonic 未安装({bin_path})。" + "请执行:cd review_service && bash tools/install_tectonic.sh" + ) + return bin_path + + +def _log_tail(path: Path, lines: int = _LOG_TAIL_LINES) -> str: + try: + text = path.read_text("utf-8", errors="replace") + except OSError: + return "" + return "\n".join(text.splitlines()[-lines:]) + + +def compile_dir(anchor_id: str) -> Path: + """{reformat_dir}/{anchor_id}/compile/(存在性由调用方按需 mkdir)。""" + return get_settings().reformat_dir_abs / anchor_id / "compile" + + +def prepare_input(anchor_id: str, source: str) -> Path: + """写入隔离目录 input.tex;返回其路径。""" + cdir = compile_dir(anchor_id) + cdir.mkdir(parents=True, exist_ok=True) + input_tex = cdir / "input.tex" + input_tex.write_text(source, encoding="utf-8") + return input_tex + + +async def compile_tex(anchor_id: str) -> dict[str, Any]: + """同步编译 anchor 的 input.tex(须先 prepare_input)。 + + → {compile_id: anchor_id, pdf_path, log_path, seconds, pdf_bytes} + 失败抛 CompileError / QueueFullError / ToolUnavailableError。 + """ + global _pending + settings = get_settings() + _ensure_tool() # 快速失败:不占队列 + sweep_expired() + + if _pending >= settings.compile_queue_limit: + raise QueueFullError( + f"编译队列已满({_pending} 个任务排队),请稍后重试" + ) + _pending += 1 + try: + async with _lock: + return await _run_once(anchor_id) + finally: + _pending -= 1 + + +async def _run_once(anchor_id: str) -> dict[str, Any]: + settings = get_settings() + cdir = compile_dir(anchor_id) + input_tex = cdir / "input.tex" + pdf_path = cdir / "output.pdf" + log_path = cdir / "output.log" + if not input_tex.is_file(): + raise CompileError("COMPILE_FAILED", "编译输入不存在,请重新上传源码") + + env = dict(os.environ) + env["TECTONIC_CACHE_DIR"] = str(settings.tectonic_cache_abs) + cmd = [ + str(_tectonic_bin()), "-X", "compile", input_tex.name, + "--untrusted", "--keep-logs", "--outdir", ".", + ] + started = time.monotonic() + try: + proc = await asyncio.create_subprocess_exec( + *cmd, cwd=cdir, env=env, + stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT, + start_new_session=True, + ) + try: + await asyncio.wait_for( + proc.communicate(), timeout=settings.compile_timeout_s + ) + except asyncio.TimeoutError: + _kill_group(proc) + try: + await asyncio.wait_for(proc.wait(), timeout=5.0) + except asyncio.TimeoutError: + pass + log_path.write_text(_log_tail(log_path) + "\n[timeout] 编译超时,进程已终止", + encoding="utf-8") + raise CompileError( + "TIMEOUT", + f"编译超过 {settings.compile_timeout_s:g} 秒未完成,已终止", + _log_tail(log_path), + ) from None + except FileNotFoundError as exc: + raise ToolUnavailableError(f"tectonic 不可执行:{exc}") from exc + finally: + seconds = round(time.monotonic() - started, 2) + + # tectonic --keep-logs 把日志写在 cwd 的 input.log + produced_log = cdir / "input.log" + if produced_log.is_file(): + shutil.move(str(produced_log), str(log_path)) + if not log_path.is_file(): + log_path.write_text("", encoding="utf-8") + + produced_pdf = cdir / "input.pdf" + if not produced_pdf.is_file(): + raise CompileError( + "COMPILE_FAILED", + "编译失败(未产出 PDF),请查看日志定位 LaTeX 错误", + _log_tail(log_path), + ) + pdf_bytes = produced_pdf.stat().st_size + if pdf_bytes > settings.max_compile_pdf_bytes: + produced_pdf.unlink(missing_ok=True) + raise CompileError( + "OUTPUT_TOO_LARGE", + f"产出 PDF 超过 {settings.max_compile_pdf_bytes // (1024 * 1024)}MB 上限,已删除", + _log_tail(log_path), + ) + produced_pdf.rename(pdf_path) + + meta = { + "compile_id": anchor_id, + "engine": _ENGINE, + "seconds": seconds, + "pdf_bytes": pdf_bytes, + "returncode": 0, + "compiled_at": datetime.now(timezone.utc).isoformat(timespec="seconds"), + } + (cdir / "meta.json").write_text( + json.dumps(meta, ensure_ascii=False, indent=2), encoding="utf-8" + ) + logger.info("compile: %s → PDF %d bytes, %.2fs", anchor_id, pdf_bytes, seconds) + return { + "compile_id": anchor_id, + "pdf_path": pdf_path, + "log_path": log_path, + "seconds": seconds, + "pdf_bytes": pdf_bytes, + } + + +def _kill_group(proc: asyncio.subprocess.Process) -> None: + try: + os.killpg(os.getpgid(proc.pid), signal.SIGKILL) + except (ProcessLookupError, PermissionError, OSError): + try: + proc.kill() + except ProcessLookupError: + pass + + +def sweep_expired() -> int: + """删除 mtime 超 retention_days 的 12-hex 锚点目录(编译产物+P1 落盘一并清)。""" + settings = get_settings() + base = settings.reformat_dir_abs + if not base.is_dir(): + return 0 + cutoff = time.time() - settings.compile_retention_days * 86400 + removed = 0 + for child in base.iterdir(): + if not child.is_dir() or not _ANCHOR_ID_RE.fullmatch(child.name): + continue + try: + if child.stat().st_mtime < cutoff: + shutil.rmtree(child, ignore_errors=True) + removed += 1 + except OSError: + continue + if removed: + logger.info("compile sweep: 清理 %d 个过期任务目录(>%d 天)", + removed, settings.compile_retention_days) + return removed diff --git a/review_service/tests/test_compile.py b/review_service/tests/test_compile.py new file mode 100644 index 0000000..e761b26 --- /dev/null +++ b/review_service/tests/test_compile.py @@ -0,0 +1,228 @@ +"""tests/test_compile.py —— P3a LaTeX 编译单元/集成测试。 + +真实调用 tools/tectonic(宏包已预热缓存);二进制缺失时集成用例 skipif 跳过, +校验/队列/清扫等纯逻辑用例照常运行。 +运行: cd review_service && /bin/python -m pytest -q +""" +from __future__ import annotations + +import os +import time +from pathlib import Path + +import pytest +from fastapi.testclient import TestClient + +from app.config import get_settings +from app.main import app +from app.services import latex_compile as lc + +MINIMAL = "\\documentclass[11pt]{article}\n\\begin{document}\nhello p3\n\\end{document}\n" + +_TECTONIC_OK = get_settings().tectonic_abs.is_file() + +needs_tectonic = pytest.mark.skipif( + not _TECTONIC_OK, reason="tools/tectonic 未安装(bash tools/install_tectonic.sh)" +) + + +@pytest.fixture() +def client(tmp_path, monkeypatch): + settings = get_settings() + monkeypatch.setattr(settings, "reformat_dir", str(tmp_path / "jobs")) + # 缓存目录不注入 tmp:用部署预热好的 data/tectonic-cache(否则每次测试重拉 bundle) + monkeypatch.setattr(settings, "compile_timeout_s", 60.0) + monkeypatch.setattr(lc, "_pending", 0) + with TestClient(app) as c: + yield c + + +# ================================================================ 校验(无需 tectonic) + +def test_validation_no_input(client: TestClient): + r = client.post("/api/review/compile", data={}) + body = r.json() + assert r.status_code == 200 and body["ok"] is False + assert body["error"]["code"] == "VALIDATION" + + +def test_validation_bad_job_id(client: TestClient): + r = client.post("/api/review/compile", data={"job_id": "../evil"}) + assert r.json()["error"]["code"] == "VALIDATION" + + +def test_validation_job_not_found(client: TestClient): + r = client.post("/api/review/compile", data={"job_id": "0123456789ab"}) + assert r.json()["error"]["code"] == "VALIDATION" + + +def test_validation_path_traversal_filename(client: TestClient): + r = client.post( + "/api/review/compile", + files={"file": ("../evil.tex", b"x", "application/x-tex")}, + ) + assert r.json()["error"]["code"] == "VALIDATION" + + +def test_validation_non_tex(client: TestClient): + r = client.post( + "/api/review/compile", + files={"file": ("paper.pdf", b"x", "application/pdf")}, + ) + assert r.json()["error"]["code"] == "VALIDATION" + + +def test_validation_oversize(client: TestClient, monkeypatch): + monkeypatch.setattr(get_settings(), "max_tex_bytes", 10) + r = client.post( + "/api/review/compile", + files={"file": ("paper.tex", b"01234567890", "application/x-tex")}, + ) + assert r.json()["error"]["code"] == "VALIDATION" + + +# ================================================================ 编译(真实 tectonic) + +@needs_tectonic +def test_compile_happy_path(client: TestClient): + r = client.post( + "/api/review/compile", + files={"file": ("paper.tex", MINIMAL.encode(), "application/x-tex")}, + ) + body = r.json() + assert r.status_code == 200 and body["ok"] is True, body + cid = body["compile_id"] + assert len(cid) == 12 + + pdf = client.get(body["pdf_url"]) + assert pdf.status_code == 200 + assert pdf.headers["content-type"].startswith("application/pdf") + assert pdf.content[:5] == b"%PDF-" + + log = client.get(body["log_url"]) + assert log.status_code == 200 + assert "LaTeX2e" in log.text and "Output written" in log.text + + meta = client.get(f"/api/review/compile/{cid}") + assert meta.json()["ok"] is True + assert meta.json()["meta"]["pdf_bytes"] > 0 + + +@needs_tectonic +def test_compile_by_job_id(client: TestClient): + tex = ( + "\\documentclass[11pt]{article}\n\\begin{document}\nvia job\n\\end{document}\n" + ) + rf = client.post( + "/api/review/reformat", + files={"file": ("paper.tex", tex.encode(), "application/x-tex")}, + data={"target_journal": "default"}, + ).json() + assert rf["ok"] is True + r = client.post("/api/review/compile", data={"job_id": rf["job_id"]}) + body = r.json() + assert body["ok"] is True and body["compile_id"] == rf["job_id"] + pdf = client.get(body["pdf_url"]) + assert pdf.content[:5] == b"%PDF-" + + +@needs_tectonic +def test_compile_malicious_write18(client: TestClient, tmp_path): + canary = tmp_path / "canary_p3" + evil = ( + "\\documentclass{article}\n" + f"\\write18{{touch {canary}}}\n" + "\\begin{document}\nno shell please\n\\end{document}\n" + ) + r = client.post( + "/api/review/compile", + files={"file": ("evil.tex", evil.encode(), "application/x-tex")}, + ) + body = r.json() + # 系统无损即通过(信封 ok 与否均可):canary 绝不能出现 + assert not canary.exists(), r"\write18 竟然执行了!" + if body["ok"]: + pdf = client.get(body["pdf_url"]) + assert pdf.content[:5] == b"%PDF-" + else: + assert body["error"]["code"] in ("COMPILE_FAILED", "TIMEOUT") + + +@needs_tectonic +def test_compile_failed_returns_log_tail(client: TestClient): + bad = "\\documentclass{article}\n\\begin{document}\n\\undefinedcommandxyz\n" + r = client.post( + "/api/review/compile", + files={"file": ("bad.tex", bad.encode(), "application/x-tex")}, + ) + body = r.json() + assert body["ok"] is False + assert body["error"]["code"] == "COMPILE_FAILED" + assert "log" in body["error"]["message"].lower() or body["error"].get("detail") + + +@needs_tectonic +def test_compile_timeout(client: TestClient, monkeypatch): + monkeypatch.setattr(get_settings(), "compile_timeout_s", 5.0) + loop_tex = ( + "\\documentclass{article}\n\\begin{document}\n" + "\\count255=0\n\\loop\\iftrue\\advance\\count255 by 1\\repeat\n" + "\\end{document}\n" + ) + started = time.monotonic() + r = client.post( + "/api/review/compile", + files={"file": ("loop.tex", loop_tex.encode(), "application/x-tex")}, + ) + elapsed = time.monotonic() - started + body = r.json() + assert body["ok"] is False + assert body["error"]["code"] == "TIMEOUT" + assert elapsed < 15.0, f"超时回收过慢:{elapsed:.1f}s" + + +# ================================================================ 队列 / 清扫 + +def test_queue_full(client: TestClient, monkeypatch): + monkeypatch.setattr(lc, "_pending", 5) + monkeypatch.setattr(get_settings(), "compile_queue_limit", 5) + r = client.post( + "/api/review/compile", + files={"file": ("paper.tex", MINIMAL.encode(), "application/x-tex")}, + ) + assert r.status_code == 429 + body = r.json() + assert body["ok"] is False and body["error"]["code"] == "QUEUE_FULL" + + +def test_tool_unavailable(client: TestClient, monkeypatch): + monkeypatch.setattr(get_settings(), "tectonic_path", "tools/definitely-missing") + r = client.post( + "/api/review/compile", + files={"file": ("paper.tex", MINIMAL.encode(), "application/x-tex")}, + ) + assert r.status_code == 200 + assert r.json()["error"]["code"] == "TOOL_UNAVAILABLE" + assert "install_tectonic" in r.json()["error"]["message"] + + +def test_sweep_expired(tmp_path, monkeypatch): + settings = get_settings() + monkeypatch.setattr(settings, "reformat_dir", str(tmp_path / "jobs")) + base = tmp_path / "jobs" + stale = base / "aabbccddeeff" + stale.mkdir(parents=True) + (stale / "output.pdf").write_bytes(b"%PDF-fake") + old = time.time() - 8 * 86400 + os.utime(stale, (old, old)) + + fresh = base / "112233445566" + fresh.mkdir() + noise = base / "not-a-job" + noise.mkdir() + + removed = lc.sweep_expired() + assert removed == 1 + assert not stale.exists() + assert fresh.exists() + assert noise.exists() diff --git a/review_service/tools/README.md b/review_service/tools/README.md new file mode 100644 index 0000000..1c847d9 --- /dev/null +++ b/review_service/tools/README.md @@ -0,0 +1,13 @@ +# tools/ —— 编译器工具链(P3) + +## tectonic(LaTeX → PDF) + +- 单文件 musl 静态二进制,无 root、无系统 TeX Live 依赖;版本与 sha256 钉死在 + `install_tectonic.sh`(本目录二进制不入 git)。 +- 安装:`cd review_service && bash tools/install_tectonic.sh` + 部署树(zh)同一条命令;或直接 scp `tools/tectonic` + `data/tectonic-cache/`。 +- 宏包缓存:`data/tectonic-cache/`(环境变量 `REVIEW_TECTONIC_CACHE_DIR` 覆盖)。 + 首次编译会联网拉 bundle(~200MB),建议部署时用 hello.tex 预热: + `TECTONIC_CACHE_DIR=$PWD/data/tectonic-cache tools/tectonic -X compile hello.tex --untrusted` +- 安全:编译一律 `--untrusted`(tectonic 官方旗标,禁用已知不安全特性)+ + 运行于隔离工作目录 + 60s 超时整组 kill + 禁 shell escape。 diff --git a/review_service/tools/install_tectonic.sh b/review_service/tools/install_tectonic.sh new file mode 100644 index 0000000..0d05e9b --- /dev/null +++ b/review_service/tools/install_tectonic.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# install_tectonic.sh —— 一键安装/校验 tectonic 编译器(P3a)。 +# 幂等:已装且 sha256 匹配则直接退出 0。部署树(zh)同一条命令。 +# 用法:cd review_service && bash tools/install_tectonic.sh +set -euo pipefail + +TECTONIC_VERSION="0.17.0" +TECTONIC_TARBALL_SHA256="8533d07f9ccbd7a65824b9e0459041bca34af1eb33daba48f59215593753a3b7" +TECTONIC_BIN_SHA256="a98aa59ad5c1df39a6c9e56cbfc5088f2b11d6c179c0130b97998e4bd46a46da" +URL="https://github.com/tectonic-typesetting/tectonic/releases/download/tectonic%40${TECTONIC_VERSION}/tectonic-${TECTONIC_VERSION}-x86_64-unknown-linux-musl.tar.gz" + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BIN="${HERE}/tectonic" + +if [[ -x "$BIN" ]] && echo "$(sha256sum "$BIN" | cut -d' ' -f1)" = "$TECTONIC_BIN_SHA256"; then + echo "[install_tectonic] 已安装且校验通过:$BIN ($("$BIN" --version))" + exit 0 +fi + +tmp="$(mktemp -d)" +trap 'rm -rf "$tmp"' EXIT + +echo "[install_tectonic] 下载 tectonic ${TECTONIC_VERSION}(musl 静态版)…" +curl -fL --retry 3 -o "$tmp/tectonic.tar.gz" "$URL" + +echo "[install_tectonic] 校验 tarball sha256…" +echo "${TECTONIC_TARBALL_SHA256} $tmp/tectonic.tar.gz" | sha256sum -c - + +tar -xzf "$tmp/tectonic.tar.gz" -C "$tmp" tectonic +echo "[install_tectonic] 校验二进制 sha256…" +echo "${TECTONIC_BIN_SHA256} $tmp/tectonic" | sha256sum -c - + +install -m 0755 "$tmp/tectonic" "$BIN" +echo "[install_tectonic] 完成:$BIN ($("$BIN" --version))" +echo "[install_tectonic] 提示:首次真实编译会联网拉宏包 bundle(约 200MB)," +echo " 服务端 TECTONIC_CACHE_DIR 默认 data/tectonic-cache,建议部署时预热。" diff --git a/ui/src/components/edu/EduSideNav.vue b/ui/src/components/edu/EduSideNav.vue index ea68aaa..4e89d4f 100644 --- a/ui/src/components/edu/EduSideNav.vue +++ b/ui/src/components/edu/EduSideNav.vue @@ -10,7 +10,7 @@ const app = useAppStore(); const edu = useEduStore(); const ITEMS = [ - { key: 'journals', label: '学术期刊与会议情报', icon: '📰' }, + { key: 'journals', label: '学术期刊情报', icon: '📰' }, { key: 'recommend', label: '智能投稿推荐', icon: '🎯' }, { key: 'presubmit', label: 'AI 预审稿系统', icon: '🔍' }, { key: 'report', label: '专业审稿意见报告', icon: '📝' }, diff --git a/ui/src/components/edu/panels/JournalsPanel.vue b/ui/src/components/edu/panels/JournalsPanel.vue index c0fef9d..983a7ed 100644 --- a/ui/src/components/edu/panels/JournalsPanel.vue +++ b/ui/src/components/edu/panels/JournalsPanel.vue @@ -1,4 +1,4 @@ - @@ -338,14 +339,14 @@ onUnmounted(() => clearTimeout(searchTimer)); @@ -368,18 +369,21 @@ onUnmounted(() => clearTimeout(searchTimer)); @@ -585,6 +589,11 @@ onUnmounted(() => clearTimeout(searchTimer)); .jp-dash { color: var(--pa-ink-subtle); } +/* 来源口径说明(灰色小字):分区常量文案 + 链接后括号补充 */ +.jp-src-note { + font-size: 12px; + color: var(--pa-ink-subtle); +} /* —— 列宽白名单(table 自适应 + min-width,不硬截断)—— */ .jp-c-name { min-width: 200px; } .jp-c-dir { min-width: 140px; } -- 2.52.0 From dddb70ff6f44acf43ae6af5fe99b44fccfbe5cc8 Mon Sep 17 00:00:00 2001 From: potaser Date: Sun, 11 Oct 2026 12:19:18 +0800 Subject: [PATCH 6/8] fix(review): directory partition source shown as constant note Stop sending partition_source_url; respond with a fixed explanatory note instead. DB values untouched (dropped after SELECT). --- .../app/routers/journal_directory.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/review_service/app/routers/journal_directory.py b/review_service/app/routers/journal_directory.py index b92b60d..113ddcc 100644 --- a/review_service/app/routers/journal_directory.py +++ b/review_service/app/routers/journal_directory.py @@ -11,12 +11,14 @@ 读时归一化(拍板细节 1-3,均在 API 层做,不动脚本/DB 原值): 细节1 lang=zh → cas_partition 恒 null + cas_partition_note="不按中科院分区口径列示"; 细节2 jif_note 源文本映射(v4 值域已是用户可读文本,旧值映射保留兜底); - 细节3 缺值即矛盾清零:en 且 jif=null → jif_source_url=null; - cas_partition=null → partition_source_url=null。 + 细节3 缺值即矛盾清零:en 且 jif=null → jif_source_url=null。 (zh 的 IF 载体是 composite/comprehensive,其 jif_source_url 本恒 null。) - 决策2:响应不再下发"来源"文本字段(partition_source/jif_source/data_source_label - 已从 DirectoryItem 移除;jif_source_url/partition_source_url/data_source_url - 保留,供前端展开行链接)。新增 official_check_status / jcr_release_year。 + 决策2:响应不下发"来源"文本字段(partition_source/jif_source/data_source_label + 已移除);jif_source_url/data_source_url 保留供展开行链接。 + 决策4(来源展示优化):partition_source_url 不再下发——DB 原值分毫未动 + (仍 SELECT * 读出后被模型丢弃),响应改为常量字段 partition_source_note + 文案,前端以灰色说明文字替代原"分区来源"超链接。 + 新增 official_check_status / jcr_release_year。 """ from __future__ import annotations @@ -54,6 +56,10 @@ _JIF_NOTE_MAP = { "所用年度来源未检得": "本次汇编未查到,建议查阅最新 JCR", } _ZH_PART_NOTE = "不按中科院分区口径列示" +# 决策4:分区来源改为常量说明文案(不下发 partition_source_url;DB 原值不动) +_PARTITION_SOURCE_NOTE = ( + "2025 中科院官方表(2026 年起停更;官方入口 fenqubiao.com 需机构登录)" +) _NOTE_EN = ( "分区:2025年中科院公开表(多表比对,2026年起停止更新);" @@ -101,7 +107,7 @@ class DirectoryItem(BaseModel): official_check_status: str | None = None jcr_release_year: int | None = None jif_source_url: str | None = None - partition_source_url: str | None = None + partition_source_note: str = _PARTITION_SOURCE_NOTE # 决策4:常量,替代分区来源链接 data_source_url: str | None = None @@ -145,12 +151,10 @@ def _present(raw: dict[str, Any], lang: str) -> dict[str, Any]: d["cas_partition_note"] = _ZH_PART_NOTE # 细节3:缺值 → 来源链接清零(消除 null 值却挂来源链接的矛盾; - # "来源"文本字段已按决策2 移出响应,此处只清 *_url) + # 分区来源链接已按决策4 移出响应,改为常量 partition_source_note) if lang == "en": if d.get("jif") is None: d["jif_source_url"] = None - if d.get("cas_partition") is None: - d["partition_source_url"] = None return d -- 2.52.0 From 55410b663a44183db2eabd75bb09b25ef64dcdad Mon Sep 17 00:00:00 2001 From: potaser Date: Sun, 11 Oct 2026 12:19:18 +0800 Subject: [PATCH 7/8] feat(review): journal format-rule fetch scripts (offline CLI) - fetch_format_rules.py CLI: robots.txt-aware fetcher (httpx + bs4, >=2s per-host throttle) + DeepSeek quote-backed rule extractor - Status: OUP/Wiley/Cell return 403 from this environment; the five featured journals' format_rules in journals.json were manually verified against official sites instead. Tooling kept for future re-runs; data/format_cache/ is runtime output and gitignored - Service code never imports this toolchain (standalone CLI only) --- .gitignore | 1 + .../app/services/format_extractor.py | 232 ++++++++++++ review_service/app/services/format_fetcher.py | 356 ++++++++++++++++++ review_service/scripts/README.md | 17 + review_service/scripts/fetch_format_rules.py | 122 ++++++ 5 files changed, 728 insertions(+) create mode 100644 review_service/app/services/format_extractor.py create mode 100644 review_service/app/services/format_fetcher.py create mode 100644 review_service/scripts/README.md create mode 100644 review_service/scripts/fetch_format_rules.py diff --git a/.gitignore b/.gitignore index 259c747..2850fb3 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,4 @@ review_service/data/reformat_jobs/ !review_service/data/ review_service/tools/tectonic review_service/data/tectonic-cache/ +review_service/data/format_cache/ diff --git a/review_service/app/services/format_extractor.py b/review_service/app/services/format_extractor.py new file mode 100644 index 0000000..05a5c1e --- /dev/null +++ b/review_service/app/services/format_extractor.py @@ -0,0 +1,232 @@ +"""services/format_extractor.py —— 投稿指南 → 格式规则 JSON(LLM 抽取,第一批)。 + +- 调 services/llm.py 的 complete_json(DeepSeek json_object + 修复重试,零新依赖) +- Prompt = 「格式规则抽取器」模板:目标字段与 journals.json format_rules_default + 同构(max_pages / min_font_pt / min_margin_mm / min_line_spacing / min_figures / + max_fonts / refs_style / anonymous),强制每字段带 source_quotes + confidence +- 诚实原则:正文没写 → null,绝不编造(与 format_check 诚实原则一致) +- 解析/校验失败 → {"ok": False, "error": ...} + +返回: + 成功 {"ok": True, "rules": {...}, "source_quotes": {...}, + "confidence": {...}, "notes": str, "raw": LLM原始JSON, "error": None} + 失败 {"ok": False, "error": "...", 其余键为 None} +source_url 由调用方(scripts/fetch_format_rules.py)在落盘时补入结果文件。 +""" +from __future__ import annotations + +import logging +import re +from typing import Any + +from .llm import LLMError, complete_json + +logger = logging.getLogger(__name__) + +# 「格式规则抽取器」模板(system prompt) +_SYSTEM = """你是「格式规则抽取器」:从期刊官方投稿指南的 Markdown 正文中抽取格式规则,供投稿排版检查引擎使用。 + +# 目标字段(rules 对象,严格用以下字段名) +- max_pages:正文页数上限(整数;原文无明确上限 → null) +- min_font_pt:最小字号(数字,单位 pt;原文若用 cm/mm/inch 给出则换算为 pt) +- min_margin_mm:最小页边距(数字,单位 mm;原文若用 inch 给出则 ×25.4 换算) +- min_line_spacing:最小行距倍数(数字;如 "double-spaced" → 2.0,"1.5 spacing" → 1.5) +- min_figures:研究论文最少图数(整数;无明确要求 → null) +- max_fonts:全文最多字体种类(整数;无明确要求 → null) +- refs_style:参考文献样式,枚举 apa | gb7714 | author_year | numbered | vancouver | mla | chicago | other(无法判断 → null) +- anonymous:是否要求匿名/双盲评审(true / false / null) + +# 凭证(强制) +- 每个非 null 字段必须给 source_quotes[字段名]:从正文【逐字】摘录的 1-3 句原文, + 不改写、不翻译、不丢掉含关键数字的句子。 +- source_quotes["_general"]:整体最有凭证价值的 1-3 条原文摘录。 +- confidence:{"overall": 0-1, "per_field": {"字段名": 0-1}}。 + 直接原文命中 ≥0.9;单位换算 0.6-0.9;靠上下文推断 <0.6。 + +# 诚实原则 +- 正文没写到的字段一律 null,绝不用常识或训练记忆补值。 +- 单位换算允许做,但该字段 confidence 不得超过 0.9。 +- 换算过程、拿不准的点、页面疑似不完整,写进 notes。 + +# 输出 +只输出一个 JSON 对象,不要代码块、不要解释文字: +{"rules": {"max_pages": null, "min_font_pt": null, "min_margin_mm": null, + "min_line_spacing": null, "min_figures": null, "max_fonts": null, + "refs_style": null, "anonymous": null}, + "source_quotes": {"字段名": ["原文1", "..."], "_general": ["原文1", "..."]}, + "confidence": {"overall": 0.0, "per_field": {"字段名": 0.0}}, + "notes": "一句话说明抽取依据与不确定点"}""" + +_USER_TMPL = """期刊:{journal_name} + +=== 官方投稿指南正文(Markdown,已截断) === +{markdown}""" + +_RULE_INT_KEYS = ("max_pages", "min_figures", "max_fonts") +_REFS_ALLOWED = {"apa", "gb7714", "author_year", "numbered", "vancouver", + "mla", "chicago", "other"} +_REFS_ALIAS = { + "apa-7": "apa", "apa7": "apa", "apa 7th": "apa", "apa_7th": "apa", + "harvard": "author_year", "author-year": "author_year", "authoryear": "author_year", + "gb/t 7714": "gb7714", "gb/t-7714": "gb7714", "gb7714-2015": "gb7714", + "gb/t7714": "gb7714", "chicago author-date": "chicago", +} + + +# 字符串值带显式单位时的目标单位换算表(LLM 若回传原文单位的兜底;无单位=数值即目标单位) +_UNIT_TO_MM = {"mm": 1.0, "cm": 10.0, "in": 25.4, "inch": 25.4, "inches": 25.4, "pt": 25.4 / 72} +_UNIT_TO_PT = {"pt": 1.0, "mm": 72 / 25.4, "cm": 72 / 2.54, "in": 72.0, "inch": 72.0, "inches": 72.0} + + +def _to_int(v: Any) -> int | None: + if isinstance(v, bool) or v is None: + return None + if isinstance(v, int): + return v + if isinstance(v, float): + return int(round(v)) + if isinstance(v, str): + m = re.search(r"-?\d+", v) + if m: + return int(m.group(0)) + return None + + +def _to_float(v: Any, units: dict[str, float] | None = None) -> float | None: + if isinstance(v, bool) or v is None: + return None + if isinstance(v, (int, float)): + return float(v) + if isinstance(v, str): + m = re.search(r"(-?\d+(?:\.\d+)?)\s*([a-zA-Z]+)?", v) + if not m: + return None + x = float(m.group(1)) + unit = (m.group(2) or "").lower() + if units and unit: + factor = units.get(unit) + if factor is None: + return None # 未知单位不猜 + x *= factor + return x + return None + + +def _to_bool(v: Any) -> bool | None: + if isinstance(v, bool): + return v + if isinstance(v, (int, float)) and not isinstance(v, bool): + if v in (0, 1): + return bool(v) + if isinstance(v, str): + low = v.strip().lower() + if low in ("true", "yes", "required"): + return True + if low in ("false", "no", "not required"): + return False + return None + + +def _norm_refs(v: Any) -> str | None: + if not isinstance(v, str) or not v.strip(): + return None + low = v.strip().lower() + low = _REFS_ALIAS.get(low, low) + return low if low in _REFS_ALLOWED else "other" + + +def _norm_conf(v: Any) -> float | None: + if isinstance(v, bool) or not isinstance(v, (int, float)): + return None + return max(0.0, min(1.0, float(v))) + + +def _normalize(raw: dict[str, Any]) -> dict[str, Any]: + """白名单归一:类型错的值置 null(宁缺勿错,raw 全量保留在结果里)。""" + src = raw.get("rules") + src = src if isinstance(src, dict) else {} + rules: dict[str, Any] = {} + for k in _RULE_INT_KEYS: + rules[k] = _to_int(src.get(k)) + rules["min_font_pt"] = _to_float(src.get("min_font_pt"), _UNIT_TO_PT) + rules["min_margin_mm"] = _to_float(src.get("min_margin_mm"), _UNIT_TO_MM) + rules["min_line_spacing"] = _to_float(src.get("min_line_spacing")) + rules["refs_style"] = _norm_refs(src.get("refs_style")) + rules["anonymous"] = _to_bool(src.get("anonymous")) + + sq_src = raw.get("source_quotes") + sq_src = sq_src if isinstance(sq_src, dict) else {} + quotes: dict[str, list[str]] = {} + for key, val in sq_src.items(): + if key != "_general" and key not in rules: + continue + items = val if isinstance(val, list) else [val] + cleaned = [str(x).strip() for x in items if isinstance(x, (str, int, float)) + and str(x).strip()] + if cleaned: + quotes[key] = cleaned + + conf_src = raw.get("confidence") + conf_src = conf_src if isinstance(conf_src, dict) else {} + pf_src = conf_src.get("per_field") + pf_src = pf_src if isinstance(pf_src, dict) else {} + per_field: dict[str, float] = {} + for k, v in pf_src.items(): + c = _norm_conf(v) + if c is not None and (k in rules or k == "_general"): + per_field[k] = c + overall = _norm_conf(conf_src.get("overall")) + if overall is None and per_field: + overall = sum(per_field.values()) / len(per_field) + confidence = {"overall": overall, "per_field": per_field} + + notes = raw.get("notes") + return { + "rules": rules, + "source_quotes": quotes, + "confidence": confidence, + "notes": str(notes) if notes else "", + } + + +def _validation_error(norm: dict[str, Any]) -> str | None: + """强制凭证:任一非 null 字段缺 source_quotes → 拒收(ok=False)。""" + missing = [k for k, v in norm["rules"].items() + if v is not None and k not in norm["source_quotes"]] + if missing: + return f"LLM 输出缺少非 null 字段的 source_quotes:{', '.join(missing)}" + if not norm["source_quotes"].get("_general"): + return "LLM 输出缺少 source_quotes._general 整体引证" + if any(v is not None for v in norm["rules"].values()): + return None + return "LLM 未抽出任何非 null 字段(rules 全空)" + + +async def extract_format_rules(markdown: str, journal_name: str) -> dict: + """markdown(≤30000 字符)+ 期刊名 → 抽取结果(schema 见模块 docstring)。""" + if not markdown or not markdown.strip(): + return {"ok": False, "error": "markdown 为空", "rules": None, + "source_quotes": None, "confidence": None, "notes": None, "raw": None} + user = _USER_TMPL.format(journal_name=journal_name, markdown=markdown) + try: + raw = await complete_json(_SYSTEM, user, temperature=0.1, max_tokens=8000) + except LLMError as exc: + return {"ok": False, "error": f"LLM 调用失败:{exc}", "rules": None, + "source_quotes": None, "confidence": None, "notes": None, "raw": None} + if not isinstance(raw, dict): + return {"ok": False, "error": f"LLM 输出非 JSON 对象:{type(raw).__name__}", + "rules": None, "source_quotes": None, "confidence": None, + "notes": None, "raw": None} + + norm = _normalize(raw) + err = _validation_error(norm) + if err: + logger.warning("[extract] %s 校验失败:%s", journal_name, err) + return {"ok": False, "error": err, "rules": None, + "source_quotes": norm["source_quotes"], "confidence": norm["confidence"], + "notes": norm["notes"], "raw": raw} + filled = sum(1 for v in norm["rules"].values() if v is not None) + logger.info("[extract] %s → 8 字段中 %d 个非 null", journal_name, filled) + return {"ok": True, "error": None, "rules": norm["rules"], + "source_quotes": norm["source_quotes"], + "confidence": norm["confidence"], "notes": norm["notes"], "raw": raw} diff --git a/review_service/app/services/format_fetcher.py b/review_service/app/services/format_fetcher.py new file mode 100644 index 0000000..1710d8e --- /dev/null +++ b/review_service/app/services/format_fetcher.py @@ -0,0 +1,356 @@ +"""services/format_fetcher.py —— 投稿指南页面抓取(格式规则自动获取·第一批)。 + +约束(用户拍板 2026-10-10): +- 零新依赖:httpx + beautifulsoup4(venv 已装 4.15.0,用户明确指定使用; + lxml 6.1.2 在 requirements.lock 内,作 bs4 解析器) +- 同域限速 ≥ 2s(robots.txt 与正文请求共用计时器) +- 抓正文前先 GET /robots.txt,命中 Disallow → ok=False 跳过 +- UA: "PlantAI-RAG-Bot/1.0 (+contact: admin@example.com)" +- 只提取正文(去导航/页脚/脚本),截断至 30000 字符 + +返回固定四键:{"ok": bool, "markdown": str, "error": str | None, "fetched_at": str} +""" +from __future__ import annotations + +import asyncio +import logging +import re +import time +from datetime import datetime, timezone +from urllib.parse import urlparse + +import httpx +from bs4 import BeautifulSoup, NavigableString + +logger = logging.getLogger(__name__) + +USER_AGENT = "PlantAI-RAG-Bot/1.0 (+contact: admin@example.com)" +TIMEOUT = 30.0 +MAX_CHARS = 30_000 +MIN_INTERVAL_PER_HOST = 2.0 # 同域请求间隔 ≥ 2s(robots 与正文共用) +_MIN_TEXT_CHARS = 200 # 正文短于此 → 疑似 JS 渲染/反爬页 +_HEADERS = { + "User-Agent": USER_AGENT, + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Accept-Language": "en-US,en;q=0.9", +} + +# 同域限速:host → 上次请求完成时刻(monotonic) +_last_hit: dict[str, float] = {} +_throttle_lock = asyncio.Lock() + + +def _now_iso() -> str: + return datetime.now(timezone.utc).isoformat(timespec="seconds") + + +def _fail(error: str) -> dict: + return {"ok": False, "markdown": "", "error": error, "fetched_at": _now_iso()} + + +async def _throttle(host: str) -> None: + """同域串行 + ≥2s 间隔(全局锁:本批抓取量小,简单可靠优先)。""" + async with _throttle_lock: + now = time.monotonic() + wait = _last_hit.get(host, now) + MIN_INTERVAL_PER_HOST - now + if wait > 0: + await asyncio.sleep(wait) + _last_hit[host] = time.monotonic() + + +# ---------------------------------------------------------------- robots.txt + +def _parse_robots(text: str) -> list[tuple[list[str], list[tuple[str, str]]]]: + """→ [(agents, [(kind, pattern)...]), ...](连续 UA 行同组;规则行后出现 UA=新组)。""" + groups: list[tuple[list[str], list[tuple[str, str]]]] = [] + agents: list[str] = [] + rules: list[tuple[str, str]] = [] + for raw in text.splitlines(): + line = raw.split("#", 1)[0].strip() + if not line or ":" not in line: + continue + key, _, value = line.partition(":") + key, value = key.strip().lower(), value.strip() + if key == "user-agent": + if agents and rules: # 上一组已出规则 → 当前 UA 行开新组 + groups.append((agents, rules)) + agents, rules = [], [] + agents.append(value) + elif key in ("allow", "disallow"): + if not agents: # 无前置 UA 的规则按 * 组处理 + agents = ["*"] + rules.append((key, value)) + if agents: + groups.append((agents, rules)) + return groups + + +def _robots_path_allowed(groups, path: str) -> tuple[bool, str]: + """最长匹配决胜(同长 Allow 优先;`$` 结尾=精确匹配;空 Disallow 跳过)。""" + + def matched_by(pat: str) -> bool: + if pat.endswith("$"): + return path == pat[:-1] + return path.startswith(pat) + + token = "plantai-rag-bot" + matched = [rules for agents, rules in groups + if any(token in a.lower() for a in agents)] + if not matched: + matched = [rules for agents, rules in groups + if any(a.lower() == "*" for a in agents)] + if not matched: + return True, "robots.txt 无匹配组(本 bot 不受限)" + + best_len, best_allow, best_pat = -1, False, "" + for rules in matched: + for kind, pat in rules: + if not pat: # "Disallow:" 空值 = 放行一切(该组无需处理) + continue + if not matched_by(pat): + continue + length = len(pat) + allow = kind == "allow" + if length > best_len or (length == best_len and allow and not best_allow): + best_len, best_allow, best_pat = length, allow, pat + if best_len < 0: + return True, "robots.txt 允许(无路径匹配)" + if best_allow: + return True, f"robots.txt Allow 命中({best_pat})" + return False, f"robots.txt Disallow 命中({best_pat})" + + +async def _robots_allows(client: httpx.AsyncClient, url: str) -> tuple[bool, str]: + p = urlparse(url) + robots_url = f"{p.scheme}://{p.netloc}/robots.txt" + await _throttle(p.netloc.lower()) + try: + resp = await client.get(robots_url, headers=_HEADERS) + except httpx.HTTPError as exc: + return True, f"robots.txt 获取失败({type(exc).__name__}),按允许处理" + if resp.status_code != 200: + return True, f"robots.txt HTTP {resp.status_code},按允许处理" + groups = _parse_robots(resp.text) + return _robots_path_allowed(groups, p.path or "/") + + +# ---------------------------------------------------------------- 正文提取 + +_STRIP_TAGS = ("script", "style", "noscript", "iframe", "form", "nav", + "footer", "aside", "button", "select", "textarea", "input", "svg") +_STRIP_ROLES = ("navigation", "contentinfo", "complementary", "search") +# 正文容器候选(按优先级;首个文本 ≥500 字符者胜出) +_CONTENT_SELECTORS = ( + "main", "article", '[role="main"]', "#content", "#main", "#main-content", + ".article-body", "#article-body", ".article__body", ".hub-article-body", + ".page-content", ".main-content", ".content-area", +) +_CHALLENGE_MARKERS = ("just a moment", "attention required", "captcha", + "access denied", "ddos protection", "verify you are human") + + +def _decode_html(resp: httpx.Response) -> str: + """header charset → → utf-8(errors=replace),防 OUP/Wiley 无 header 乱码。""" + enc = None + m = re.search(r"charset=([\w.-]+)", resp.headers.get("content-type", ""), re.I) + if m: + enc = m.group(1) + if not enc: + m = re.search(rb"""charset\s*=\s*["']?([\w.-]+)""", resp.content[:4096], re.I) + if m: + enc = m.group(1).decode("ascii", "ignore") + try: + return resp.content.decode(enc or "utf-8", errors="replace") + except LookupError: + return resp.content.decode("utf-8", errors="replace") + + +def _squeeze(s: str) -> str: + """行内空白压缩 + 去空行(保留单换行)。""" + lines = [re.sub(r"[ \t\r\f\v]+", " ", line).strip() for line in s.split("\n")] + return "\n".join(line for line in lines if line) + + +def _inline(el) -> str: + """行内渲染:a→md链接 / strong→** / em→* / code→` / br→换行;跳过列表与图片。""" + parts: list[str] = [] + for child in el.children: + name = getattr(child, "name", None) + if name is None: # NavigableString + parts.append(str(child)) + continue + if name in ("ul", "ol", "img", "picture", "figure"): + continue + if name == "a": + href = (child.get("href") or "").strip() + txt = _inline(child).strip() + if not txt: + continue + parts.append(f"[{txt}]({href})" if href.startswith(("http://", "https://")) else txt) + elif name in ("strong", "b"): + parts.append(f"**{_inline(child)}**") + elif name in ("em", "i"): + parts.append(f"*{_inline(child)}*") + elif name == "code": + parts.append(f"`{_inline(child).strip()}`") + elif name == "br": + parts.append("\n") + else: + parts.append(_inline(child)) + return "".join(parts) + + +def _list_md(el, ordered: bool) -> str: + lines: list[str] = [] + idx = 1 + for li in el.find_all("li", recursive=False): + # li 文本不含嵌套列表(嵌套列表随后缩进输出) + buf = [] + for child in li.children: + if getattr(child, "name", None) in ("ul", "ol"): + continue + buf.append(_inline(child) if getattr(child, "name", None) else str(child)) + txt = " ".join("".join(buf).split()) + if txt: + lines.append(f"{idx}. {txt}" if ordered else f"- {txt}") + idx += 1 + for nested in li.find_all(("ul", "ol"), recursive=False): + sub = _list_md(nested, nested.name == "ol") + if sub: + lines.extend(" " + line for line in sub.split("\n")) + return "\n".join(lines) + + +def _table_md(table) -> str | None: + rows: list[list[str]] = [] + for tr in table.find_all("tr"): + cells = [" ".join(_squeeze(_inline(c)).split()) + for c in tr.find_all(("td", "th"))] + if cells: + rows.append(cells) + if not rows: + return None + out = ["| " + " | ".join(rows[0]) + " |"] + if table.find("th"): # 首行含表头 → 补分隔行(合法 GFM 表) + out.append("| " + " | ".join(["---"] * len(rows[0])) + " |") + out += ["| " + " | ".join(r) + " |" for r in rows[1:]] + return "\n".join(out) + + +def _blocks(el, out: list[str]) -> None: + for child in el.children: + name = getattr(child, "name", None) + if name is None: # 裸文本 + txt = _squeeze(str(child)) + if txt: + out.append(txt) + continue + if name in _STRIP_TAGS: + continue + if name in ("h1", "h2", "h3", "h4", "h5", "h6"): + txt = " ".join(_squeeze(_inline(child)).split()) + if txt: + out.append("#" * int(name[1]) + " " + txt) + elif name == "p": + txt = _squeeze(_inline(child)) + if txt: + out.append(txt) + elif name in ("ul", "ol"): + md = _list_md(child, name == "ol") + if md: + out.append(md) + elif name == "table": + md = _table_md(child) + if md: + out.append(md) + elif name == "blockquote": + txt = _squeeze(_inline(child)) + if txt: + out.append("\n".join("> " + line for line in txt.split("\n"))) + elif name == "pre": + code = child.get_text().strip("\n") + if code.strip(): + out.append("```\n" + code + "\n```") + elif name == "hr": + out.append("---") + else: # div/section/article/main/figure/dl/details/… 容器递归 + _blocks(child, out) + + +def _html_to_markdown(html: str) -> tuple[str, str | None]: + """→ (markdown, error)。选正文容器 → 去壳 → DOM 递归转 Markdown。""" + soup = BeautifulSoup(html, "lxml") # lxml 在 lock 内;缺时 bs4 自动回退 html.parser + + title = (soup.title.get_text() if soup.title else "") or "" + for tag in soup.find_all(_STRIP_TAGS): + tag.decompose() + for tag in soup.find_all(attrs={"role": _STRIP_ROLES}): + tag.decompose() + + container = None + fallback_hits = [] + for sel in _CONTENT_SELECTORS: + for node in soup.select(sel): + text_len = len(node.get_text(" ", strip=True)) + fallback_hits.append((text_len, node)) + if text_len >= 500: + container = node + break + if container is not None: + break + if container is None: + if fallback_hits: + container = max(fallback_hits, key=lambda x: x[0])[1] + else: + container = soup.body or soup + + blocks: list[str] = [] + _blocks(container, blocks) + md = "\n\n".join(blocks) + + probe = (title + " " + md[:500]).lower() + marker = next((m for m in _CHALLENGE_MARKERS if m in probe), None) + if marker: + return "", f"疑似反爬/挑战页(命中 {marker!r},title={title[:80]!r})" + if len(md) < _MIN_TEXT_CHARS: + return "", f"正文提取过短({len(md)} < {_MIN_TEXT_CHARS} 字符),疑似 JS 渲染或空壳页" + if len(md) > MAX_CHARS: + md = md[:MAX_CHARS - 1] + "…" + return md, None + + +# ---------------------------------------------------------------- 入口 + +async def fetch_submission_guidelines(url: str) -> dict: + """抓投稿指南页面 → 正文 Markdown。 + + 流程:robots.txt 检查(≥2s 限速)→ 禁止即跳过 → GET 正文(≥2s 限速) + → 状态/类型校验 → 正文提取 → 截断 30000 字符。 + """ + parsed = urlparse(url) + if parsed.scheme not in ("http", "https") or not parsed.netloc: + return _fail(f"非法 URL:{url!r}") + host = parsed.netloc.lower() + + async with httpx.AsyncClient(follow_redirects=True, timeout=TIMEOUT) as client: + allowed, robots_reason = await _robots_allows(client, url) + if not allowed: + logger.info("[fetch] robots 禁止,跳过 %s(%s)", url, robots_reason) + return _fail(robots_reason) + + await _throttle(host) + try: + resp = await client.get(url, headers=_HEADERS) + except httpx.HTTPError as exc: + return _fail(f"请求失败({type(exc).__name__}):{exc}") + if resp.status_code != 200: + return _fail(f"HTTP {resp.status_code}") + ctype = resp.headers.get("content-type", "") + if "html" not in ctype and "xhtml" not in ctype: + return _fail(f"非 HTML 响应:{ctype or '无 Content-Type'}") + + markdown, err = _html_to_markdown(_decode_html(resp)) + if err: + return _fail(f"{err}(robots: {robots_reason})") + logger.info("[fetch] %s → %d 字符(robots: %s)", url, len(markdown), robots_reason) + return {"ok": True, "markdown": markdown, "error": None, "fetched_at": _now_iso()} diff --git a/review_service/scripts/README.md b/review_service/scripts/README.md new file mode 100644 index 0000000..c1f8d81 --- /dev/null +++ b/review_service/scripts/README.md @@ -0,0 +1,17 @@ +# scripts/ —— 离线工具(不被 app/ 服务代码引用,独立 CLI) + +## fetch_format_rules.py —— 投稿指南自动抓取(探索性,第一批) + +- 依赖:venv 已装的 httpx + beautifulsoup4 4.15.0(用户拍板 2026-10-10); + 解析器 lxml 6.1.2 在 `tooling/requirements.lock` 内。 +- 用法与流程见 `fetch_format_rules.py` 模块 docstring(CLI 一次一本期刊)。 +- 产物:`data/format_cache/{journal_id}.json`(运行产物,已 gitignore,不入库)。 + +### 现状(2026-10-10) + +OUP / Wiley / Cell 官网对本运行环境返回 403,自动抓取路线失败; +Genome Biology / BMC Plant Biology / Frontiers / Rice 可抓但 LLM 抽取结果 +仍需人工对照官网。当前 `journals.json` 中 5 本精选期刊的 `format_rules` +为**人工核验官网原文后写入**(`rules_source=official` + `source_url` + +`last_verified`),**不是**本脚本产物。本工具保留作为后续换网络环境 / +换可达站点后的重跑手段。 diff --git a/review_service/scripts/fetch_format_rules.py b/review_service/scripts/fetch_format_rules.py new file mode 100644 index 0000000..4b5dd3a --- /dev/null +++ b/review_service/scripts/fetch_format_rules.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +"""scripts/fetch_format_rules.py —— 格式规则自动获取(第一批,人工核验用 CLI)。 + +用法(在 review_service/ 下): + /home/xzq/5090/teamWorkspace/zh/plantai-rag-new-venv/bin/python \ + scripts/fetch_format_rules.py + +流程: + 1. fetch_submission_guidelines(url) # robots.txt + 同域 ≥2s 限速 + 正文转 Markdown + 2. extract_format_rules(markdown, journal_name) # DeepSeek 抽取(llm.py) + 3. 存 data/format_cache/{journal_id}.json(失败也存,便于批量对账) + 4. 打印完整结果 JSON 供人工核验 + +凭证:结果文件顶层 source_url(步骤 1 的实际抓取地址)+ source_quotes(LLM +逐字引证,按字段分组);非 null 字段缺引证 → 抽取判失败(ok=false)。 + +约束(第一批):只跑指定 3 本;不触 API / 前端 / journals.json(format_rules 只读 +查名,不写回)。journal_name 优先取 data/journals/journals.json 的 name(只读)。 +""" +from __future__ import annotations + +import asyncio +import json +import os +import re +import sys +from datetime import datetime, timezone +from pathlib import Path + +_ROOT = Path(__file__).resolve().parents[1] # review_service/ +sys.path.insert(0, str(_ROOT)) + +_JOURNALS_JSON = _ROOT / "data" / "journals" / "journals.json" +_CACHE_DIR = _ROOT / "data" / "format_cache" + + +def _load_env() -> None: + """镜像 restart.sh 的 `set -a; source .env`:REVIEW_LLM_*/DOCGEN_LLM_* 裸键 + 由 services/llm.py 在每次调用时读 os.environ(不缓存),故调用前灌入即可。""" + env_path = _ROOT / ".env" + if not env_path.is_file(): + return + for raw in env_path.read_text("utf-8").splitlines(): + line = raw.strip() + if not line or line.startswith("#") or "=" not in line: + continue + if line.startswith("export "): + line = line[7:].strip() + key, _, val = line.partition("=") + os.environ.setdefault(key.strip(), val.strip().strip("\"'")) + + +def _journal_name(journal_id: str) -> str: + """journals.json 只读查名;查不到 → id 连字符转空格并首字母大写(LLM 上下文可读)。""" + try: + data = json.loads(_JOURNALS_JSON.read_text("utf-8")) + for j in data.get("journals") or []: + if j.get("id") == journal_id: + return str(j.get("name") or journal_id) + except Exception: # noqa: BLE001 + pass + return journal_id.replace("-", " ").title() + + +def main() -> int: + if len(sys.argv) != 3: + print("用法: fetch_format_rules.py ", file=sys.stderr) + return 2 + journal_id = re.sub(r"[^\w.-]", "_", sys.argv[1].strip()) + url = sys.argv[2].strip() + _load_env() + + from app.services.format_extractor import extract_format_rules + from app.services.format_fetcher import fetch_submission_guidelines + + async def run() -> tuple[dict, dict]: + fetched = await fetch_submission_guidelines(url) + print(f"[1/2] 抓取 {url} → ok={fetched['ok']}" + + (f",markdown={len(fetched['markdown'])} 字符" + if fetched["ok"] else f",error={fetched['error']}")) + if not fetched["ok"]: + return fetched, {"ok": False, "error": f"抓取失败:{fetched['error']}", + "rules": None, "source_quotes": None, + "confidence": None, "notes": None, "raw": None} + extracted = await extract_format_rules(fetched["markdown"], _journal_name(journal_id)) + if extracted["ok"]: + filled = sum(1 for v in extracted["rules"].values() if v is not None) + print(f"[2/2] LLM 抽取 → ok=True,8 字段中 {filled} 个非 null") + else: + print(f"[2/2] LLM 抽取 → ok=False,error={extracted['error']}") + return fetched, extracted + + fetched, extracted = asyncio.run(run()) + + result = { + "journal_id": journal_id, + "journal_name": _journal_name(journal_id), + "source_url": url, + "fetched_at": fetched.get("fetched_at"), + "extracted_at": datetime.now(timezone.utc).isoformat(timespec="seconds"), + "markdown_chars": len(fetched.get("markdown") or ""), + "ok": bool(extracted.get("ok")), + "error": extracted.get("error"), + "format_rules": ({**extracted["rules"], "rules_source": "fetched"} + if extracted.get("ok") else None), + "source_quotes": extracted.get("source_quotes"), + "confidence": extracted.get("confidence"), + "notes": extracted.get("notes"), + "raw_llm": extracted.get("raw"), + } + _CACHE_DIR.mkdir(parents=True, exist_ok=True) + out_path = _CACHE_DIR / f"{journal_id}.json" + out_path.write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n", "utf-8") + + print(f"[save] {out_path.relative_to(_ROOT)}") + print("===== 完整结果(人工核验)=====") + print(json.dumps(result, ensure_ascii=False, indent=2)) + return 0 if result["ok"] else 1 + + +if __name__ == "__main__": + sys.exit(main()) -- 2.52.0 From 11337a788fdede4ca786ad702f9528b76562e100 Mon Sep 17 00:00:00 2001 From: admin Date: Sun, 11 Oct 2026 13:29:35 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20.gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 解决冲突 Signed-off-by: admin --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2850fb3..85d9284 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# 运行时产物与环境 +# 运行时产物与环境 node_modules dist/ .venv/ -- 2.52.0

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 z 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͞m8<)>5<*<^D=#1zxb$?b%4s; zeRmqX!Rwa&s4(V;?G=p@DpK{A&XVUy7$QDRnKHaNJ$5+slyO*SxBTdP?$Aso6uLbt z^kRMO;Tx**E{F(KIapsKuk=A`SJ9RMQtsVELZe052?U8*x-}XW$A|K}gG0ky{Y!;5 z+f{>FcA5`R$L(jWw3p@mWK-n4^qu#1HtEKkh&%irBBTk+S8p%yIZ+chTD)Shl&7y3K8?Sw5pX_Us+S~Q;vHVZBJH_N z#w7Fm7heQgRY3W})Q(`_-_&BRh*;CsAwhu z{_nOsT0)QC2i3z#xw4Xy(vl!S%QV3W|52&X`<^J1F~w=~^MM2`A|DnXphUdtp(|F- zLZQWev+qn9QE^QwK=wzA3-DshfS0+JgG3)96437$6QPjww}%k1mQY2l|AVJpXgWv0xhS~TA?FH%JC~U)#sM;L zF7eW%`X4H9`2BbeRcgL9nX4hc6@AInDsp`CL5dGWU2Dy|aERD;Xj^rl8gF_0_oxBq z;(In@^bvJ}3OaHG&EK;+K}e#)h=D$4E0Ns=G*1bYn3+@;u5)2fDrs|*N91PSSS)l4 z?eNxmu3h>tDkndX)6i>Rq`3No`Ggps2I93!-2SUkufc7{=#Uy-h^Li>;6dC6gFySzl-C8eXPn6uN?nnaapXpRPWk^X3T|_Ag!1 zv98YpuK0sDRllz2lVXv8=uLgY%&?dGei5;BdawQqE7?t%qIS{Rd%dWf_n64A?Xj@H z_u|*=i3dKy@b|g!V$iJzojf6(Ze4_x1Gqyi(OZafwFV6VFN_Q?gH@}Q8UU*{xKzfe zg8!k+iur+I;KH)!-2^-_TT@{Qb8<5FpS;xv-+Grn?a=5Li3s=Du8K1ujvac?V`8-? zpiqfoTK*8ObreQXxrY_1?T(^cMI)3cjmTKE6EI?GVy5&-^S55S=8mL$^3Fk;^XhoX zRBKn54`P(C*X88ql}fgwy>AQs;&ZKo!9FS5m?4pjk3ooc*({2DI4j1?A{0R`04z$@ zHWKU;LM-TGIUy#T>59mh;*-Pk`;}8wmzD*3wF=YsVBO>GETdo~S6K>?ByEFTw|ZV* zkJXye4|c~ZwnjZm^2Zvl3z{;SJ-ei{eGr92ye{Wt<=zI>ki~KQ_xgd(XKz_G8SZU; z3&b8ktqm@`eY}iwi;qM?o{j4vF$pgCqKiW*3LIMCSlywrkYnjF$Y-;u3m1|&q3~eR zesTXX&%sE|qN4qww0Z~>IEL*P1X|ZKNF)vMpajJcWV$)40B5OCEg8uci$ zrCYli2B2PY{b}v@Fy)D`Ifw7UlZDdmmG2C0JsiBkjkw05C@9!(qkEfiT0}H%hct&v zy#b6(Dn?ef#rIU*k%xA^J&Lc}4zInHBwM~g3w!7TsV z6`NP3)OCyKkL8fV%$(Ggq-$-uTm;no(y5;tQ`m10_joheu{}j_BNLteGMziL@_pBc z?P*b-7i0Mc;gFF0H>r|>x*dfLtg!&3ABkFV0Z5+?vU>B><5-LEJjKvP1#bGZlvSk0 z=2^}1=3TV}>5FC@bP+!T{FJri8}zdsoi|GtRR(;p>FETo=wpXQeIXP+xnNhc;loKsH0ssRtF^gg%3B@B;B|jCs#^bu4y{#)-3r5GCc6O zuI@@kc~2r$y_CDKnqH3H3c^B1=nH@a7Tsm#Y_`1PKFbMcpc}bQT|I^$(<;-Z@lM~? zD)2&cu82>?K_OrnPn~YU{rC#`dISfBwcsvU=O#@pU~Gf5(GTyWYCxXBD7FXX8PTP# zSeFhx`0I$~3EsVRbw{J$$|)=z+8fbDkV$^ZzhPZ=_{Domv9O zMFYZ3@>iZinw19=cAA{^mmgtVF*cv^W2g8=Xg`C>>V?D(I4C9h|tS2Jm=ClY>ZA@VN#nUd-d77dVQDG z4@pBX%EMQu8VQH|KKD8Uh>ahu9IFS)}QftcF74FBum1c=PYeImxRPbUzr zZO7(tCb)gAc-Om9cOg3!#2w3E=_#2l;2g;(k^*>mOUR5geY0+kg z*pMXI?96^1n*c(IVbG7OAe3+zag&Q$zT#IwQ#A97dz;{n#%}jT>{-XARrxx{>Wpav z1J(}V6{1Z>O-*XuMpMT%|aU_PenVvaOLUZ zRig!uft!697!;Xk1hUp9Qlb%eKQ0eWnGRo|asCv?UkwtBS#d3Wik@Qo>B#zRMBZUS z!Yj;7&zS}5~!qooIgY5QVM_AfUEtFM1veB{8&!EWxp*NOT; zm4GWx{mRW9xx3+%n4H*LKV9~9Ij{#GM&%cU-p3**j}J>z-xThz3)=;fUe2@(0ZFyR zTO2@==S=Mo$k99%mW+OCQYSyYH$Hn*k38V&ba)Wkd3dC6Qsek4bcTD)#ps}=*op(& zJva3J_o+d;>6Q4%r|OCb_!=`p$@so6T!m}HD&W!wVA5?*qz}NQ8@}h%y-><|J56CI z^x_JyRo>6{fx;;!6y_28xn=EQgIDQLBJyKH@3VR4+53Z?nykGk0$-^PSf2X)GAvJx zf#<2uUqN~5$3~`{&}q-kqwGa@C7kW)43aA^T*Jt#Uj&90hqGe4M}*eC`$;3`U*++n z`n~UNiWBDG9S`)vFhQz>6!i(Dchxt{$#6JguBUc}W&`i+)nzcGzkii&bvDToVfAQIa6swn(NJZNWg{ zOcRg+Cy|?68YCC$RvmpvF>*O?9GCBj$t40=qfgs+u2p;+G_^C!8licnXZEzrd9qX2 zJ2dfKC`v#eqAG!sX1r~~i&w@Xfrth6li|OFs0||+qJu)DzQCA24cGuMe>P+TQsgwq z2BeB#Vyfs&-_xn2%dvkUlZn+tFy9o0cnsBq?>nN|Lgt4QrFs^ zz4y#KF>?;5d?BBh?}{{X^7B+gclPi1KabXcoRa3C4ip(cpJnPo2RS7Taw<=;=AFFX zkKo>`Riqd}mGQA#WTAjnQ@bAg_NuWvjNWKsJWXEm!{cjYwWzD$GL&UmyshDk=4=FJ zZ2WG0Sb44KtXlyxnp_D@l9OeOJf~n_-|?j|td&ZOA_i=H zQ@IGFk3k(N2T0DcFM!yk!!h2X>ifm*PD%L^&w-bbRFxwe?xVxE#tQ>o9k%hA8}cjs zDfMibFUo5*UMfpzM(a+BF~pR_(r~#J`Pa$0H4KJ1|vnZkdi=ILxvP_r27GX6xyRg;{YV%pU02Cty zEYt|pa?(@la>XK_$3!{vM4Fx5SNWsSAZF;GdO#zDB{YyEF>;2qqKVfqYH4#Kkr|x* zrVqa>DTIUiRr|&DR0G+*MqLAwR;ko(8{P=}wy({HejQdg(@bU(gEP$` zqj>l>>D}p}V4EssDNGk4B}d*8KkFx0#Cwo`i?BtYDK4^|_gEkrmb-$OG!%=;T3ndc73}5l#X^ek%Q1dp{-^O8Qf{ET zjP_)#zPJX%0@~WlN+cH8Uf^D!sTqe0LRdX9xJ+ zR6&CUXo9PlD?6YGt~27qqe!-WTB`#~FBp&i)UOYZmkgpvD~2oOCz$ze?OtSD9Zt*^ z4X*xSP$|322gEkitT9<2O9ddiX1qGEd?MLjrNBj^CZ0N+eQH*yXd($MN_QNc)AD@! z@vOdCDu}q*of&YDV&zq3n@R7hpS8Q+?Y)jot7K2=@?wbA$s>n(xG70z z+Y|#{Zy+YX0uHpI;&~Jf_-tK#8nQN{pb(2IqJKuyxLLKJTU_z47tg-UzkamxweFA# zoV>Q2bVuit@CVNGGrBo7`*QULY2%a&WyM)@PXt5_ntfOZrpD+vhI z_~*^qV}ep;a^hB1lGt}_4#n!LhBlM+nOYZjV;kkwtL-?(KN&+wQ7v${2OWdJ0e=OL zDFporFV629UMHzIVS@yIRs0o|r>3cR`=(TI1~E7l@8~IK_(68G$*Rs~t2VzaMu0QO zs&IF9HR78y1?tnG+@)rCnHQH6qqY@+V$3qhVgM|X16TwB{Eo2*k68(W%;%~JBsD?JsDJ)W;aHF+*p@E%x^K;QaQ{=kcnXY#7<%yOUQ8 z^**VMo)i!|1pD`}X7xr87Qhz=PaXEY!5NPELg+2vaH)k(pUdF!#EYXB{#T7gKGOZB zs*eZOcw%JO<|X{JDs%HeJ<@*Ox|%I4-gDIEVmTKykL zb8G((q}Aad9ht^KTP6GTmzhB@PFqj2z!N~9m6R=XHeHo(mUsUAx^@+>mxm6{ejNOZ zM;+{}nV)@R`&ruhNroY)T6~*>A3^4l*L`Jox6$0a-vZbguFegxbp^3j%pgTQcHm9v zU+uy1%t6$Cg?O}Vdz!a-OHwWOpW+iM`IC@|7*Fm(S_k;;VA8oCMnH)Lj){%>KgWcM zsJS;2&>Th^NA*=CwwA8BuWSdqKSXQkk6B(9D_O{HIxt^f&HS8sp?SPKHXAY+yiD*; zQ)Xqkh8yy`KF>W16;vyscrIXRMN+=PhF2>gJTADUCDcIL>)bd)Cgo#N$r{Y-Ca8$C z%n)(Y9YOc3>9pj;PVC`szwoDzGY=1Y7v>dCyZ$b+!iZ?b_lU$%Ul2oV&=t`C2uo?W zOjK({2a*4xcm;G2T#d?$?Uh~Kw}e*JmSR&nUk$#kUhB$xyjc~QpfkT!M<3F299#>h z&{W7(qu-fUe6R1G^`o;FLpi<(4M-*CSDzW6TF8h)!9Nl|sNyztT9tHP%&rD0D?CyP z8z|^<ErX&cPqca@z`g{5hRScrhP{F!qxOA_IfMWW2)JFn%ys)C1awG!xv5vW^sk z;w>SOqB~harTCu?2+;5+ey=}#CKSa-JtJ+uUq8M%{2Mnhpl|nWiTZ!T1yzMM`;x?y zZwDjI!rTkUu25LAPQi{;wL>TnRqgFnit=3tv$9RZ=l*s;z@g^uaJt>8m7e}NDIWoaME9deTb&*YspeU zNm<||PDI4A! zY&MEQdSrQ@L^Mc*N|}=z;Qu^H;_j|;<7ePxQoSxaR=!fNr*pr+u&#&HSwN56wgw<@ z*-R0j49JZy7Qneu?N%oo$(i)`HK;2tp%VwbZGVi^{v#Gw6nY5r!@)LRunR*uQ9z6+ zW}9D~lQDk#G3bN)<~#cvfpNu_k}q0=n;7)nxtgMv+^Cb4p%vS%i>12OEgQZV-D)9BfE-x}LzDZjSrRg2^?KD%$lx@R<1 zE&Nh?-Rj=phTeWWmWXK+gM??>;lFcyGNAp#@!j0(wiu)<;u{^@RLnMmj{o$qvOGWv zTE%B$gJ|G?wF6S{5DytdL$7)cwuwdUhE>h-BGuQ~nT)iLoR=~0SyGO3UddYG2TtAICS{C(t98+CxI(hT`*IysR?C8N5Mga>{5OsT1hpG%7yqV-( z!%4niJC?SGX2gSS^!LGdOEKL)+B#85YaL(X*oErO1R$#ra4V|l)Q4fW-d04`o$_G? zM`(6V?PF49va?$%MUDXwMIIV>p1n;W!9L;35A}elXDdJ z_QbcJBf7n(b=lQ1|0Oy<8QIfVGL{l^t%gxUbVZgz5W4)=I8Z9!9<2+{h>Y<7d{+79 zHryN@=reRrKD zY{RqPECNDe*`wYD<6Eewe)jE3&1|FkIuWOI&RM$ga~zLNVutY;wW^O<;dhf!C=nNZ zHzpSGe^m)L0$pKT;YA^1qC+Mz;0zK{DqnZqp-{Z&Y?L{I;l;*W*W&n;dGVC7{kVbo zw-PI!e$Ud?M9Swp3c3D(fk2!Ip71o>=j;R3E-nP@8=>F@MCt4;T1J)fV5={Q6Pm{V zwvF)m-?kAHE>Qh*#U^>TBLr5f^*V#1o!={}S?0P$^RyEkV$`1sAeqzKsmtM5PNUOI zBO;;VLhN1NVw;e?7)*z8fl)5{H!!q{~=2BlRY z#9~*`2CD;0c$&pScpF_>%Jl0j+9{EZCxeT;ISiAolblD}Bb1}|3Qz3dYdTtvS>w$U z<1gzV2Px2cE(@1aMqey}eqS>`CV#dR82Q;SzVWj$k?E%}K`f+Kd&=LXuw$=?`avuu zis}?OFIUjmEA$#uV4NA-ZWWo_!>-JQk7fHPx{x7v)1}7fX}jQIWPOSllDUP4y4eWlS_payR9XkDPRrYKdh_q1aAJ_R~p*q^QzpzC4`dv;J%tQYCLOIc$#e*-yAShL4Co^nt!tZ$C1JuPI%;Auf zdaeox6s-!=D=OVeTJU|BxYgIGq2S1x=YMwmJE=}rA~TO(UX}3;cw#2ovNwDzFMJ{k z$0APIEa@VM8bX`9#}rTr8<}LR*E~LYrdt^GY9aXJwkVff5kuW-E_uWz}@{;bei!IMDI+nJU-u&0m6s$w8qr( z?^?r#$fN6BKlTi_^ffO&&*S@JOKxivjeZP|k0J#YtDhKt>*0q9prsW0H6`;~C<;g) z*y4DlKlf{@;r~&Kb7k>5cIZiNPpGNgrVorxj5UG9z8~#D5QA2Y(3&Y|V=+a_`_C`m z%i|gRzic|zwI}hCcgryYE{|jk_`BpuWJ%oe7JO%SiC3+`lRquoQzi9R&?=Oba@!gU z#_Jx4uxLBUC9Pj0XOvP2U!-su4=2;xn?GhpQCxk*7EOtyK%`#IMey*vKbfN970CYE z_g*w~R&i~gh$SmOk7${XV2?sQ-hEqjB8X&2w0=(ThoP|Rw%mjU$i>(h!6&aCtbAW} z9KLRxjaVKJM~dqi8B(Pfg^|{SmbM{a7L7DNtHKLjIGyskb{FGev5{`_fyrs;seRVROic0r^+7UIMQg z8&jev1!6sO|KFL3VRW+7gOHw8#^L0o8ssxR=B1$?=gWQ@>0 zjl$9)A+@|uY7k|U zXoUEeFAXecp*2B~EUVB|uIn?mus3`KFPRFU;HgxrB(V&Va9Dg37!hb;?Ra~JehAj7 zu~JwjR&Lp4b9AZIzSy@yH*SQypDdGR*+Z`EzP!^hTqFtZt-{FXaNDUYY?S`2h>PbD zqtRoWF*z>V>V>(0uZ#LYljw#dn6m@^pkpi57(wQU8XjxSUk>56_G#=t$=+j%$BIDWn zhq&P#U?Q1Uy+rZP*9+B~fGJ~NuCozwj}DCQqCAfu+KDTzTs?%V%;}gRwfo~VA7*+8uX#}6hmxcBj-rf zS=FIG@4oP^4dtn5G!GJPG*xYT&7uH~-p?0%Bi-c|f(~*$@-$ax`G!=qS8Rha$l>S+ zW3bf%JX-{#%GD_s+;5@rA`7wQ??uEU=fzKTX1pGMeA&-E)-80;JhuJq7DkxBq|mb} z*#6*C{@&F6UZ7xepeZw!x71$Yi#7^s`R~UfeP-f!)avmkTf-Y5pRVdIMSmFPJ}pH; z%EV5Rrx`)0F-j`*i+py?aZ=s zWh36Z`#+oYuTJP*Hq3roS;Xra8;hpA8pd`_nWti)CO7vADQYy~O+FUr4xL z-L93+mMZJTG$TT48s62($rzobv25W^EU3Q+3R-wpTMGoq3t6hiq=~Aa_8Yi&Z&#=D zo5DZWe;#0eipt$uJ}T9u_PsTm>scE;=*%$d%<4VBC|GdYy1ADK%=s?-aBQuY5dyOv zMT8aly;k2%!EK>^tMpAgtO`A)aJ1Q73T$orz!V>p=F#RvDNvd-%T3L!r(e0`e(QXG zGH{tqqMu#`Wp|U3YeMVS9i4eb*Kw9nNM@&|m}Z~vA`$i~B^d24e*W~FWjn)??<_gi zdjQ7xbcFPR-xkyEyB-vK4u@cwEd$xV|b*X({tmi5REVfb0|iZI);O0bvWF9C+&W z16U#f21BGMnUb=DQ`jn@;QDNt3fH~!SkG7%UI?$Npka~%dQ?-JPL)|+;76MFcc0^V z4PcSg80>UgMBI#pHtgi@Jd+KWb>uUtyEsGef>6zB7$Ig?Y>~%Wpzx6az%>Ja+v*zi zmhItsxUSlm5$l(CzbW0-4c2b511*G_>T&O|=cmX3?@B58=M5}UQa4l~{5&46=#T>F zS6#hkyQ;8sC<^-R>!!M|lE*I--B^qRkZHRzIjzS)bb9DYHR2iFd0_wY5}x4pgQ41} z#KvR9Mbia(x;!jdJsTb*qo`2rr$`hj!{`3K92qj>M_xDnocW7nCN=6<+7=>ba>`-|a&a{@fM9xFg! zkZ5dPYzg3mn^pMsaXy)kP1QJvT+Q#m)ta?Jf4~$dvY{&PWC8?+%X^hjsBkiLta8dB zC2`A17tik#s;df4LZpaf|Nq9TGcV$otZs-a8S#4NbXk&pU|qucWO zr!NWcQ>xm8op#Rv&2@%*q*lo2$iXx+?1{Z`(W)9(zN*z51y|+PqP_6}7TvIDx_VR; zNko073#*oRDl8=nM?2zuwd4-!=R|3n3OIY-yFmyTSbZJ|V0a1ph&^06h3F z4xT4qWYOMK!R-G+ViyF3rCg&FrweBeFVIrFmQ;yFE};8NHwdMZr*j@*ss0MWFmWC*lIOW2DD@#EjW>%7ImolmiNh_6Coe+zhv zyJ9NNHIG%^YhIW6R8A8SWpxayc@)AxwXhx5^y><)gyrfe~)D^={( zWKk*zB|@H6mt<9iR2&8v49JMES;Hg7X_I8ZvSL1a3Qlu4tpuE=rR~vw3X{_qn0h>t zaf9>IAb{>Eb08*8U;O6#)l|}ng`A1o>Beq%xXXbP9R|qW`+hR6<6cc z;DiS2_ip<0lfDO7BDXWV31Tb1UPKJUmh4XVrpACkP?cL(yjkG9>91F~z8wc&eI<+~ z_L&;?j&|>)8%u@T!LJIbe=2DewFW6%`}=#q@DO=?aXT`&NV8pW&!Zbi(37+CV11pc zETMwYf_UF|vlX^@cSJT7vRR>Z+rTIp5U_|#6Z?V8gLRI+)YbB?MRwHj3{QTP3pc^Q z%BR<%q7~_&;e)nT|Iq`C&#v-Kud5hdUDXc(qS#%VT7%Lz0L`;F+u&$EYIdYy|CUhT z`)m9J3!JRlm0&f=rI_aWa<3ps|BHdUTtbMgVs0q7XVNf7$3~oDF9J9+p zLr)5nGTm7NSFyP*R2c(%9eVF}8%5&Hu6_Kjzx^e#Q|#-vn!&gz&!cWT+1U`0rZjI? zy9&9jB<6s~x@zPd*L`#!3&K=PoKM3*;!H-g;|=LmMnSBO=TS(UH$drPA$>M|(TH9c zVJvv7`JU&KBITSHOjPjMu`SsuEB`aAr(x2@{hqaphKm%@IHx~R=F*h4 zdRoyQ`E%{tMBI@nTT_7*Ym@8{6VgkOrfw*q#!{FtMoM8*bDbk4t|q+O+eZH6{(b&P#GuV(x5Z=t*t_zdOlJ(baU&btqmu%AOp=) z@_A_pxVkh>5)^QC!)B;a1z2(g?gb&e{ZBA>YB6R!v3K>%+l0D#lgK#@~_6&+V27qll7S)!wz9E{EcqfnT-ByO$pd!_8OAzlUsZ zPUD~=^OhV%M`;jQx}&t9v>=jB0^K+XbYsYi99v}1V~pa-&(=c)JuKUk4Mw3@U+(Wc z$R?;`haYz(Jsw7zoxeH2ay%>jt7zUV21wv^b49hdabnIUOP&nl3+E{KWEdqyJ`y7l zvJ@+KADsxmFmD-aGBHCn(4su*7@4qclq1x`X2EIWwA3kq(?&b2gn-k=X{k{Hr%hgA z{%Gw_Umv^n+#w?K6HBr(S5jD`LUF|^55!;;g+D(iwK^8!4{R&Sm>{eAa z5Fi=&eGL_IY>BLRY#>0R_Bz@osbmaV6uEfZo-NQpaYGj#uTLK@pJ7IfKP9}|A#i1% zQYH*Q&*Xs4@P1SB4hrs57Y%!_Opt;p#J=lGVJgQ1xnTyPZg-ds9K7h4OBGN!+;+R! zGzSD$Yb@z98)Cw`wrYaA%7`r|vou1$meE+`R6_c9?QvFaZm06vna*U9`+}sKa+O!7 z$)1BBIvO`&R+uS;XU&9aVCOdneS~1=XUzm^VCTE##xHHed1|glyAYQ)Xja~OD;VxE zM=7wWtiIr9QDb3pS(a=)0gSIuD#PFJQSI;2Bq%5!HqQ^};>8cur&vdqo)Cx>F!MoLk?mzuE7wJsKM@MvI^)hUYCgD^e^uudgn}o-uIHIyw%?fxV{ZI zx@6HzTggv8mU>G6eCWLnx1oZ4~Dq6eAez#kGmU)hEF7rFDl&0{BsTOeNfSOh~X~w2$zi>A1QIJwR|Eb|s>QXyxc?8~p(Wegm`(g@monY%a@z*^Im6Jmx51mSAWI${9+ zSe#EO*K)fCiOmwwlXs13rmSIou4vSV; ziS{rphY1yPaZJU!MdqY^s>TKIb=dUl&?}VtQ`!!IuM@>aRu>_jj`*^nJTev!&vO~_ zhOPU<r`IM{tMDM^J9aaCzlaPwK4U9bdD7pOS`B6q8NO$6g*-ANF|yPt zNB7UrE%~2zUC!9Gc*VqZCbNom3n^#?F|GU;KFatU1}}n7|5pSl4=a;&zRqGuhVaMr z&tmZK7rI%$^7xh9TgJ{Xl_ehXNDb=gp7QVqdJ>h)F6~7o4l@IVyn?paP!yR0F>v`o zRip6Bm+|!gHE?=k5+?RB-WI{4Qmn2+igIv8B8P(!@VxnCc1Dh;(q^}J56jPHrPp6@ zL>FlwVEW(uhaMtr`o#v=eh{MfjGsBR!7a;=t`MsfaL7SCETfD1ive;S_cwP4o4$C} zLNMes8aG$Fy6iCJV)Z$;h|rc9_F?+&q49w70VJ!{B+B3O^Vkf_$;-N+b|tJd2rCrg z@hKJ@W8?xS(`P4sLLU_C-q~KxQ46DbJbjw1WhWAcK@tYX9g%|aXFyvL0c}xKrBRC~=5e#SFtpc+ zAa1=KP3k5CW~>6%kPpY^Rlf(uXYD zs*7aI!EEmDf7NJC)85*#h~wp zj$ivX5iqxtjhWMMk0q*Gh1<9m-Jf>oda5H>(psqV^V_+qB(mrKvH?E~9({~~9vKZw zS4QhYq#CW@h5$aBiKxb`f?>2uV zd33-9+lP!MOxT}&6OS>ac@;VpxvtCfE>rRg7k7fX)ms}^jMhJuiM;gI*y2SWarLlK{B#_24ibXOSkAo6H+(=k#Wk@Z9OS85X9o&|WyEar%l9>tA63 zQIx9rvh4=RK#DeklRld;Sugnx)O5@7l9$b(i-e}`;8Kd5N6Yuh7x@u|!eVkIKd8Az z1cU;D^buT> z`(<*z0kj=?bY*!k|C=nL$C|TE{~t7-+WG3*<;DH;Z_~~_W^ZbmDqfJ21;h;m9|6|N zr5msQ(cQ+u!O!pf-E~E!zegC;9@x(PD zn333$JZscY|8sV7A4BEXUncC{d}7^tc*4*MV0#)-KQ+q0{IwXK{O63mo3849!T`W>TDUl)V z8B_KKJgHKEp^T;-0IlI>$Lm{KFFB?E((Ws8#;olQ-T@zGG}rJaIc{r2ec`RWu<9Ts zLAj>5Izj!Jn0wSjQV+ukCL;;wFEfd|b-J)R?I$#1IzpXgJ%FVt%C?Yu6ioj!v$OI3 znb{@sfWzAIq~gJ2)!T9ML9#wZ zfj2+*)jq--K2~y#OcC<;!jXpGXn?s%fb5JeGYVS-=4KFix%a4apRm&H>jpdOf}w?R zo~skApyWYnF_Z0$abwWz5g3SO*iV&);t9p2@-W7R%F2EDY_jVC4Dxi&JP;1@BP%;_ zgFGEOPaYWLmEw8Uk8+L6i+_bj9w)kVnLINk%eY?0n^<{ly4J?;JfjIbEm=gL<;aPr zc3Jv(6z~lvbc-nF!WAP8j}`ja{gWq1C7lIM8ZixV1YMrk_@((>fJ+kiA`udTP{&1G zb1oJ)y*b?k7ijrF=BJe;wX=9?yp)&xZ~yt(g7?%Vsgmxi&SAOIh3*vFNH34PO*EVB zX2YVPfBqRU2KD-q?)g3lvnJ%U&9!U6YNh8AN>m?qF54cw-+b$l?#bpJ4(6>5;)+^I z>Y4frYnLxBc}R7K#?Ng{X1oL3#3pzeWR{(p!yAxUx!kY5!86Oa^ACbkbE3qL0-X6W z)A!a^Z=CScb&mRDt7Dcg@?d>#X}$HX!E|>Dj$_UNCkg9 zi<=+uy!53&W8zi*%~?2k3UWe7KNp@8@7s2gm?q?12FKT#$m{J6-mVflzU-`=z5dhr z>h)`GyqMPq0`>aGISz`MpXQR(TH~qT(a;6>`5m<_WGqC`oi5Xse35W>cvEyUcp`v< zW>)MX)AliB>NlGLZE#CY*t!i^a=hX~hgSwa7n|YlXpc%y%XKKH zhpXBh&6|ovL-RL%@D!c7$h8Z zs+li)`nT~Cd~`ux<|oH}0@Bg_$D`ZEQ52?@k8c>xo&hpHmiGAXxsL)%>nk4Lg@XR& z*!*KB%Zu)>{oF2#UpAq-sRX~BhVbv$AOswm3Rq9uA69e7650b_C-ntN2mI!R^4|I1 zRO&xmJib_!{3NU;L&dBzgn@{s#F2Gwh|vJBea-Vz9Ee5N#aB#wTx4spT1X|>uN6Ru zztE$4dxf;cXR`oYDz+TN!KEVad!AId#A|ibM;2>5%=!7}@SGMn z=NDwm4q_?L<22GqmLw=v)8CQJE}?e6%dXc}lHEwG4nx90hIS#cs!FI>1%iMxnN(%N zITMesJzO`M@D#xpZQ3h>*p2U8-$NFj68wVcc^YCd!xZQ_RwsdsL>0;FN5$E-`T<#l zhBQX}{jL9DlE%_Kl}G;%z+$D0HVLi4bmU+tU-5_mZ5PXn`S`-A{OM4&+;!s#EDp8j zMTriKsFWUb8P84==mcmO{DL=jq{Uk=yc_m@$B3|2r=;1*B_gduw?8rXlc99Y$NYXm z57U4EwCB)|hNFFI8>1G2qC(!ID=A%PCcCvFka&=WpQb+-77dTQjLcm49B}Q9!g|{7 zg{h50-+ZL8Om9(Um{P=gIw*}AUegD)bwWI4I>GV}a-u+!e+k~a0U7@#EId;D&+n-^ zVFkc~3Q%z%phU^T@2|3D>lvCvTV=2kiQRA(B&51Nh$9N3m2Y{@!H&;!Pb<}Mg(Ogy z4@urPe>uWO{?1U{7XzjQF3h1>0PeVdIfzR{B4pC4eH{A3*z}C!;Oy0N{G{>b1*sJ-ijx1pq?P7Z-s6^h4 z{&rl_HrdYqFLEu}y;tXLT(&{ppH|@5Koh~d2WxLrcKkdT_)x^rXO@k<#w6_Bwl|C+ zmkwgEI+c%tSgVd^w74{|Vr@J;G{@NEDQyLM=86Tf;@2@6a4s%0o@{u3o&A$L@>6lv zF^6-}Qsg!A2l8JGXTmNl)fR z3r3N$=q}Hw7mesgf$Jan)o%*AGXaWNs6$yWmQpmxL<5AO!=pnPH+(tiHq6<370V-dSb-L_!ZM+A-?jpu# z|A2889C3>`yJ|zZedv64<3GSOL$;0cA%h2cA>lWr-E0S1u(S-@Bv|_CiLSfHQ+7K6VeOswnPHjZDMX{srB@!B@5lx^TKs(uS(Zuq&ofui)e}y-NWM3!l!n>d z)G@&u8F}iMS#(!tR|`)Vz|pUvrxFC^Av4*4|Lo2&gGkJvI@bjt-u+?aC)9*I>D6o} z{2miqL>DA}8^SXGmabr7lTj323x5T(7v5W8U6V2E*{dwm@=erzBT2L&fbrW_MvP9> zA@ZWX8@$s%^QnEOJT^UMj&*wXY`)|Jr%G7!F47`O@*uO$W3#Yn(4QH#2oY(f(VQ1l znp@{y)dDw4n4wwK)z2$J#zu!)lfWR+M0TY}Hy9-HAap?iMLw8!-#CUWV~sQ`Ll-A~*M{exh$q$G+CEE5I2XL8_)hi8|fze+SXLr6a=L@F7K zLORH-5U@Q}ua9@ss@Pzz^GDCOxm-uH1F;G{VztL*ERDuH-9WT#_G0JQ7n1h3cdIXBRgi`2F^ zd`T@C#NoE5;lA#Qc@CTT`E$RrG2HZMy?@i&(_ev`4B2g$z+?y(BU_9R zPet_b`qrU-ur{7QqiDs{esoY;_f!%I^bU^02iD>wBIx|aHM~@7nGo8Q)@@P!lVxj} zqR$typ3JMKX&h*P(J0;jb<)Zb=Vd>;GkBNEQ)u)>)3E5?PuVrN&qP&@2&)Z$T{C8C z#Xn@P*AYjG`VQ%|{5uz5>R+ z1J%;{{z=bU6fn$6QpJ&09mC9Cq(_8yIVOvW@(&$!5#z1%z$q2~Grs6o3W~+`=XU|qA75kRa82ZDXMRzGajOgGh9B$KE4?%G%L`OsUgN0n z|A*$mAfJRjr$1jH3gSD$0wx)zH7MLN?QQB5LM_hMot|Ok6nr5R&`o3Vn@N4hgp4@0 zjodF6Qx}lwW{*$qfWRy*lv5*Wh@H)7j<199G5ZSlRl?|RT^f(#>t7_c& zYK*QZlUWKURS(@3<0tO6X`SYC-`b|oy z_B7C9Yt;hSf3?>y?7hf!oHo0&_#FAMri$#>%n9A75LqV>{YX!X9ti5+Gidi4G8phs_GN)Lv!52A5;oPz00{hkz@3O-Kp*s!j8xgeDR`BTO=Z7~Cp0XVZlmIwC_zWi6+odk;&|I43zTK3rHCp7Ba-Hq5`}H^0w^czF8}>b%22@ zVA>`S3?m3D7>>Y)P9l@JPY@F=#6T|m&LzPsqNg#+z z7pcw;jiJy$rH*&(LJ;7GcRofU*{QK?@!KOi2aW9SE75X2oW>#%T*JDe~n;&-6SuC+CM z3aUYA-KC`5>RXhX+eK+m1zdK@gujdMpH@qI0jp+D&Ay|1Bth-w(AjAbyuNu%DAMTbBd|#bB{oeH z%Ea8pGh@T9uo(;*)-c0G>Vn>FjDqx98FI`0R9Yy;S?uJX2GZXIZb(?qL^G*v zN74p>W~sG3aswsBY6Lb|5O3Q_%IU6tgEJ>#R$c#P*=S(-cpSX2>W`|dk{w5ILq;Tw z=kmCAyzMgVyWMrvE_%1l1J>VG!hpplR;fgX1e5KYwP`p2Z)P~1(*uZc>yecujNsL*Z&G7Yl)hsL@TGVAzP+sj}4JMOQGU#xViu0E}=UMC4Y$`%DbbTJ5>Lfja za-SXViOGV?3LSE1`40q<&4L;wL*i2cLmsZU$@%Y{EZY(iF1d6*|30u)LufUV^B44> zBJ6Yje9dc_T-oz7>REXaXjyqk_xf^{_I7Au{2{w@cl1|hV4@v4Q&a~;mc|-uL&AkN z;Jm!hI8gN6h9aqoiCMf&n276?@9zxD8XNt<4HL~SCFU$@S%Hwyds5}@Xa(iesCjdp@n!NI=R++O96qfhGv?Oy}I3f4nn-M z@;}=I!sgRL$7l+lZ()sQn0n_CS+4x;f3L5W)wbxiuV&lO=Ui$>IM+uwWz?*E68Riis?y9O}u}hnO26suA`uIX;zSb%_is)use98zSzGKC2co9p4!X*8VMq z^S{M5SO6I)(5w+Y+c}Sxjqc*gU2PwE4R^0aigDB;xb@@{joHf zkTl1T?&>9@g{GCig2SC(5@UFub_*RuOMJMoD^_|_MnFEs6DoHN(2m@6hz_7#?8ONb zWfR{YWs6HXh(D(P4?1wN+YJI;wwDFJGPWWf9@ptSV~o0i6m*?(5E|fzqpEiz@j(Bu zU>f!!qZ0AX_{zcc5of^}q&Zm{fJ4>6rvwb{b=hY3H9v*^ade*A!I>3LO4fw5`WcC1 zAyNyLzu<+*cLQ+~*KY>2Z)hRkMg4er97NES?PyIeqzP|8ov_*(z65omrtVS-um+1Q zxl6zrI?LRaFT{w4gSv(fkK}{|SvyA#$>XCiN-V3DkxQF5!wQU&jekt>EMs z(qBEn?o2kIhpa@}B9R6NN`AV7AeJzlyH9H3XPiX-et(gq@c>*OF8vcw8PU?)z&~Fj z2W@rVN5(GWn^?`>YD%}U^3=@nx=iaeBJ$dsp|{VD`ScN1GxdL~lI-2TT9MfJ*)hWq z+J{3Q6Z|RZZ9x??0NDeQFUCxydth8dhO{TxAA1ns*C4%Fg~4nmuEu8Zoa=lLk*)PY?3zJi(O924uru zudKx2ZDT&_USRA--xl^-^9X{=Id^aW}jAvqkvd46CGI_lyQB(BSP7%AjE7ErZw z!kT<%>xp%2o}fKqJCTMAC`hgSQ4mP2D`}5{An>3yb45WFUg*nhYf%}{Ko0Kp$5P+7 zp4)F%M|kL;ufOee)lPTm5N!?c_1nTbJ@HW;VnW+fI_Q(W*9qke-n=Ph2Ko-?!{pyc zQ!!eQW=O^@dKw@-;I#Ot%qQ{b1R|f(^K$U!6Fd1-)C^oXW@%hUnsUGs*zRH&%B3Z}iWti; zs3+};30s&I@2c?2zy5Do{PNiQOXukK$4Hh3D9(Mt&&F~N(aFakRCV&ueg8?85X~y1 zKcS^PwHl8gqWSf2;67$%+XKLQM1HaxxUjGyytl5F(2!yX6$%i1?n7tP2|A&@pc5L7 zy!&gVJlD+ChLV&o7@OxR3FS-*0)8+nTt~u&!F_o)Yr*S5%RyR#!PixEP)p6=$!B`7Y1fM<$~bd~3?9OuZ5u4;E$fPjx>P!2PDktcvr@MD$aHCbui@oc zM6cRgayzf;gz-CqJ9GynzN9M#OiIhV3(1uZkCIm2hs!x!f^JG2diBW=+L;sG%}<0Z zf=}@hF-(E8$gZCM%tDr-LRo>~0h1AH#!y%TBf&zoKs-HL4otB@Z*Nu*mv;3Aa93b@ zO>3OoozEF#m>nYTyXxs^+FgkPYr2qFJ=fZdA`c?nlXeDdDAgIiDEwm>Ebwr%b%}yE zBhHnl+%2O(z~%QDF{Yp|-L$_e(tTMQ=yHED+JCb;+J#2Z9e$ZlW1McL%=lN1@acDH z+gB}ix(&Z>Z0wDZ7B~(QQHKLK9}(2$QpH&772 z0w={GI13uwu&FO?T{XH#ggv(tczkM5<|I)@OiJ}UcYafCdoV5+GRr}egwjH1bD3_- zs;oC<4%%{G!;+Pe`VgqTRzF?``^eQoDoD!Mq{UzN0;jb;?)4`GuiPVw{DXKj4{=5Vvm_*mr* z0V=&W`41k{&o6+i9U*#I)tnE+B=T}Fy`{1;3*GrE5OX|UzcH+Jrp){i8lp5*avves;@XJz#IBoUX_^H$ zDls8s>$b2RZx9UNhq8D|5$ad{4+i#=5ay7Bx8yFAV{P$GJfnH&bm1X!lE|_H72_>QSkA=Qs~Sd2M^DO>^a}7kMq^Pw2)R}y?MjarJ+y$ifKK? zleR}YbNxZ)5YE*{)kyFbc?*emc&LYyWSB}lo-e)ouOD_lK)-%~e*6Iag84x|q961l zV!>-c@=kp7%Re^bN+zllp2uKheDb_neeQ@#_n?ijnlewru`;oBdi&F& z(~sGvk|s4&E8vMI7(`Z_Oxpk~ioxN?2b6lbN!TV}Q9%}!o3$On^Z&=#SI1S=bqxwg zN?t%3q`N~zLO^K&k?!ugv^3J)jUduoQo6fSkOt`n>8?3fpI6^!W_~l@9|!K*Yp>jE zuXFY}I|N#`tE#J?k~xffq1*^9HJJjB6}!<=nvpp5q&qM7w~AB6OK(3gcr4xbq#Sds zeLjj7TblsEGj2$*N-!t_QyPti?Wn|(6IwBX$Sg@rupgkU9&nmi#7Vw3r2|G zg1HXM^1i9~r<_MIQjeo5jVY5@tx15h0N{YhhOk7Mv{X4y{6Fh1QP(p;2cKogBvCl( zusmgIFP{N}PhC->wnx*N63>9i$z|oB-XdQ^i%PG|IqQ8HZ8l^zZkixr4CH2DZ(1rs z3H6%mo|+z3esOQU9E2E=2Fjt{9Wpvq*ql-Um*~Qq1@vO@Be#=f zEt8|7ucrbE!3WXp;hHpDY^+{+TmlMow%OMyyaO_$c@-TBncF~@l`4?|x-76PXPgo~ z7x7h}|5h|%C~2*qh*`r#3#JjU6~D*yzGeQ0Z&_G2&aJ86e$E(~IcI|!DBn=7hmMqV zlnzWT-5oKW4jslhiKFaC97AG81Mn^n``pVFO@WE7QmKp$zynd%(2t+MC(={nt@fY4 zh8Ir$k-ly62g5z~?7)mb@#Npp5O=|oYfJpFAB)J^q;nKQCM0nJs@8r0@kX zOLxi0fuLJ4ANaNwlFE1nFzy)AzLPN8f!+bFyLS*-*mq}=+{8tuAYI1xk`WNT5c2#PpEc)v^tBzBf#W5AgS2fZ zi&ON98lqzKD;(~BhlAJo4aJlMYghKM_@ zd7Fc?XTVy)ZUQ?2_pk5Z0cV?Zmq14!YLK~oG$&et>;1cL8+=!1ZS4}V%r+N31 zqgJ*DuSQC?FqqXApD=+P=E)A>8yP+#Fk3cAiRKiT#}7XcKLzw@AEN{4D@IrExwV(K2u)t{!Ta&qq9#-K3Uf^520D*M z(63NzLuvv@&zEH?+#Hp!5f=hbfltR61}ea(<1>BBaGK-B9naF{tlS5r2<8r=a(5IZ zuUzEU6S=4d+6)geJvBcCYCS^{`^Of0sqV!Po~tGE2X>Em*ty?1wolRDg`=7i2ur!q zzbbQ=%`tra0{a@s-oUb{MX1QH7tcACY;X*%Ub{RpXbihU)6^FfDjGjQX!5LraVRZy zU6})>bB(xI+Hdr3^ZO}~fb0*vOFgouhE7bloOwb5+&f8aSp3j| z&#L!33AL7Oxptng+Vj#k{2Q=~8e~dH2zrjkp5us;%HcQh^ZT6J zv&iA$i{N7&_}CF4=DLs=aw);!7%VA4EFVME$cPwZem<$(!!33R256q-YwX2J$cZC@IHCamRn)E^#w}$fD(OZiJ@G(<>Loq zxyNNg?P%n~E4i2^U<3Tm35@MS0EB>L0*=N1e9qV&PBFY<3_ufQ$+1ds{%3Bl)XrtY^?gEY0_ooe$E2>Aliwv53QwaEY^8vun~ z0??;_Lw++jHL>L8BMKY-SjNdJVo6>5hDeLRCRG1j75v}Oz`t<+9|*bPg*7es=`Rs> z^Rg>UzacF1k^d{CSKYdA=r>ydTNBG0IwzTCBv|s!O_?oYifzDMw*w%iyc7rn%DeWd zhF6?8+I41YGY#8obAYQLY$>rka!!gSj7XX$Ok)7alkBFp4nQ;kS6kRpO--bR3~~1- zYB>(Qd1JABt0%UBeGJ&$#WdL6L&jk#HIJNAivW}@aM^X|`#-VWgrcoz(O1#qX!WP* zgB#?Pli92VflJ8X`!IYhrBOWc>eD!6&ZfBhf+w~*{S4T~*9>6%nlJ2@ySB~%*j-Eq zT&7`e%wWcTzuy;OM>V>0AyiTb^y)4v?zm%s@P@rqP6rgl4cF5MY*2;@dIP<%rze+x z#47;?y#uaqkEEx%aB0qnTiC|}j$8UYGGueZ7yfo@vLV0`BW{yso&C@1H}KRV|EI(x7} zWB^N{7d@cF#cw45UnS8h06LQ<{m~f*kc({$)%lkoe=CxofogvwLCw|w$6QWtbie?j zihjRjVFzNsaVP*t4uHQsm$LHBVLqhYHt5Fim#f|`Z$1AR`-j!g(j(q~fi5rp0lW0( zX-{4wtdq~v{$-X~&C=Q8_GbC}sMzWlq zOiNSpM1pgLKi2p=P}qASSUC?q7-UE^e(Xv!M0YCaumDCJ0zfVR3_2Awzo9UW!AdkX z1i&o-yr(d(2EaG~lsFSKhoLl{1;9=K%m={7l*ad1vBtU2z-D4)7w=x;vtvisa#7B3 zn&pQ3p9D}?i-2N{XH{v2-b#Jke>QG`&1U~GsfC)8G3ZKz!)(JQ*yM&y;JIcB6#8j{ zJjalG5+H5wC7rf$pHNn;e{ECC^}G)?H<>i;(eOiX5(_cQ5I<`&*GZ#ag*QbmUZ6DR zh%^mQw5<6#XuEfLZ15yT5-8%Oq|?8)s|D&A0!5(VCm~5c|BKX@B3Jw$(#mq%2>DKj z9X7LE6`;t9DUBY7{fQ??h8m*z8r zwwIR2<{h-t04sTY0jVyv02#+G^MfdIQ-AS{ADD zdBk0sEf~Lj&Ybedq{9AAP$or#7bXuNmE{kq`!CY@tfb$hzxc`u{R@ej{V${l6q&Yh z?U4la$_EKRRtKQXZ?A;l{F3sI%Vs3lYlzXHDx_^BWcy&p=v%)d{G)GLc9KR)0MwbW z8wq(n`_CF)p~>1ye_w*~O_pS@k@-amt#50mFvzU@S4;+uz4Ro|P{6LnfVp{eUGweS zyhF@d&>ByN6+-IPEuh-{az1vvzA+XN%YVG2nUkc}9{_D%So3$K= zb70o?Kb&cqy9QTyeuqE}CcY(NGPQLrR}DVCto?vbn^Tn977(M-AD5vT&q%XZ%%dg# zig7?=*!P1>u7Ey9K;Qz{7c%S>r+=}80M`4j)ILD!5>#rJnK6CZBU$5+?qsUt7Kf#6tTd z5EjtR0?(kAF!sm1;g3>D6An=GR=6tCWgpRsP!E3m+ehoQL#}B4OKJ{~mIKYl?F6)U5--s5O3+`Qd1axU|5-fSll?!OHYKPB z)&I!_YF4z~` zcc0y`{U<$bN*n!2@j%M?gX}UZSwtL8?Elx@p&(2xF!@in(qS-2(BJrTCrRv2nn5l~VU1_s1%l;|!~g%J*~!0!0kQKxVhp5P4C@ zV}LyGlz%hPPE@uLTngc0y)JpmsI{5;9N*)o~(@(fB- zpWXxo7zlTi>uED&E+TUMBKY-NoQwDgVFcQV0`i^Umu1yaTg#+Gsb69O9K>2ixCW(- z{);wi@lSn%zxDh7ORdQtw1Zqm`yQ_>64;B?#7g>SZ@ed&4Ad*aG~=r-V2ahcD~$>2 z7%UFp2wM_Adl|o|Te&-4{%$#^G;Vd#%mPB6X2Jw!{}4d*dCNNIqCJ+QG`voKk|3l>9qLv2cdO$kC+fgF__v+N=4ZXJSR z?(G+E+%s-|*n1dnm^bGM2*=eu)@V&*^A51}pJvgneANq?LeaH$%2i%FEDz+Gs(yuT zihtb;OWo5Il=+e>8{ZYxw0Zy*gJtpIf#r?TlXgN9>sK*;QJvIvB< z{4nA%U}1IJUJ$8-r1oG4_Y>YU#5Ym2Avgp9M;E}addyBcAiEpY$RzLs%n$IjzDSIU=# z5a)9iya67z2<;vn^fh(4%9kkT*HO3`>R%QxX&1X72`*&83)SuH$;v|aj@;s&TTu{4 zf{E4Dp_T>aZ*wY3@6ED*G+SEtuoBwcK?pO3mGM}GLKa7GESE)CS3eDJH(-1@(kvpS zKO{2S-ja9U?HYosJ63E<5#u@U&{!WY&H!hx4ZYjkJ?=5VO%Tj=ub|b?sw-!XR1D`4 zFP-rq%5aF0vnSJ<`f4R}al*Q(Ho*}#N#C=Az1{|M8M3%E6VAznE;iucT6|dEQ zne5Ew=dsVyNOgu7|Ni+aOEx@@?Jx-?%2?xbvVX^m&=Ul?D&R0*Iv{4A0RMIDj4bV0 zS)hNzM_!`0vtd3Sg{aQOqS3kgt&EP2Qn2WzIfAH<)T^&Pg@2?3!)wBR`AodO7rXJn zD=u}HH;D6Uv^<_|$PUwxd+L)FRoa*2BHj1#ZiI?5;iFD0L8tn@emr6|VyN{w@BG6^ zW*pe}#BtxBqVeUpO<)cmyZhWPc+0&fwvM>Rnn{u!PdGE9BJyh0LBm8`Ckg=_@-6v$ zcp3hz$o@Dz0XiR06Yj@xW#`V7KO=suOzpW>to?86jJv)@vjLW|0lk6n_mRcF4TK(C ztZ!pu0qqXIj2#+plkIqhk9ep;K2PEgYc*7_)#&oc4Ms|6*4WC-d;8py)SXI4IIX*~ z+c%NA;nk(Lm**=NFAohHInl`UwyWU?>RiZUO8lzghI0BN_M`@4o9DYErwpCA&HFTw zD+%8cYti)TX*+kHBCM-8ePkcT-$lS(8Ra%qxc*G|j7gFTe1h6I`1Bx;(x`-bWeHGF|d>K{tUnFO37QVDj&1Y&FEpD{1m$L#4n zsvL5qT&N2vAUo_5-VWhMKred?lI=qGlkWJ#bdb6u7}a)TO}A)qQO7ZwAEI;@)v*l z;Cb@D9ZWuhNsc|^07Q=s$|K7E<7nvLF8_5v^soH$%i(KHTK1HE(YbD3p8hfh6`TfE zk5+E7oZXDZ%#Gh#Z1#44x1Zc7VUCuFQA0D-=fpOA*WyVTt&7_SE8*1Sjo2$=11!RuaQ zyn^gOxj2;EUBgSo=4R2qW$IKYp!DJNra^D|zE<^gU8{=z`a?r;%3yWs_?)3Xuk1Y^7F#}?AKb5kH9Xb|_J`hTDSKHDEaaL8P-5tycG+p&-8(N$+_iEo<4sLl^&`}n;ySEuo>PuEthYTvj#{e}$DW!>8&fYidrs&^2 zOb(UaUYKa^X}KuWpv&FWFCCS8xcmg(2sak&+Wk0PZ=7SUcD7P0nhi8wcnaxqs?nTU zKg~YW&BS}y^|}SlujXbxVNE?`^}4J%Y^lDXzRgUwQF;DQhSqR|?R72upwocDbGy5l zN%+tm$b|PgVR1iXq`}-%g*kAcQGI{IsDh4$GFb>wY}res8EHS%|)CCL`@G z_NwBVOzM7nx9t@|VBB!_it|Fdw zjOTNtR=d=JhBho~u+Ahoo61cfNkSQ~J6c&QtqqLH%r!xtl+c%#gn3fWyWg@v&Rogh zx^_4$<0K?^gFjSB60igS+87?EJClL_uR5=Y*HxbQ5Nb&Eq@llz;T@fQkK}di>hX5&ooUBXZn(VoZxx0-Pgm@wSWIXYeMCX z$`5k9rVxe;-Y+i$!lEfxQl&J0Vn*%HY>|XesJyT|uBOjLB;O6svbW7FMt``Eo~oA8 z*eCn<+UST?(t; z!Vmyks1TNIh;N(|l|nw7EUVe)T|(`^qYx1B%!s%SQhXF6L?St6`$KX+`wcn?pOqwB z{pZmc3BmvdjjN51SJlnTwiujXDm1;E4F$#k_kNk#m;g~0Y8jrG0P;AlblMQDDuEG! zir{Rpi$RXvsM=t5G1w*hV91aXj9)0To{G;S74-J(!xSYXub-Rct7~fYY?}au^R(p} zx^#S@!@fcJ&$%c(^vIjHXkJ-$9^h~DXUwO;;VS)^RpW%w#a6ShLEa2`mOQXQIT9M_ z)@_qki#)i6({mD1h}dJ`BEkM#W(On*rOFvPk_d|TAM6SXcLewCnGD;&+2Q4?V{Xi- zc9*sVQba*RfKd?~XfK#Y7nOFevCKOiqGuJ;oCBV$MmzN86k9#pWJwIKTt=Ex49T6r z-L>9x_T17*s|~SkU?F_Gvr2*Mpo%@LIY_acDW|dgDn>LTym^`aB!1Pw=WRnt|3dwi zael=WFACz6jFb_o9receQ{Jc>r;PB%<SJ_T zARvi`bMPWG%a?95E)jHNnZxYs4TLvlJAu*1V|Y1UqX5cEgDLkJZ5)-}l_2sP9vN~H z2c1sryd)83dw$9YdV=0l0arwfnM7{Fj*;$nud}}`<65zMNo!#FxHf+fb9v9vyxnkb z9RD?4IPa5$_xpW!)!Lq0W-Ic?E2xL=NO@^E;ApCoK5eyv2yk5?F;G&2i9=Q z1JaxNF8E#vruWo-Do@8Bg94NFo8vKt;$oL&B3l>Ho0Ylub6Lvg*+G2{`mJgZb{%OA z)OYfjBY{T!eY&{^8{uQ7eK>I^;wve314&#ch3p%__HWUs;Md`J)(s8EYox#C?p7-` zk)6Ec7kR4H)0$|n9#?Jq<#TTa25fvRoBU$Q8`3xZ_4CDnS}H{t>(PM+eoUcL)*W?N z=rLZP%^Y*Oi^0Ieeo5~FvSER`Te;pO2~PbYPFO|>K#(GLHe?M>VV#O<;&56nBk|4Y;RpY0ZcHBF0Il6bWL#CY^?cHpf@)Q-2F?@zys0MdjELuOU zqHDO%wg>yedI)}2k`+-Wc}vpbI{&TKcFCzLS|UtAN{X&PDy_=AOhrcU8VT9Tk-zk< zkiF-4)sTGT@rM&wDZ7$fD_I0xj~pomR$nFZgo>-SuYB-@tuZ*N;|9J{)Gl=-Th>D|+gNyq=XO|3yv5Flp7LiY$Et z!rYB8L6#7ke(X5R9Y7c4XG`+pL6!l5IwP1ytu)+LKTAG3)i|dY=(S5D)t$kxP5VhdNYD_J{V)&|nSKvdwt< z2}*PCOAmD1W(le7BQ%o$9_+n&x-! zI=wMuuHmIY9)?=E9PLtilR(<{m}@MNR@VIt(}tXEgOS#!IRdf9&MkZJiTZ~k5cWpX z*>scQj;abw@YgGEEqLT{T`3sANF0!D+9)|n1Vb5Dl9c1^Ivo=RzU z{GbSd^2(k{s3|1{**WByK})(N=8}lF5Bb;@QQixOVk*#PlN}RYAL1oLuXpJITtd}z zS&AGa3J{Dk(RQ(SVf^cr+bMcFua>i`AR5C*(?&Xe3ww)!t>$K3RGVHc@1ikjWGc$N zAD=W?BG7#<%Ko6gz7%Zwsq990l?9-0ILASSE*lRcC zIH4NSSQ??(KG917B66Zyp@(VLd$VGziaykjbv3F7Pe9^yyMyc#qgJHu18_~5=!$Ez zuEXAJmYttHs1YP<^TWAyogd&0%=HbC@KX`&<}@fL<^{Jh2J)G{5%g0L7I6{S0Jff} zy^vg+S`@tc47;jHwcjbtOcg6H70-JdFZzf&8skJMicM!R)Ir{=E~wMfQC5uwcf;81 z3C(+=y$g+uNPRo_!>Q&4H0O$y+$S#=_=hm@-Rku;qk{ZA<2A#}(NV^NV|Czj)7E@F zaSgYo#`}Z)pLJ1yu9VmW&l5yM4PLJ-si31VVO>S(z!O}Zr9L_Mq7`6ITzSqL6I>-F zjnPK?W~EmJMla`$;Gl|dySv8$tnP8#K@IsB9WjeQH!EH+r*>ONpZl}YkEqAj+LFQY z%8c+sJGjxNC2kCom!rC@p`G9o*j@X9z)c1TmlB(i4YnwA;?UXtZQxvb_GWIU*k zCmlSlR_DzJI%%swQQ+T|=YpheH=fUrTz8euc?N6g#b&CpT8ghEDf`6FuXmW?#-&Z( zS)V(fd@XHo(%yUeT*Gu5{2kK(pXcfw)vyUJCXD(ToGC7q_oTD=S0-g)ywLAExGDj9 z!8R+|%E7_6S5fNJ$OVo-(;i{2LDlc>?`(q*9&>X1+}Y+6>dKU4jtR?i&HkLAv7U*|LGb)c!4|F8rOt_k)bOU5(eW^un>E5Oucyc)9Pw_XB4 zeC$uz_o%oOg{$b@Y}hB=(G~jGIO$f~XR8IEgiB9xF*^_6#Rco?hO!OM3@7DXTT4{o zQkEM|Qq(@Wl2RfL@%sYb{zEE)<}-yZg{Y&ed@ic8DHZ*#OEg4U%YY+EO(bh#2j|x! zb^=cG??o(-cF6m9i}CEZ>DFR>v{xGl2`0`QzTXf|iws}M`%R4Syuo(D64;N{)6`M1 zr_16E%)gEaTXZFV@QtW9d_2u~C=?R6;rml%sPOAP*-hpwF~?|W;S(IhzE`EC#NW)8 zi#yj`IKp;wmL3DT^s*R!pBhhhd9SiNQM5N}CA3@E%us)f&K?~0^ICo1VbCt;^QCyV zW0O2L(&;ccTt~O_OAeGhA{Fl;^C^r47XqQHANbeRS`D-Dq8KwzCC$rO+&|*y@3zDG2(;nGlJ z)gdVA?B*apowycd%eD#{=k3ER!wUhA4v`XwoTH?L%Nu-H*2h?$vk`H!bpC@0G(Q+A8W}+yR{cp&OSRc^ zd5{!Bf(P!I$l!Yg_Wa6dRC+gp3tt2R2@bk_+*&dvS8P}fy!-QI6EAvO0Nt|m8j2WxL+@nvoy+PF~OQDJdBh5kA-(R_HO%(Lj zR+bXY;$CzcNXu#HE{{HX^hT^U{HI9>s)<|55d&8zrLtktY@)Ssj)L~9_q(_R>E|Nf zfGxst2$s%K8ks!%`twT%(N&&A(U(gp#Z{z>j#uFlM4XHKL};?;b*VmD2uIa+n_akm z`wguE&rx4g=?C|IebbwtXgJ8l=Z~o+`8GdyhM+3DWez`nEv{f#Imc+*dig5B=q`sf z-`sjPw~#N)FT3|yb!mThWmK4OF>(lwp&K$XwiH*NORdV13l71sUdD5X)!ho!bM`3P zjUIp|&MQJ@42T$Si|;LxvRh)#{Wf!gf!nctEaK#!*ASGfZj+7)*$HJI841HB*; zS2cNznHlkrI3<;EEtlF#0%S+VI3AH#VY0lpF6;WwEpa(B)8P!4Ui~WQ=mpKTZg4TQMkgi#6@m94|fTu zKFXJ{RM*QnnPk9N2&6^NbDVxjLssthSa#0qb+KYMU(v<;Hx%Dpt*eez?<80J)UC;P zPlUfSaJ=5XLB~^IH+#V5pow7mf|jT(^1e=SMM9m0EpR{_FH?WabB!;8{m6l&r|}az zLO7pdv_$2{WC2q6o5wUI33P+k?%zQQIQzlYBsAn!j89z?7!UkEe(qrapE7NZO0tlh z7g6Yq2-c}76$ccOont^!^5`imX2Jp=IPz>Q^p#Rn2S@^qEekr$Dn#^H)7(3;fvsr8 z8Q;bcL$W{HzhnAQbgIp{pJ@@^`JqBY^epG`4@~E3K6+ zwP4)Z^^SBU#l0C;kC#T}YEEZ6)hU8SLJw%_9#knshUykD!naB*yfbF?6U?0D6_cI3h5G-v0%(*&|gXPEY1tL;=^^yl(pRi(`RAwyI5KIcmf4TVfnW z)VRG((GVrW>}ibCWeKw~u{(**X%8Qc=OP9yiPiiZZ@=AG@1FQ{GpL(d3i&M%JlJ^7 z4GUS}4U~9nLAvrh>-MntD=0)ew5P)=C$J84Vlk+c--+nktS{3ZWFQpt#W1utVvE?( zg-a1%p(HeHbhs-~4Ni@>8%#GICgMTr7fV8WI=b(d-#1-vM?RdGw6c%{!wvX@w1sQt z`M~H!h7#MKh6CXsrQUD@R9wuWJ*%x8fzf0RE5xcYms3~Xy4>_gPA#AA78>_ zys7h_l#LJ8)ZaIQP{5{ym7EB-n1fDtFV>R{aP;|%T4P(__AlK*1P<2k_g|i&&I4W^vgxET0ko{aqN5~qkagM5p7S>_4me@%_c8D7agn<;`m#qp4 z8Q6Hd6?kZN$xjG99^ZF*K?pYkD(HRfI>LV$EUn4!6Q#*VwgI6rX!Z;$WUG6)Ai^$y z?|HIa^pWQIcBfgX0tGh>AK5H~CabA=7pzB*3PBqyKP(ZkU1j&@2RAcb*7pS-6iQx} zWEFT|X%-8-{}4Ts06yNEk@aRSq5 z4r;YAygn0nhwmOoC`A-T}cLq6m-CYg(w7wKuz;cNhIwokhtBoV%{z)TB8i9-=T^ zyNxj)djUN2 zrICAbNOg-XcqwL}drZ`q{@fLGTJZ23V;ZqXiaK~X z5|sFX8{Xy|ggZGjuA+%+hTh*95BWowHYGzo2v}UYmx#reG%A=BRf>RZqU$JA!h&2g zWo^;@T{t9ma4!jsc;JC_sheP#1Vy@7#Egv1yBQB7TH zc|*4E($Ripc!oR-!Q{fZq~~>)iVI}@%xy1;MFXTga(wAVvIESM(Fk@=3EkjP3GPo( zG(+VP2;#dPU+Or8HhWJJi=QGr+{bguo16A7gK|)^FG}QgBvb~be%EuB# z10x#1-PDa065!|HN*y5<-|Ajh#B$xR4PMPrlOV^ta6CK2J-$Aj=y({Jy(uJWF}Nq- z;)-Bt|HP&4;_u&7>5qjxF^tcFVD4^1m6`2n@2cShKc=AD87v}BCKO7DpB@VlAKOon_tC3GBn%is*tI}-`<4HCCR53eHgoFU@423v` zBJXM^(#_eu8FGV&r}aT)krGz}YGS?q09|qIsl2`#5*U8uCEf2?JUc$L)gd9mbj8}diHgdS5(!>KqnxgW|vP(Ln zzP(#@BP0-ToZq_Mc31JJ7ro|00|q+r7HY;x`l#2o(eLC+^NVMqj^s*PvycWP3n!cw zfjP`KT;Ou^fpXk>o!hy^`-hfWM4YBx`GV3cJWjE<$gLNp0#4>gn~)!z(-v%*Nz+Z0;^jDV&||Q0b@< zi00MV7#0?HO(;|lK7q2c$YGc^K2V$Nd#VgN-j1&&cr$A^y|G?T=jD+$7^{Zun)y9M@F_6RzPq%#Eu)2%pixJ+%jd2l{Yq+hrz zNrVKVf=6knVnA!xi@5CQXeFI06gG%|cYjiESw5Z}FTxu^kit$pFR@a|WHKrDypb|*dhLqbeyTKUmBTJRvGb#~>Xt&tEkxNB-&zTZ-PYC9buL#B!Zq ziLiortH^7qSPa<7sAsxz;=vV)kk=F~d;;hgnA5b(;CJx5Vnczq<`TW7Lg`7QY<=_s zow;Ft9=H)^q2X)X1qM3hu@-{UD$*Z4JlrfFjbq{sh>5n^G1vJh!lv@VC1|WM8=UC1 zs)G>r=ESSOe7lx&Ria3i%aT#tV5xVF?_-dID@&)pZ=E`+Qn)b z_Hkwy{IvBc%XRBekS%z%gnz{IqCU+EopskOOF%_%<4Y%L=CiOd4jeeBz;T(82va=} z^TZUbv`OWqQ0AqpUH1*Dq6(Te$g6hrcz<{J9n@^|c43d?=L}d@SRjMvDULE{NjSWa zkJ$hXu#>?iWopzbJt14A#u;n#-U!~=VEakG2a0%h9` zz+S!5WhQxi4)*h_lBb6nDJ-W%n+$^^jreZ77os=*kQKXAy!av7c;fhOJ69o+R zn~wD7?P%fw7=Ydpo2UzadjXay!kO+~r_7A<))zw1EMsy(Jue9766i6tN%Bre=Vg5w zW_$I>fEkzVd|*LC%`!o&slNC;@^-xC9(at+{z=4GSFQ@9x00_aPtzBOYayvx4s7^T zw$mqZtHN4|^>n}iyQf7eR4pTtLL|Toct`$aR}3Fv;oIvk&32@d`>0MV(!@7~OjH6J zz8+On(^DOScr^>-rd_3KtBZIT6Lv=j5BDdgD29?uxSe!Eb-rRLvzv1aDQO z`@IB6r)sg~5v8dbAF2UGko@DAjb%T6m-=$sjZQh^4TXU74BlJYaoDXTQNQd9^x+{%&A>O=vTVv7XBA zp|7!yh7>v6YAp%$NpbWMWr6y5r$t?8ohxU&hNNS-dBj zE5w{n8-^v)eiSk};Ex3UFqhmaKA3NkEXeeIN978^Ww>=jolN9yQlht9J&u-@*ebS> zrd1H}eQQPK$@pBBkzC;E$k?PTj#JbS;?j=9qmn=mZKpF=0h>wInzL>98eZwA+Z4;1 z@Z;*jRs$@KNsQv|!|QPNj@fKe*i-Wegm1Sfur%u?#Waw$%xXKaN}jfTt#wB#i3nRF zBvm{URjR%-5ON3C9_59}A|_)NBz8+tilQSAp*jS2Xl80yCt?gtXu%9P9=Fa^qrDUu zVn+KhU71?{nkKVOl}=^fZ!Jo32_#-8Mc2D7YUfBrHC6M;W{Nq~n5S+@&;0N-XRf3$ z1@j5{4aM22%gC*t!UHrpX4(clY#wLU@qtoy$KTA`k7xvXkQREJGDd%}W&!oYyD?XG z*TZSXzug)2mj9;6KqOT%-AkuNJ=T*>y^=I? z5*rq>BnYKX9jVovXFplygm~dIf~+J=`HOIA(ixQPzN=>%Bm`g29N>e!L)bK#WG$wt zs0AK7ItAOS!*dxz->*7Ob(oQqNB4_fsZhy6loT{_Gc~+BUlh;lPHtv>i~_4KnmWaz zprA)@6(vN*VrS0yuz-0Pdtx@-mx>}#hh5bVb(Dq*Ee0A&th()r>%I4aDMMA6edqM1 zWP(rB;5)PvuJS1i-6sn~>`u#Nf5}bkIo4aA8{}f zjU5T;wJxyW7)`-fD&oiv3q{puPaaaNYu)IGU$4}vv-qc|?=}O&1_(6@U;4Tz*wGMY zN)E%S0fk;=B5vZj)$^p(E_$kW+O7puYsP>&@V@$Lf;cMTVqgIetWn&y)yY7o)N-(! z&TR{QN?9yXnBOJ^jJE$-g7Dg#MBX2`jUfYw2RkJ&2ZdY?$H9Ki>&v~sRB1g6ISs;S z^pgtrY%GrE-R%&`VFEuRhv?Rlc{ih~k4sK0jwOtfda)Q&6VbL>7&ncD)(s1*wucql z)-GV@aZv%D=-OhvNT%_5;r%bcz8e1ig_6fGHGCl3-El!@Bb76yZ}HA^hoSdx36W=&cm-yOlHB*u)L-Gu(&K-3Y26y$| z$xTg;)>E31$-L-dr-R55_cIWG@wjyVT$GO5Utc61h$2*1)DAA%-grB6U?pZ<r_Z}6 zwGg7>_-!!stlqpCCG7c}+~{?|*9hriA**sYB8638hXq%T%bkWWEJ)nZxe&Plh2*nk z7dn!_d_h6*_rkBLrUT-zgJ8Ev=Co9lUjfowOsW%L(aX0VV&(9DHPYeqr^lai*if zfuAG>l_1;|grOS2lq&JwU%TC-AnB-e*S6y$H-VnhLIu{!%j5M;a}hcL31q=F48^hP z!k6M1d^Wf%xo#XkcHCfn$`Zg&s>-e*{7TJW_)^c1)3pL){dyhs z2`we`8@at@MjfHL5VI_HkNB{P>w5Mvx}LBL`7vQJ;JyBwFrKYp*yN?PID+Aw;^{!e z`$T>M!!r%ClVwe~=tlws@6I>`bIWTem16AR1;vuvi4h-J7V0N`$}IYbT6R6Q*gg_Z z3@hsbjKBN?=0$plI9ANvO(;7c=}y(ZKCW6SeP398K^*xw$CYaI#fz`jWf){iA>e|e z6baFATG29XpWSyGoIP5lraNza2!v_U8?z}1x6=+K48GDDk~x@C!U5H?-mP=2 zs>s>$`1#NJ@DqrgagT~gW}!`5h=|EI#bxQeOpN3c5z`bP`BuGeEs#bVNaa&V+K?VI zOcY462n>g(cs~uslB<=ruG7UNbqG37R9mPt*xlaG_#m(e;;DNP`@iNj%Hf_46|f5S zGnkA$QeC~lCvZQ*F*k6TJ~t7za^a}mfg~9xor+jU5I&>K(>Cv9#u@M3f~YLnOi_dl zYQJve%#JfOoS6Da8&>vorS=0y_6|3?-G!n2B%`fRVdF-s(}vMP32marcaIid&2ZF` z>+92Qhsznlde~>ah1$InI5^wAWkp9?;bCpp;Sdjo&tqDkFFVmYE_!JxV(?xMW7vse zWxQfy22HS=Av)rA5|lQD=4Ww&KgA_cl|IyDu-_pO;ETUp=4o6i?qulg!-pgui%6tX zXH|Azh=8beBWcBA-`)pu)5rKI>$oO^(!i@+zFgQGl{-oZFFE*jacc>TlsW5_cp>3u zeXNA-&)`-hD6>+7v2u~jC=HV)q|s=7(Jc)>1NLzCSFXFrzL;0iTKJ)Cd*4fd>~a<~ zBAJWBDbev()oqqA*e}Vs?bh;jjIPD)*BGUSg6m8clR)f+-eLNNYhpqCf_^`njEVogE*3`sKA7bK!7FZ|nfWKo%vy3$%X~pq!7layM2BBA= zjBB)&9Tt;Cu2$F(pbfC+%Rl9x#wg#_)sI&*bWCl^{hGNEvnp&CbXo#(Id}lYexSl#>O1&8eVqZ3I8@HbM%OY@0v4N0VT7D5Ln|y3*uV_Dt{03_=UqfjrqT$xhdV zd0mZBQj_l3@OA-b$d>es10?U%nV5{V?jk}t2qozm7jV$rHW;jp)$pV~jt@!Vwk^_4E>9FJTsbA{XsRfLK|&^ei6 zK7SGIr>A1{sOHP-zh*74+n z#Ex(hYelBxqUzz7!SFvj`zqS?O4Hp(E83L5>U}&gN*gn6YYjP9-BW9eFW2Q1S=m!V zE>HbR2$ORZ`hlo3_dc;P(S5IMVWf>v$r&xmR0p&y=~l3 z{=jzkHjNv?l_0zcmkQW#Mx)1i^8w4Lo~fC5LMrUz3!ZkdBlhAXu1URvqfYXQB`p`h zs2QNEl%$grk0{?2SsTxNVZ3&2ZKIFItei*gibGgD3>GzIHuVq#_2J5!&gG^oD0R8E zn#)lv8~dNMtyhY4Xw9M^cPnl(k*xqNjrqb2$wWzq3vy#VU+Z~bp9BN`j@5&cIA-81 zTYzmsoqNCOn}$}cK+S%kq^h!jv#|OeYu#O~Ce>Uiz{IiZ8kH2Up#3#NcedkFgMd|) zpRad-`yt@lc9dAW7i*%I=c)B-0%o+3Le>V?mx31Bf~PI>@XneN%y=XBOJwPHgykvX zE8p!X>yFTOSJ#4l&C4Yb+iuvr&J)dyMpTl`Ooqt4c5)r}=N>!f51ckGa z@*N$0U#=u(KwctfGrPiVH4AJoKj)VFMAD30!4R>u62|2;w&h)w$6VuWXqt`{oe+y< zwpiTgAQss1*x_uDvfS*>#e#)h>l1B6?s`(^0H?^f9f)gRFVCjFnm{CNch~r#@!^ho z@a~v%7=AUnwo=4xy;v`)Z1_FxxIQnyF*zYN#w^k#d4yx|t(Mb1FFQe_#AftTr9r2C zgkI@w=S-z(=RnZgfxhX=fwu(nMUZRz0s83Cig^v%X|AsXs_rZ1DBbX@1kol}xKSoG zT8?DtDvK?cN*_5VvwjAv;aQAEj(4+J2EfUsi869MJ>Xawwc|kFcl#QmDDWBb`7AMA(EX??Q5(Hc$**FeL*>F$g09Iw*i|FKBm=XdK#B*YEO{82QFNd#99vD zUdXNpvBU{Xv@Nb7@00uQyBgzV7oedE1L?OOryo{-jU#-Fk9{CB$cG(Yel%oW+9_r1 z+4`({Vzjl!2Sig58pd`_r%Uph`LdoB)xs;vT2LKhtp{lW$CAStFv&ane`Al1S$asg z3r6a+|K&Dc!X@v1{1tO%gMR|d3=GlICyJwOhf4NrW!DyBeo)g|e~FV**P9V;%2mN% z^m<8?f?uL=Hl*5&?|N@K+F(Kz*362bTln=Z60bT2G>)?2B&64~2?*TzZ4xu(_6<1a zB1PNnxAEiAs)Ev>5RhHoW%Pc9WP(jAS&Y65$B6U}5a}XC+;Z`ejo9>cwJ7awjUV0b z`ld9x%K8#hsH=(AK-ukSpp&)D>cdNVyjW$0RWH_yIggViKF{Qufswis6s#pT+_v-Q z>+XM#@t@CA+Qt*U5}AkD@ub>X3F+@doAT5TzJ^AdYDKomz5ZDazCy-}%NToa)2#Ss zKvwCdl*QQBy#NhI>&rxo-%c|2Ptn8IuC#*ebY1Dh4!K`uJ1xKzb#Qz=FJqbY8uM=%?{X{2l^-`J)EM$~vNk${_GU3IF3``%yYJ{wt1z@?rbB zXw>(nP?Xk9?F^4iM61q^;%I`>Jq?m_)VtbQGG%_E?5tzvx5X{p6t!DxZpT^$?nhJ9A)Uy+)X7jo|st_#FI>bo7+yQ zh!#w4Y4r&s=rysN6K%TDdKu|zyd$PLl>a&|M z?G*n|kMSzqtv}VBZx`6!l!xMsibJC6+<(;m5Z|DpBLE&L)ZUC%0br!N`lB z0G5%}6cd|V3i$`^L7QT>0t=5112uCkWu{{8g3rWumSg!oFKhVTr+58XmScp2rne zjsBauFnXQIgMQJHtX>I;MAFBExz4@Fpc*qwdgr>;t60&|u|K2V3B)~0hHnpPXmFry zm|D1hnn;HacCVRLRd`j_mC^F=nPu?ZpSpho%_m~tAn7lm3Lm{ns?V4h8Mpur9|LBu zQB5@eNdc;9_i7AQuj@26R(Syu_#C&$uzNVl4k4L{e2NG*xnsrT(-aU3Z9&1h(cvivBq+`J$3q8Be z4={o0Xhidd6sUAWlsgN8q3hyI0%DyxfEb+Gk;eg7caq~`Z9w0Jf4m?5wKWvdgfHVV zfr@TQM!^EFBR`)k8V8DX9^tCInmEfDAM+<5Hs^L4y~l3-GsvAPV#5P|vCxldqOc=I z;<8^lMfs?Rvh!^9-M*v@NVcCs#627!%1OdHO~6-nJDkUb2BG=6HGh5dUzp1#qcj6` zLGy+>1pXCM(Ykye7@B`>MF+Abyh7O1#poT>_$V-X9671;EHGXClza|?)qq1j9?N`p zzfKgNb=u3-Tgj6LJJu|H620H^i`rp{1ocQjEObdt)bS`Po23Va`tA?#2e)nE+Cs)de3x%%^!KJ*85~Ca0j7>x&?5hY+x&qW?6KCm_F7_*j`1z- zN}al~YR*yJi_|LfYA87&F@dS-EA2)xV1zycId|D8^WSFc9|BxX{7i{RlQ;IjyOg%b7LiUVXY+y!B@9!bD zC|U8`iEm|xOp(Kmf6dhcGDwCXOozA`T8FLKL7R+Kp*gp+a(Vp^2*wbF#`fLG3%T4@ zr%n@mj>JCDTw~RdtlL>-W{1M%Vdt|sJ>#$`?ev&kJ6&BdP**j$e}cuY1M#YnOMn_~ z$d0y+pxG$eY>7#+rMH@L5RcrdayyB`df+po@GA&*GG7}>K8K34^d zMlP7I|DzNrxf%@mkYL)qHGAi7apAi>9k*%ieP1A-j42R3TrLpD9U^{cOOTKT{=7n| z$=+6z?WdoCSXSrv=Wj%L66!q%M2+&g(qJZuSol=8v7>={5fTVN05SbU)+;Tiq?Kfd zkRh=v4m1s`0W1z*9)FattF=a3*O0orvJ$|lJXb1JsBoWHY&aQh;C^jjYj>dRg83`3 z4!_Z)SXihe^|v8j!X7VCJ*_bami0h&aTW{1#Zh|wO#8^hht-J@vq>YEno&{H1y8QD zX8Rc`cUI)UukP)(49)36GjEU-#JGRI9Svn=1~14DC%YL94y2a6^*W8Jy?)+V#Trbq zg-e(VI1f6vjGemZT?*RzJ5+5eHd-GLL>t4;IB+p06Q%SZ4T7Na9YXar#1in|7#{Ma zZ}(pPmZBvVoQVH8Zl%JM1~ExjTz<$4YN+nOZ*bjOI-n<)-Co{h-w*y?D9Az^!{-wI z+YDJ%t;WR1*B_mcI8y9b*+9+V1%CyX>e4|d2s0VUJ*z~_Txdy2?*g zPxhK{=@~fmg^BWm_i{%;t#E|@6;CGf+ynL~$5D>&?oJq?m3Q~ksA3J#MUL8?rYoOM zh)1fUpDwA0{DdscR{~UKc=>Clqh&E;V~xW{$2P;Z7Cb@(e#0y=FZd!_=SeiqHF96X z$;-o`_i*PZlwT2XRXC|ctIpJ>_xLZ%&W0Se&$A)A0*pk!p~@ll_%1uw>gfm6JLgq zO-!lIVxe=q0EVM=c`f3HpN^EQ=M%)x?cx-&0~{2kzKG13XjKd>vq?MSs|`3%fm$3F zwHK*uJ#j2I*;t8XMg*;~$2{Ch0LFm9uB)tD&ivnUk*rGyn6W$aL%dyH&tm@3NJs@L zx*;~4`=6d!3}VzAdWwi8brMG2bbd8SfvQ$!!pg$-+}#}Rnu0&a6kR>H)2R0f7AFYGP_KG|8G z-`+5PQj2{1?}1*o4>-Y<$lF9lLt-w*+m>)?r$%gN%vmkL)pLFEf6&x^oR9Hc(5a39 z{dx~>Uekyv$@k~!PFXn7usV&2<6;RkwI51eY~o+NE0Uf3=7dFVO9MD1Y*PjTW;^E% z)xlxBbUx5bgl24voWz~;_nV{FBbGm4Cq~nyCy_{D!aV64xO~Q)H0TP$8PUsf)_(41 zo;&f4-H9{V+X4G}MB4W=p9HIsgVO)VwN6�Chw%=5&_7(ZBR5$;p@JgzIACH}MgI zS&*-AlkZCg4nwaO-{&q*?(lc;^PA4stIOsxLO6X(*b)ozk9~-k zn%d+rfUBeUVKZ)7i)^wV0eXx)H+LGI0)X{2m%4cULP#=X1CBI@NP{{soTZ%!A3J+i zIvHCWtGafp# zsH6bcLVhd{t&Jj;& z9Iv|Zi;obO1{}1C1GHY(%VnUt0@6a_$uo@UXu zZxQ1oforYOLKuPhzWN#Foz?48`dq)>{L6s@Sr#L<`sqt-PZl#+xPbbfcsS}W34t%q z6M%7Cb(hikIe`>-CoX$)e{voo z9ZR>yP$&OZ!%PM5Rs_TxLAH8bM65yG39RQ#$h1yt)d-mUHfB|w!Om~JUDarKh zoBdM$@`rLxnQ>LD$FZjT>)>5%Psfk+@c_IL2~o0x2rK=S9|@@40PC@zKY%l$0)#iC4cK$tP@X~roxk^GeTk0n^WGWIh9>B&$@Soa8#FlJXvTVR0=qkYY zyiruPeE;~8GM9GBc?rH}1I&Mjt|9|=p8IaoFGQJITH%nOPzBdlP&b3<&;f?8t7FTc zpzzH?5|ydtsI*X9;|iIuBGkTnBzz$WYhKqkIQF8JRShzMQ$E5a*Zq#1jfw-x*w|WG z21T6RWgmc_+Ey&7_jijNoXr`M0awnONLe2HjW|s2+xK3d#;jO9RfKv5G2@r|L~XbC z?JO*r)dMRcQ4a#i@8~VPjibWME$P;s-wv$%P84Uk4bn6I&QysE2-*wPaC%w38oJf% zFWPcYdQy>j4&)I8gI7*gc0Y~&g@~I}3^%wJglDYkq`lJYbbrZ;^?m}pI)_tn8L0`Q zb{)rF)X|U2W69p(5DPg4gQ_F(zxCg2Hv~cadjAqXYY-jRqmhwh=K*X&VZ26UKt7z* z8%0KT(*Z)>IPKH@oOpcpRCMD&L|gyyM}z;4rN)hQ)Plx#KhOqM8NF^*LQTECn%OD% z_v>ut?Ja#RS%FAVeWMic!G(Cl7^BPFjMZ8diNw?CB&1DU|NY8_>?)xirh`wcGnh