diff --git a/app/services/qgis/map_service.py b/app/services/qgis/map_service.py index d26a2ad..e0d39c5 100644 --- a/app/services/qgis/map_service.py +++ b/app/services/qgis/map_service.py @@ -48,16 +48,10 @@ class MapService: template_cache.reset_project_state(project, texts, extent) else: logger.info(f"[首次加载] {os.path.basename(template_path)}") - modifier = TemplateModifier(self.config) - actual_path = modifier.modify(template_path) - template_cache.load_template(actual_path, layout_name=model.get("mapLayout", "A4")) - if actual_path != template_path: - try: - os.remove(actual_path) - except OSError: - pass + # 直接读原始模板,不做文件级修改(避免 ZIP 兼容性问题) + project.read(template_path) - # 更新 PostgreSQL 图层连接(仅首次加载) + # 更新图层连接 + GPKG/SRID/表名修正(仅首次加载) if not is_cache_hit: self._update_db_connections(project) @@ -94,59 +88,89 @@ class MapService: return model["name"] def _update_db_connections(self, project: QgsProject) -> None: - """更新所有 PostgreSQL 图层的数据库连接参数""" + """更新图层连接 + SRID修正 + GPKG静态层替换""" db_config = self.config["db"] override = self.config.get("template_override", {}) actual_schema = override.get("actual", {}).get("schema", "qgis") + static_config = self.config.get("static_layers", {}) + static_enabled = static_config.get("enabled", False) + gpkg_dir = static_config.get("gpkg_dir", "") + static_layers_map = static_config.get("layers", {}) + static_count = 0 for layer in project.mapLayers().values(): - if layer.providerType() == "ogr": + provider = layer.providerType() + + # GPKG 静态层替换:postgres 表 → 本地 GPKG 文件 + if provider == "postgres" and static_enabled: + uri_str = layer.dataProvider().uri().uri() + for name, info in static_layers_map.items(): + table_key = info["table"] + schema, table = table_key.split(".", 1) + if f'table="{schema}"."{table}"' in uri_str: + gpkg_path = os.path.join(gpkg_dir, info["file"]).replace("\\", "/") + layer.setDataSource(gpkg_path, name, "ogr") + static_count += 1 + logger.debug(f"静态图层 {name} → GPKG") + break + else: + # 没匹配到静态层,继续处理为 postgres + self._fix_postgres_layer(layer, db_config, actual_schema) + continue + + if provider == "ogr": static_count += 1 continue - if layer.providerType() != "postgres": - continue - - try: - uri = layer.dataProvider().uri() - uri.setConnection( - db_config["host"], - str(db_config["port"]), - db_config["database"], - db_config["username"], - db_config["password"], - ) - # 更新 schema - old_uri = uri.uri() - if f'table="{actual_schema}".' not in old_uri: - for old_schema in SCHEMA_REPLACEMENTS: - new_uri = old_uri.replace( - f'table="{old_schema}".', - f'table="{actual_schema}".', - ) - if new_uri != old_uri: - uri = QgsDataSourceUri(new_uri) - break - - # 表名映射(模板表名 ≠ 目标库表名) - uri_str = uri.uri() - for old_name, new_name in TABLE_RENAMES.items(): - full_old = f'table="{actual_schema}"."{old_name}"' - full_new = f'table="{actual_schema}"."{new_name}"' - if full_old in uri_str: - uri_str = uri_str.replace(full_old, full_new) - uri = QgsDataSourceUri(uri_str) - - layer.setDataSource(uri.uri(), layer.name(), "postgres") - - if layer.isValid(): - fc = layer.featureCount() - logger.info(f"图层 {layer.name()} 连接更新成功 ({fc} features)") - else: - logger.error(f"图层 {layer.name()} 更新后仍无效") - except Exception as e: - logger.error(f"更新图层 {layer.name()} 连接失败: {e}") + if provider == "postgres": + self._fix_postgres_layer(layer, db_config, actual_schema) if static_count: - logger.info(f"静态底图已本地化: {static_count} 个 GPKG 图层跳过远程连接") \ No newline at end of file + logger.info(f"静态底图已本地化: {static_count} 个图层") + + @staticmethod + def _fix_postgres_layer(layer, db_config, actual_schema): + """修正单个 PostgreSQL 图层的连接参数""" + try: + uri = layer.dataProvider().uri() + uri.setConnection( + db_config["host"], + str(db_config["port"]), + db_config["database"], + db_config["username"], + db_config["password"], + ) + # Schema 替换 + uri_str = uri.uri() + for old_schema in SCHEMA_REPLACEMENTS: + if f'table="{old_schema}".' in uri_str: + uri_str = uri_str.replace( + f'table="{old_schema}".', + f'table="{actual_schema}".', + ) + uri = QgsDataSourceUri(uri_str) + break + # 表名映射 + uri_str = uri.uri() + for old_name, new_name in TABLE_RENAMES.items(): + full_old = f'table="{actual_schema}"."{old_name}"' + full_new = f'table="{actual_schema}"."{new_name}"' + if full_old in uri_str: + uri_str = uri_str.replace(full_old, full_new) + uri = QgsDataSourceUri(uri_str) + # SRID 修正 + uri_str = uri.uri() + if " srid=0 " in uri_str: + uri_str = uri_str.replace(" srid=0 ", " srid=4326 ") + uri = QgsDataSourceUri(uri_str) + + layer.setDataSource(uri.uri(), layer.name(), "postgres") + + if layer.isValid(): + fc = layer.featureCount() + logger.info(f"图层 {layer.name()} 连接更新成功 ({fc} features)") + else: + logger.error(f"图层 {layer.name()} 更新后仍无效") + except Exception as e: + logger.error(f"更新图层 {layer.name()} 连接失败: {e}") \ No newline at end of file