产图记录
This commit is contained in:
+118
-98
@@ -36,20 +36,6 @@ _locks_lock = asyncio.Lock()
|
|||||||
xian_center = getattr( settings, "XIAN_CENTER", [108.948024, 34.263161])
|
xian_center = getattr( settings, "XIAN_CENTER", [108.948024, 34.263161])
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# 时间戳格式化
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
def format_disaster_time(occurred_time) -> str:
|
|
||||||
"""将 occurred_time 格式化为时间戳字符串(YYYYMMDDHHmmss),作为文件夹名"""
|
|
||||||
if isinstance(occurred_time, datetime):
|
|
||||||
return occurred_time.strftime("%Y%m%d%H%M%S")
|
|
||||||
elif occurred_time:
|
|
||||||
return str(occurred_time).replace("-", "").replace(":", "").replace(" ", "")[:14]
|
|
||||||
else:
|
|
||||||
return datetime.now().strftime("%Y%m%d%H%M%S")
|
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# region_code → 区县名称映射
|
# region_code → 区县名称映射
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -58,7 +44,6 @@ REGION_CODE_MAP = settings.area.to_dict()
|
|||||||
|
|
||||||
|
|
||||||
def _resolve_district(condition: dict) -> str:
|
def _resolve_district(condition: dict) -> str:
|
||||||
"""从 condition.region_code 映射区县名称"""
|
|
||||||
code = condition.get("region_code")
|
code = condition.get("region_code")
|
||||||
if code and str(code) in REGION_CODE_MAP:
|
if code and str(code) in REGION_CODE_MAP:
|
||||||
return REGION_CODE_MAP[str(code)]
|
return REGION_CODE_MAP[str(code)]
|
||||||
@@ -66,43 +51,23 @@ def _resolve_district(condition: dict) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _build_map_title(event_type: str, condition: dict, template_name: str) -> str:
|
def _build_map_title(event_type: str, condition: dict, template_name: str) -> str:
|
||||||
"""
|
|
||||||
构建地图标题。
|
|
||||||
|
|
||||||
格式:陕西西安{区县名称}{震级/降雨量}{模板名称}
|
|
||||||
- 地震:陕西西安临潼区5.1级地震专题图
|
|
||||||
- 暴雨(有降雨量):陕西西安长安区120mm降雨专题图
|
|
||||||
- 暴雨(无降雨量):陕西西安降雨专题图
|
|
||||||
"""
|
|
||||||
district = _resolve_district(condition)
|
district = _resolve_district(condition)
|
||||||
prefix = f"陕西西安{district}" if district else "陕西西安"
|
prefix = f"陕西西安{district}" if district else "陕西西安"
|
||||||
|
|
||||||
if event_type == "earthquake":
|
if event_type == "earthquake":
|
||||||
magnitude = condition.get("magnitude")
|
magnitude = condition.get("magnitude")
|
||||||
if magnitude is not None:
|
if magnitude is not None:
|
||||||
return f"{prefix}{float(magnitude)}级{template_name}"
|
return f"{prefix}{float(magnitude)}级{template_name}"
|
||||||
return f"{prefix}{template_name}"
|
return f"{prefix}{template_name}"
|
||||||
|
|
||||||
elif event_type == "rainfall":
|
elif event_type == "rainfall":
|
||||||
rainfall = condition.get("rainfall")
|
rainfall = condition.get("rainfall")
|
||||||
if rainfall is not None and rainfall != "":
|
if rainfall is not None and rainfall != "":
|
||||||
return f"{prefix}{float(rainfall)}mm{template_name}"
|
return f"{prefix}{float(rainfall)}mm{template_name}"
|
||||||
return f"{prefix}{template_name}"
|
return f"{prefix}{template_name}"
|
||||||
|
|
||||||
return f"{prefix}{template_name}"
|
return f"{prefix}{template_name}"
|
||||||
|
|
||||||
|
|
||||||
def _build_info_text(event_type: str, condition: dict, occurred_time) -> str:
|
def _build_info_text(event_type: str, condition: dict, occurred_time) -> str:
|
||||||
"""
|
|
||||||
构建信息面板文本(左上角橙色矩形区域)。
|
|
||||||
|
|
||||||
暴雨:时间 + 累计降雨量(如有)+ 已持续(如有)
|
|
||||||
地震:时间 + 震级(如有)+ 位置(如有)
|
|
||||||
不显示灾害类型标签(暴雨/地震)。
|
|
||||||
"""
|
|
||||||
lines = []
|
lines = []
|
||||||
|
|
||||||
# 时间
|
|
||||||
if isinstance(occurred_time, datetime):
|
if isinstance(occurred_time, datetime):
|
||||||
time_str = f"{occurred_time.year}年{occurred_time.month:02d}月{occurred_time.day:02d}日{occurred_time.hour:02d}时{occurred_time.minute:02d}分"
|
time_str = f"{occurred_time.year}年{occurred_time.month:02d}月{occurred_time.day:02d}日{occurred_time.hour:02d}时{occurred_time.minute:02d}分"
|
||||||
elif occurred_time:
|
elif occurred_time:
|
||||||
@@ -110,26 +75,21 @@ def _build_info_text(event_type: str, condition: dict, occurred_time) -> str:
|
|||||||
else:
|
else:
|
||||||
time_str = datetime.now().strftime("%Y年%m月%d日%H时%M分")
|
time_str = datetime.now().strftime("%Y年%m月%d日%H时%M分")
|
||||||
lines.append(f"时间:{time_str}")
|
lines.append(f"时间:{time_str}")
|
||||||
|
|
||||||
if event_type == "rainfall":
|
if event_type == "rainfall":
|
||||||
rainfall = condition.get("rainfall")
|
rainfall = condition.get("rainfall")
|
||||||
if rainfall is not None and rainfall != "":
|
if rainfall is not None and rainfall != "":
|
||||||
lines.append(f"累计降雨量:{float(rainfall)}mm")
|
lines.append(f"累计降雨量:{float(rainfall)}mm")
|
||||||
|
|
||||||
duration = condition.get("duration")
|
duration = condition.get("duration")
|
||||||
if duration is not None and duration != "":
|
if duration is not None and duration != "":
|
||||||
lines.append(f"已持续:{duration}")
|
lines.append(f"已持续:{duration}")
|
||||||
|
|
||||||
elif event_type == "earthquake":
|
elif event_type == "earthquake":
|
||||||
magnitude = condition.get("magnitude")
|
magnitude = condition.get("magnitude")
|
||||||
if magnitude is not None and magnitude != "":
|
if magnitude is not None and magnitude != "":
|
||||||
lines.append(f"震级:{float(magnitude)}级")
|
lines.append(f"震级:{float(magnitude)}级")
|
||||||
|
|
||||||
lon = condition.get("epicenter_lon")
|
lon = condition.get("epicenter_lon")
|
||||||
lat = condition.get("epicenter_lat")
|
lat = condition.get("epicenter_lat")
|
||||||
if lon is not None and lat is not None:
|
if lon is not None and lat is not None:
|
||||||
lines.append(f"位置:经度{float(lon)}°, 纬度{float(lat)}°")
|
lines.append(f"位置:经度{float(lon)}°, 纬度{float(lat)}°")
|
||||||
|
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
@@ -235,66 +195,34 @@ async def export_map(req: QgisMapExportRequest):
|
|||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 查询推理记录,获取 occurred_time
|
|
||||||
inference = await loop.run_in_executor(
|
inference = await loop.run_in_executor(
|
||||||
None, qgis_repository.query_inference_result, inference_id
|
None, qgis_repository.query_inference_result, inference_id
|
||||||
)
|
)
|
||||||
|
|
||||||
# 将 occurred_time 格式化为时间戳作为文件夹名
|
|
||||||
disaster_time = format_disaster_time(inference["occurred_time"])
|
|
||||||
event_type = inference["event_type"]
|
event_type = inference["event_type"]
|
||||||
|
batch_key = str(inference_id)
|
||||||
|
|
||||||
# 构建批次文件夹路径
|
# 构建批次文件夹路径(用 inferenceId 作为唯一文件夹名)
|
||||||
file_store = getattr(settings, "FILE_STORE_DIR", "G:/files")
|
file_store = getattr(settings, "FILE_STORE_DIR", "G:/files").replace("\\", "/")
|
||||||
output_tmpl = getattr(settings, "QGIS_OUTPUT_DIR", "xian/qgis/map/:eventType/:disasterTime")
|
output_tmpl = getattr(settings, "QGIS_OUTPUT_DIR", "xian/qgis/map/:eventType/:inferenceId")
|
||||||
output_dir = output_tmpl.replace(":eventType", event_type).replace(":disasterTime", disaster_time)
|
output_dir = output_tmpl.replace(":eventType", event_type).replace(":inferenceId", batch_key)
|
||||||
batch_folder = os.path.join(file_store, output_dir).replace("\\", "/")
|
batch_folder = os.path.join(file_store, output_dir).replace("\\", "/")
|
||||||
|
|
||||||
# 去重检查:同一 disasterTime 只产图一次
|
# 去重锁
|
||||||
if os.path.isdir(batch_folder):
|
|
||||||
existing_files = [
|
|
||||||
f for f in os.listdir(batch_folder) if f.endswith(".jpg")
|
|
||||||
]
|
|
||||||
if existing_files and disaster_time not in _in_progress_locks:
|
|
||||||
logger.info(
|
|
||||||
f"[去重] disasterTime={disaster_time} 已产图,直接返回 "
|
|
||||||
f"({len(existing_files)} 张)"
|
|
||||||
)
|
|
||||||
return QgisMapExportResponse(
|
|
||||||
code=200,
|
|
||||||
message=f"已存在,共{len(existing_files)}张",
|
|
||||||
data=disaster_time,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 去重锁:同一灾害时间排队等待
|
|
||||||
async with _locks_lock:
|
async with _locks_lock:
|
||||||
if disaster_time not in _in_progress_locks:
|
if batch_key not in _in_progress_locks:
|
||||||
_in_progress_locks[disaster_time] = asyncio.Lock()
|
_in_progress_locks[batch_key] = asyncio.Lock()
|
||||||
task_lock = _in_progress_locks[disaster_time]
|
task_lock = _in_progress_locks[batch_key]
|
||||||
|
|
||||||
async with task_lock:
|
async with task_lock:
|
||||||
if os.path.isdir(batch_folder):
|
# 精确判断在模板扫描后(比较文件数 vs 模板数)
|
||||||
existing_files = [
|
|
||||||
f for f in os.listdir(batch_folder) if f.endswith(".jpg")
|
|
||||||
]
|
|
||||||
if existing_files:
|
|
||||||
logger.info(
|
|
||||||
f"[去重] disasterTime={disaster_time} 已被并发请求产图完成"
|
|
||||||
)
|
|
||||||
return QgisMapExportResponse(
|
|
||||||
code=200,
|
|
||||||
message=f"已存在,共{len(existing_files)}张",
|
|
||||||
data=disaster_time,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"推理结果查询成功: id={inference['id']}, "
|
f"推理结果查询成功: id={inference['id']}, "
|
||||||
f"type={inference['event_type']}, "
|
f"type={event_type}, "
|
||||||
f"occurred_time={inference['occurred_time']}, "
|
f"occurred_time={inference['occurred_time']}"
|
||||||
f"disasterTime={disaster_time}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 推导参数 + 构建配置
|
|
||||||
os.makedirs(batch_folder, exist_ok=True)
|
os.makedirs(batch_folder, exist_ok=True)
|
||||||
|
|
||||||
config = _build_qgis_config(batch_folder)
|
config = _build_qgis_config(batch_folder)
|
||||||
@@ -327,6 +255,31 @@ async def export_map(req: QgisMapExportRequest):
|
|||||||
if not template_files:
|
if not template_files:
|
||||||
raise FileNotFoundError(f"模板文件夹为空: {template_dir}")
|
raise FileNotFoundError(f"模板文件夹为空: {template_dir}")
|
||||||
|
|
||||||
|
# 检查已产出的图片,只生成缺失的
|
||||||
|
existing = set()
|
||||||
|
if os.path.isdir(batch_folder):
|
||||||
|
existing = {f for f in os.listdir(batch_folder) if f.endswith(".jpg")}
|
||||||
|
|
||||||
|
if len(existing) == len(template_files):
|
||||||
|
logger.info(f"[跳过] {len(existing)}/{len(template_files)} 张已全部产出")
|
||||||
|
return QgisMapExportResponse(
|
||||||
|
code=200,
|
||||||
|
message=f"已存在,共{len(existing)}张",
|
||||||
|
data=batch_key,
|
||||||
|
)
|
||||||
|
|
||||||
|
missing_templates = []
|
||||||
|
for tpl_file in template_files:
|
||||||
|
out_name = os.path.splitext(tpl_file)[0] + ".jpg"
|
||||||
|
if out_name not in existing:
|
||||||
|
missing_templates.append(tpl_file)
|
||||||
|
|
||||||
|
if len(missing_templates) < len(template_files):
|
||||||
|
logger.info(
|
||||||
|
f"[增量] 已有{len(existing)}张, 缺{len(missing_templates)}张"
|
||||||
|
)
|
||||||
|
template_files = missing_templates
|
||||||
|
|
||||||
# 构建所有模型参数(批量模式)
|
# 构建所有模型参数(批量模式)
|
||||||
models = []
|
models = []
|
||||||
for tpl_file in template_files:
|
for tpl_file in template_files:
|
||||||
@@ -340,13 +293,13 @@ async def export_map(req: QgisMapExportRequest):
|
|||||||
)
|
)
|
||||||
models.append(model)
|
models.append(model)
|
||||||
|
|
||||||
# 一次性提交所有模型到 QGIS 子进程(单次 DLL 加载)
|
# 一次性提交所有模型到 QGIS 子进程(并行多进程,实时写进度)
|
||||||
_generate_batch_maps(models, config, disaster_time)
|
_generate_batch_maps(models, config, batch_key, inference_id, file_store)
|
||||||
|
|
||||||
return QgisMapExportResponse(
|
return QgisMapExportResponse(
|
||||||
code=200,
|
code=200,
|
||||||
message=f"任务已完成,共{len(models)}张专题图",
|
message=f"任务已完成,共{len(models)}张专题图",
|
||||||
data=disaster_time,
|
data=batch_key,
|
||||||
)
|
)
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
@@ -362,11 +315,14 @@ async def export_map(req: QgisMapExportRequest):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _generate_batch_maps(models: list, config: dict, disaster_time: str) -> None:
|
def _generate_batch_maps(models: list, config: dict, batch_key: str,
|
||||||
"""并行启动多个 QGIS 子进程,每个处理一部分模板"""
|
inference_id: int = None, file_store: str = None) -> None:
|
||||||
import json, math, concurrent.futures
|
"""并行启动多个 QGIS 子进程,实时读取每张图进度并写 DB"""
|
||||||
|
import json, math, concurrent.futures, subprocess, tempfile, threading
|
||||||
|
from app.services.qgis.qgis_env import (
|
||||||
|
get_qgis_python_path, get_runner_script, build_qgis_subprocess_env,
|
||||||
|
)
|
||||||
|
|
||||||
# 并行度:取配置的 worker 数和模板数的较小值
|
|
||||||
max_workers = getattr(settings, "QGIS_PARALLEL_WORKERS", 4)
|
max_workers = getattr(settings, "QGIS_PARALLEL_WORKERS", 4)
|
||||||
workers = min(max_workers, len(models))
|
workers = min(max_workers, len(models))
|
||||||
chunk_size = math.ceil(len(models) / workers)
|
chunk_size = math.ceil(len(models) / workers)
|
||||||
@@ -382,16 +338,52 @@ def _generate_batch_maps(models: list, config: dict, disaster_time: str) -> None
|
|||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
all_results = []
|
all_results = []
|
||||||
|
db_lock = threading.Lock() # 保护 DB 写入
|
||||||
|
|
||||||
def _run_chunk(chunk_models: list, chunk_idx: int) -> list:
|
def _run_chunk(chunk_models: list, chunk_idx: int):
|
||||||
"""单个子进程处理一批模板"""
|
"""单个子进程,逐张读取进度并实时写 DB"""
|
||||||
return _generate_maps_subprocess(chunk_models, config, chunk_idx)
|
request = json.dumps({"config": config, "models": chunk_models}, ensure_ascii=False)
|
||||||
|
tmp = tempfile.NamedTemporaryFile(suffix=".json", delete=False, mode="w", encoding="utf-8")
|
||||||
|
tmp.write(request)
|
||||||
|
tmp.close()
|
||||||
|
|
||||||
|
qgis_root = getattr(settings, "QGIS_ROOT", "D:/QGIS")
|
||||||
|
python_path = get_qgis_python_path(qgis_root)
|
||||||
|
runner = get_runner_script()
|
||||||
|
cmd = [python_path, runner, tmp.name]
|
||||||
|
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
|
||||||
|
env=build_qgis_subprocess_env(qgis_root),
|
||||||
|
text=True, encoding="utf-8", errors="replace",
|
||||||
|
)
|
||||||
|
|
||||||
|
chunk_results = []
|
||||||
|
for line in proc.stdout:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith("PROGRESS:"):
|
||||||
|
try:
|
||||||
|
r = json.loads(line[len("PROGRESS:"):])
|
||||||
|
chunk_results.append(r)
|
||||||
|
# ★ 每张图产出后立即写 DB
|
||||||
|
if inference_id and file_store and "error" not in r:
|
||||||
|
_write_single_path(inference_id, r.get("output", ""), file_store, db_lock)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
proc.wait()
|
||||||
|
try:
|
||||||
|
os.remove(tmp.name)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if proc.returncode != 0:
|
||||||
|
raise RuntimeError(f"[子进程{chunk_idx}] 失败 (exit={proc.returncode})")
|
||||||
|
|
||||||
|
return chunk_results
|
||||||
|
|
||||||
with concurrent.futures.ThreadPoolExecutor(max_workers=len(chunks)) as executor:
|
with concurrent.futures.ThreadPoolExecutor(max_workers=len(chunks)) as executor:
|
||||||
futures = {
|
futures = {executor.submit(_run_chunk, c, i): i for i, c in enumerate(chunks)}
|
||||||
executor.submit(_run_chunk, chunk, i): i
|
|
||||||
for i, chunk in enumerate(chunks)
|
|
||||||
}
|
|
||||||
for future in concurrent.futures.as_completed(futures):
|
for future in concurrent.futures.as_completed(futures):
|
||||||
chunk_idx = futures[future]
|
chunk_idx = futures[future]
|
||||||
try:
|
try:
|
||||||
@@ -484,3 +476,31 @@ def _generate_maps_subprocess(chunk_models: list, config: dict, chunk_idx: int)
|
|||||||
|
|
||||||
logger.warning(f"[子进程{chunk_idx}] 无输出")
|
logger.warning(f"[子进程{chunk_idx}] 无输出")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# file_path 数据库记录
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
def _relative_path(absolute_path: str, file_store: str) -> str:
|
||||||
|
"""绝对路径 → 相对于 FILE_STORE_DIR 的路径"""
|
||||||
|
fs = file_store.replace("\\", "/").rstrip("/")
|
||||||
|
ap = absolute_path.replace("\\", "/")
|
||||||
|
if ap.startswith(fs + "/"):
|
||||||
|
return ap[len(fs) + 1:]
|
||||||
|
return ap
|
||||||
|
|
||||||
|
|
||||||
|
def _write_single_path(inference_id: int, out_path: str, file_store: str, lock) -> None:
|
||||||
|
"""单张图产出后立即写入进度表"""
|
||||||
|
if not out_path or not os.path.isfile(out_path):
|
||||||
|
return
|
||||||
|
rel = _relative_path(out_path, file_store)
|
||||||
|
if not rel:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
from app.repositories.qgis_repository import qgis_repository
|
||||||
|
with lock:
|
||||||
|
qgis_repository.insert_file_paths(inference_id, [rel])
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[实时写入] 失败: {e}")
|
||||||
|
|||||||
@@ -27,5 +27,31 @@ class QgisRepository:
|
|||||||
"condition": row["condition"] if isinstance(row["condition"], dict) else {},
|
"condition": row["condition"] if isinstance(row["condition"], dict) else {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def insert_file_paths(inference_id: int, paths: list[str]) -> None:
|
||||||
|
"""实时写入文件路径到进度表(唯一索引自动去重)"""
|
||||||
|
if not paths:
|
||||||
|
return
|
||||||
|
import os
|
||||||
|
sql = """
|
||||||
|
INSERT INTO xian_inference_result_file (inference_id, file_path, file_name)
|
||||||
|
VALUES (%s, %s, %s)
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
"""
|
||||||
|
for p in paths:
|
||||||
|
name = os.path.basename(p)
|
||||||
|
db_helper.execute_update(sql, (inference_id, p, name))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_file_paths(inference_id: int) -> list[str]:
|
||||||
|
"""获取已产出的文件路径列表(从进度表)"""
|
||||||
|
sql = """
|
||||||
|
SELECT file_path FROM xian_inference_result_file
|
||||||
|
WHERE inference_id = %s AND is_delete = 0
|
||||||
|
ORDER BY create_time
|
||||||
|
"""
|
||||||
|
rows = db_helper.execute_query(sql, (inference_id,))
|
||||||
|
return [r["file_path"] for r in rows]
|
||||||
|
|
||||||
|
|
||||||
qgis_repository = QgisRepository()
|
qgis_repository = QgisRepository()
|
||||||
|
|||||||
@@ -113,7 +113,10 @@ def _init_qgis():
|
|||||||
def _process_single(service, model):
|
def _process_single(service, model):
|
||||||
"""处理单个模板,返回结果 dict"""
|
"""处理单个模板,返回结果 dict"""
|
||||||
name = service.generate(model)
|
name = service.generate(model)
|
||||||
return {"name": name, "output": model["outFile"]}
|
result = {"name": name, "output": model["outFile"]}
|
||||||
|
# ★ 实时进度:每完成一张图就输出到 stdout
|
||||||
|
print(f"PROGRESS:{json.dumps(result, ensure_ascii=False)}", flush=True)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
+2
-2
@@ -11,7 +11,7 @@ PREDICT_PROBABILITY_THRESHOLD = 50
|
|||||||
# 静态底图 GeoPackage 目录(相对于项目根目录)
|
# 静态底图 GeoPackage 目录(相对于项目根目录)
|
||||||
QGIS_GPKG_DIR = "app/data/gpkg"
|
QGIS_GPKG_DIR = "app/data/gpkg"
|
||||||
# 专题图输出子目录(相对于 FILE_STORE_DIR)
|
# 专题图输出子目录(相对于 FILE_STORE_DIR)
|
||||||
QGIS_OUTPUT_DIR = "xian/qgis/map/:eventType/:disasterTime"
|
QGIS_OUTPUT_DIR = "xian/qgis/map/:eventType/:inferenceId"
|
||||||
# 专题图默认参数
|
# 专题图默认参数
|
||||||
QGIS_DEFAULTS_MAP_LAYOUT = "A3"
|
QGIS_DEFAULTS_MAP_LAYOUT = "A3"
|
||||||
QGIS_DEFAULTS_ZOOM_RULE = "11"
|
QGIS_DEFAULTS_ZOOM_RULE = "11"
|
||||||
@@ -83,7 +83,7 @@ FILE_STORE_DIR = "G:/files"
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
QGIS_ROOT = "D:/QGIS"
|
QGIS_ROOT = "D:/QGIS"
|
||||||
# 专题图输出子目录
|
# 专题图输出子目录
|
||||||
QGIS_OUTPUT_DIR = "xian/qgis/map/:eventType/:disasterTime"
|
QGIS_OUTPUT_DIR = "xian/qgis/map/:eventType/:inferenceId"
|
||||||
QGIS_DEFAULTS_MAP_UNIT = "制图单位:西安市应急管理局"
|
QGIS_DEFAULTS_MAP_UNIT = "制图单位:西安市应急管理局"
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user