瀏覽代碼

拓扑检查核心SQL算法集成

wanger 6 月之前
父節點
當前提交
fa6f455fb4
共有 51 個文件被更改,包括 9008 次插入648 次删除
  1. 181 0
      processing/algs/gdal/A00.py
  2. 190 0
      processing/algs/gdal/A01.py
  3. 190 0
      processing/algs/gdal/A02.py
  4. 32 85
      processing/algs/gdal/A03.py
  5. 190 0
      processing/algs/gdal/A04.py
  6. 198 0
      processing/algs/gdal/A05.py
  7. 209 0
      processing/algs/gdal/AA01.py
  8. 208 0
      processing/algs/gdal/AA02.py
  9. 208 0
      processing/algs/gdal/AA03.py
  10. 208 0
      processing/algs/gdal/AA04.py
  11. 208 0
      processing/algs/gdal/AA05.py
  12. 208 0
      processing/algs/gdal/AL01.py
  13. 208 0
      processing/algs/gdal/AP01.py
  14. 208 0
      processing/algs/gdal/AP02.py
  15. 56 0
      processing/algs/gdal/GdalAlgorithm.py
  16. 83 1
      processing/algs/gdal/GdalAlgorithmProvider.py
  17. 189 0
      processing/algs/gdal/L00.py
  18. 189 0
      processing/algs/gdal/L01.py
  19. 189 0
      processing/algs/gdal/L02.py
  20. 189 0
      processing/algs/gdal/L03.py
  21. 189 0
      processing/algs/gdal/L04.py
  22. 189 0
      processing/algs/gdal/L05.py
  23. 198 0
      processing/algs/gdal/L06.py
  24. 189 0
      processing/algs/gdal/L07.py
  25. 189 0
      processing/algs/gdal/L08.py
  26. 189 0
      processing/algs/gdal/L09.py
  27. 198 0
      processing/algs/gdal/L10.py
  28. 208 0
      processing/algs/gdal/LA01.py
  29. 208 0
      processing/algs/gdal/LA02.py
  30. 208 0
      processing/algs/gdal/LA03.py
  31. 208 0
      processing/algs/gdal/LL01.py
  32. 208 0
      processing/algs/gdal/LL02.py
  33. 208 0
      processing/algs/gdal/LL03.py
  34. 208 0
      processing/algs/gdal/LL04.py
  35. 208 0
      processing/algs/gdal/LP01.py
  36. 189 0
      processing/algs/gdal/P00.py
  37. 189 0
      processing/algs/gdal/P01.py
  38. 208 0
      processing/algs/gdal/PA01.py
  39. 208 0
      processing/algs/gdal/PA02.py
  40. 208 0
      processing/algs/gdal/PA03.py
  41. 208 0
      processing/algs/gdal/PL01.py
  42. 208 0
      processing/algs/gdal/PL02.py
  43. 208 0
      processing/algs/gdal/PP01.py
  44. 208 0
      processing/algs/gdal/PP02.py
  45. 2 2
      processing/algs/gdal/topologycheck.py
  46. 39 35
      processing/gui/Postprocessing.py
  47. 78 0
      processing/tools/SpatiaLite/SpatiaLite.py
  48. 二進制
      processing/tools/symbology-style.db
  49. 19 8
      processing/tools/topology/read.py
  50. 488 515
      processing/tools/topology/topoCheck.yaml
  51. 2 2
      processing/tools/topology/topology.py

+ 181 - 0
processing/algs/gdal/A00.py

@@ -0,0 +1,181 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    A00.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class A00(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "A00"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def commandName(self):
+        return "ogr2ogr"

+ 190 - 0
processing/algs/gdal/A01.py

@@ -0,0 +1,190 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    A01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.system import isWindows
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class A01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "A01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 190 - 0
processing/algs/gdal/A02.py

@@ -0,0 +1,190 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    A02.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.system import isWindows
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class A02(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "A02"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 32 - 85
processing/algs/gdal/A03.py

@@ -57,8 +57,10 @@ from processing.tools.StringUtils import (getConnectionStr, getNow)
 from processing.tools.GeoServer.Geoserver import Geoserver
 from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
 from processing.tools.system import isWindows
+from processing.tools.StringUtils import getUUID
 from processing.tools.FileUtils import getParentFolderPath
 from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
 import sqlite3
 
 pluginPath = os.path.normpath(os.path.join(
@@ -71,11 +73,12 @@ class A03(GdalAlgorithm):
     INPUTVECTOR = "INPUTVECTOR"
     OUTPUTVECTOR = 'OUTPUTVECTOR'
     TOPOLOGYTYPE = "A03"
-    in_table = "topology_table"
-    out_table = "topology_table_temp"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
     TOPOLOGYPARAMS = {
-        "intable_s": in_table,
-        "outtable": out_table
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
     }
 
     def __init__(self):
@@ -89,7 +92,7 @@ class A03(GdalAlgorithm):
                                                                   self.tr('输出位置(矢量数据和报告)')))
 
     def name(self):
-        return 'A03'
+        return self.TOPOLOGYTYPE
 
     def icon(self):
         return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
@@ -112,11 +115,11 @@ class A03(GdalAlgorithm):
         return 'topology'
 
     def topologycheck(self, parameters, context, feedback, executing=True):
-        print("面不能有空隙检查开始啦")
+        print("拓扑检查开始啦")
         # TODO 参数设置
         spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
-        table_name = self.in_table  # 导入后的表名
-        outtable_name = self.out_table  # 分析执行后的表名
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
         output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
         export_layer_name = outtable_name
         # TODO 将 vectorlayer导入到Spatialite
@@ -124,111 +127,55 @@ class A03(GdalAlgorithm):
         if not input_layer.isValid():
             return {
                 "状态": "拓扑检查失败",
-                "错误信息": f"Failed to load SHP file."
+                "错误信息": f"图层数据不可用。"
             }
-        crs = input_layer.crs().authid()
-        # TODO 构造连接到Spatialite数据库的URI
-        uri = QgsDataSourceUri()
-        uri.setDatabase(spatialite_db_path)
-        # TODO 将vectorlayer写入Spatialite 数据库
-        options = QgsVectorFileWriter.SaveVectorOptions()
-        options.driverName = "SQLite"
-        options.layerName = table_name
-        options.fileEncoding = "UTF-8"
-        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
-        # TODO 将QgsVectorLayer导入到spatialite并指定表名
-        result = QgsVectorFileWriter.writeAsVectorFormatV2(input_layer, spatialite_db_path,
-                                                           QgsCoordinateTransformContext(), options)
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
         if result[0] != QgsVectorFileWriter.NoError:
             return {
                 "状态": "拓扑检查失败",
-                "错误信息": f"Failed to import SHP file to Spatialite."
-            }
-        print(f"SHP file imported to Spatialite as table: {table_name}")
-        # TODO 执行 SQL 语句
-        conn = sqlite3.connect(spatialite_db_path)
-        conn.enable_load_extension(True)
-        cursor = conn.cursor()
-        conn.execute("PRAGMA synchronous = OFF")
-        conn.execute("PRAGMA cache_size = -20000")  # In KB
-        conn.execute("PRAGMA temp_store = MEMORY")
-        try:
-            conn.execute("SELECT load_extension('mod_spatialite');")
-            print("mod_spatialite loaded successfully.")
-        except sqlite3.OperationalError as e:
-            return {
-                "状态": "拓扑检查失败",
-                "错误信息": f"Failed to load extension: {e}"
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
             }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
         # TODO SQL语句
         sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
         try:
-            cursor.executescript(f"{sql}")
-            print(f"Script executed successfully.{sql}")
+            dbutils.executescript(f"{sql}")
         except sqlite3.Error as e:
             return {
                 "状态": "拓扑检查失败",
-                "错误信息": f"An error occurred: {e}"
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
             }
-        conn.commit()
-        conn.close()
-        print("SQL execution completed.")
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
         # TODO 将数据导出为本地矢量文件
         processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
                                          "ogr")
         path = getParentFolderPath(output_vector_path)
         csv_path = f"{path}\\report.csv"
         if not processed_layer.isValid():
+            dbutils.closeDb()
             return {
                 "状态": "拓扑检查失败",
-                "错误信息": "Failed to load processed layer."
+                "错误信息": "拓扑检查结果图层加载失败。"
             }
         else:
-            options = QgsVectorFileWriter.SaveVectorOptions()
-            options.driverName = "CSV"  # Output format
-            options.includeGeometry = True  # Include geometry
-            # options.setLayerOptions(QgsVectorFileWriter.LayerOptions())
-            # context = QgsCoordinateTransformContext()
-            # options.setOutputWkt(True)
-            context2 = QgsCoordinateTransformContext()
-            error = QgsVectorFileWriter.writeAsVectorFormatV3(processed_layer, csv_path, context2, options)
-            if error[0] == QgsVectorFileWriter.NoError:
-                print(f"Exported {table_name} to {csv_path} successfully!")
-            else:
-                return {
-                    "状态": "拓扑检查失败",
-                    "错误信息": f"Failed to export {table_name} to CSV: {error}"
-                }
-        # TODO 导出矢量文件参数配置
-        export_options = QgsVectorFileWriter.SaveVectorOptions()
-        export_options.driverName = "ESRI Shapefile"
-        export_options.fileEncoding = "UTF-8"
-        result = QgsVectorFileWriter.writeAsVectorFormatV2(processed_layer, output_vector_path,
-                                                           QgsCoordinateTransformContext(), export_options)
-        if result[0] != QgsVectorFileWriter.NoError:
-            return {
-                "状态": "拓扑检查失败",
-                "错误信息": f"Failed to export processed layer to SHP file."
-            }
-        feature_count = processed_layer.featureCount()
-        return {
-            "状态": "拓扑检查成功",
-            "结论": "不符合" if feature_count > 0 else "符合",
-            "错误项": f"{feature_count}条记录",
-            # "矢量数据输出位置": output_vector_path,
-            "报告输出位置": csv_path
-        }
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
 
     # 判断数据是否为字符串
     def is_string(self, var):
         return isinstance(var, str)
 
     def getConsoleCommands(self, parameters, context, feedback, executing=True):
-        inputvector = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
-        print(f"拓扑检查输入矢量图层:")
-        print(inputvector)
-        outFile = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)
-        print(f"拓扑检查输出文件:{outFile}")
         return []
 
     def contains_keys(self, obj, keys):

+ 190 - 0
processing/algs/gdal/A04.py

@@ -0,0 +1,190 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    A04.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.system import isWindows
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class A04(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "A04"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 198 - 0
processing/algs/gdal/A05.py

@@ -0,0 +1,198 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    A05.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext, QgsProcessingParameterNumber
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.system import isWindows
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class A05(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    tolerance = "tolerance"
+    TOPOLOGYTYPE = "A05"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        # 创建一个参数,提示用户输入一个小数值
+        self.addParameter(QgsProcessingParameterNumber(self.tolerance,
+                                                       self.tr('容差'),
+                                                       QgsProcessingParameterNumber.Double
+                                                       ))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        tolerance = self.parameterAsDouble(parameters, self.tolerance, context)  # 输出的 SHP 文件路径
+        self.TOPOLOGYPARAMS["tolerance"] = str(tolerance)
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 209 - 0
processing/algs/gdal/AA01.py

@@ -0,0 +1,209 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    AA01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class AA01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "AA01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/AA02.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    AA02.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class AA02(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "AA02"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/AA03.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    AA03.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class AA03(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "AA03"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/AA04.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    AA04.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class AA04(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "AA04"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/AA05.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    AA05.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class AA05(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "AA05"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/AL01.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    AL01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class AL01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "AL01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/AP01.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    AP01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class AP01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "AP01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/AP02.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    AP02.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class AP02(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "AP02"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 56 - 0
processing/algs/gdal/GdalAlgorithm.py

@@ -25,6 +25,7 @@ import numpy as np
 from PyQt5.QtGui import QIcon
 
 from qgis.PyQt.QtCore import QUrl, QCoreApplication
+from qgis._core import QgsCoordinateTransformContext
 
 from qgis.core import (QgsApplication,
                        QgsProject,
@@ -296,6 +297,61 @@ class GdalAlgorithm(QgsProcessingAlgorithm):
             name = name[:-3]
         return name
 
+    # 将VectorLayer导入到SpatiaLite数据库
+    def importLayerToSpatiaLite(self, layer, table_name):
+        # TODO 构造连接到Spatialite数据库的URI
+        uri = QgsDataSourceUri()
+        uri.setDatabase(self.spatialite_db_path)
+        # TODO 将vectorlayer写入Spatialite 数据库
+        options = QgsVectorFileWriter.SaveVectorOptions()
+        options.driverName = "SQLite"
+        options.layerName = table_name
+        options.fileEncoding = "UTF-8"
+        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
+        # TODO 将QgsVectorLayer导入到spatialite并指定表名
+        result = QgsVectorFileWriter.writeAsVectorFormatV2(layer, self.spatialite_db_path,
+                                                           QgsCoordinateTransformContext(), options)
+        return result
+
+    # 将VectorLayer导出到文件
+    def vectorLayerExport(self, layer, path, type):
+        options = QgsVectorFileWriter.SaveVectorOptions()
+        options.driverName = type  # Output format
+        # options.includeGeometry = True  # Include geometry
+        context2 = QgsCoordinateTransformContext()
+        error = QgsVectorFileWriter.writeAsVectorFormatV3(layer, path, context2, options)
+        if error[0] == QgsVectorFileWriter.NoError:
+            print(f"Exported {path} successfully!")
+        else:
+            print(f"Failed to export to {path}: {error}")
+
+    # 将VectorLayer导出到矢量文件
+    def vectorLayerExportToVector(self, layer, path, type="ESRI Shapefile"):
+        # TODO 导出矢量文件参数配置
+        export_options = QgsVectorFileWriter.SaveVectorOptions()
+        export_options.driverName = type
+        export_options.fileEncoding = "UTF-8"
+        result = QgsVectorFileWriter.writeAsVectorFormatV2(layer, path,
+                                                           QgsCoordinateTransformContext(), export_options)
+        if result[0] != QgsVectorFileWriter.NoError:
+            print(f"Failed to export processed layer to SHP file.")
+
+    # 拓扑检查成功,没有错误项
+    def topologySuccessWithNone(self):
+        return {
+            "状态": "拓扑检查成功",
+            "结论": "符合"
+        }
+
+    #拓扑检查成功
+    def topologySuccess(self, count, reportpath):
+        return {
+            "状态": "拓扑检查成功",
+            "结论": "不符合" if count > 0 else "符合",
+            "错误项": f"{count}条记录",
+            "报告输出位置": reportpath
+        }
+
     def tr(self, string, context=''):
         if context == '':
             context = self.__class__.__name__

+ 83 - 1
processing/algs/gdal/GdalAlgorithmProvider.py

@@ -99,7 +99,48 @@ from .ExportVectorByMask import ExportVectorByMask
 from .ExportRasterByMask import ExportRasterByMask
 from .VectorProject import VectorProject
 from .LicenseMake import LicenseMake
+from .A00 import A00
+from .A01 import A01
+from .A02 import A02
 from .A03 import A03
+from .A04 import A04
+from .A05 import A05
+from .P00 import P00
+from .P01 import P01
+from .L00 import L00
+from .L01 import L01
+from .L02 import L02
+from .L03 import L03
+from .L04 import L04
+from .L05 import L05
+from .L06 import L06
+from .L07 import L07
+from .L08 import L08
+from .L09 import L09
+from .L10 import L10
+from .PP01 import PP01
+from .PP02 import PP02
+from .PL01 import PL01
+from .PL02 import PL02
+from .PA01 import PA01
+from .PA02 import PA02
+from .PA03 import PA03
+from .LP01 import LP01
+from .LL01 import LL01
+from .LL02 import LL02
+from .LL03 import LL03
+from .LL04 import LL04
+from .LA01 import LA01
+from .LA02 import LA02
+from .LA03 import LA03
+from .AP01 import AP01
+from .AP02 import AP02
+from .AL01 import AL01
+from .AA01 import AA01
+from .AA02 import AA02
+from .AA03 import AA03
+from .AA04 import AA04
+from .AA05 import AA05
 from .topologycheck import TopologyCheck
 
 # from .ogr2ogrtabletopostgislist import Ogr2OgrTableToPostGisList
@@ -225,7 +266,48 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
             VectorProject(),
             LicenseMake(),
             TopologyCheck(),
-            A03()
+            A00(),
+            A01(),
+            A02(),
+            A03(),
+            A04(),
+            A05(),
+            P00(),
+            P01(),
+            L00(),
+            L01(),
+            L02(),
+            L03(),
+            L04(),
+            L05(),
+            L06(),
+            L07(),
+            L08(),
+            L09(),
+            L10(),
+            PP01(),
+            PP02(),
+            PL01(),
+            PL02(),
+            PA01(),
+            PA02(),
+            PA03(),
+            LP01(),
+            LL01(),
+            LL02(),
+            LL03(),
+            LL04(),
+            LA01(),
+            LA02(),
+            LA03(),
+            AP01(),
+            AP02(),
+            AL01(),
+            AA01(),
+            AA02(),
+            AA03(),
+            AA04(),
+            AA05()
             # Ogr2OgrTableToPostGisList(),
         ]
 

+ 189 - 0
processing/algs/gdal/L00.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L00.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L00(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "L00"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 189 - 0
processing/algs/gdal/L01.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "L01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 189 - 0
processing/algs/gdal/L02.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L02.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L02(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "L02"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 189 - 0
processing/algs/gdal/L03.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L03.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L03(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "L03"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 189 - 0
processing/algs/gdal/L04.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L04.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L04(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "L04"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 189 - 0
processing/algs/gdal/L05.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L05.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L05(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "L05"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 198 - 0
processing/algs/gdal/L06.py

@@ -0,0 +1,198 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L06.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext, QgsProcessingParameterNumber
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.system import isWindows
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L06(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    tolerance = "tolerance"
+    TOPOLOGYTYPE = "L06"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        # 创建一个参数,提示用户输入一个小数值
+        self.addParameter(QgsProcessingParameterNumber(self.tolerance,
+                                                       self.tr('容差'),
+                                                       QgsProcessingParameterNumber.Double
+                                                       ))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        tolerance = self.parameterAsDouble(parameters, self.tolerance, context)  # 输出的 SHP 文件路径
+        self.TOPOLOGYPARAMS["tolerance"] = str(tolerance)
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 189 - 0
processing/algs/gdal/L07.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L07.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L07(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "L07"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 189 - 0
processing/algs/gdal/L08.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L08.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L08(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "L08"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 189 - 0
processing/algs/gdal/L09.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L09.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L09(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "L09"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 198 - 0
processing/algs/gdal/L10.py

@@ -0,0 +1,198 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    L10.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext, QgsProcessingParameterNumber
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.system import isWindows
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class L10(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    tolerance = "tolerance"
+    TOPOLOGYTYPE = "L10"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        # 创建一个参数,提示用户输入一个小数值
+        self.addParameter(QgsProcessingParameterNumber(self.tolerance,
+                                                       self.tr('容差'),
+                                                       QgsProcessingParameterNumber.Double
+                                                       ))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        tolerance = self.parameterAsDouble(parameters, self.tolerance, context)  # 输出的 SHP 文件路径
+        self.TOPOLOGYPARAMS["tolerance"] = str(tolerance)
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/LA01.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    LA01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class LA01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "LA01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/LA02.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    LA02.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class LA02(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "LA02"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/LA03.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    LA03.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class LA03(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "LA03"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/LL01.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    LL01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class LL01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "LL01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/LL02.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    LL02.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class LL02(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "LL02"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/LL03.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    LL03.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class LL03(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "LL03"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/LL04.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    LL04.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class LL04(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "LL04"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/LP01.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    LP01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class LP01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "LP01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 189 - 0
processing/algs/gdal/P00.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    P00.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class P00(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "P00"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 189 - 0
processing/algs/gdal/P01.py

@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    P01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class P01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "P01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "outtable": f"{out_table}_{uid}",
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/PA01.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    PA01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class PA01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "PA01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/PA02.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    PA02.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class PA02(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "PA02"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/PA03.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    PA03.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+import sqlite3
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class PA03(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "PA03"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPolygon]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/PL01.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    PL01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class PL01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "PL01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/PL02.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    PL02.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class PL02(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "PL02"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorLine]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/PP01.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    PP01.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class PP01(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "PP01"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 208 - 0
processing/algs/gdal/PP02.py

@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    PP02.py
+    ---------------------
+    Date                 : November 2012
+    Copyright            : (C) 2012 by Victor Olaya
+    Email                : volayaf at gmail dot com
+***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************
+"""
+
+__author__ = 'wanger'
+__date__ = 'November 2024'
+__copyright__ = '(C) 2024, wanger'
+
+import os
+
+from PyQt5.QtSql import QSqlDatabase, QSqlQuery
+from osgeo import ogr, gdal
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QApplication
+from future.moves import sys
+
+from qgis.PyQt import QtWidgets
+from qgis._core import QgsProcessingParameterVectorDestination, QgsVectorLayer, QgsVectorFileWriter, \
+    QgsCoordinateTransformContext
+from qgis.core import (QgsProcessing,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterEnum,
+                       QgsProcessingParameterCrs,
+                       QgsProcessingParameterField,
+                       QgsProcessingParameterExtent,
+                       QgsProcessingParameterBoolean,
+                       QgsProcessingParameterProviderConnection,
+                       QgsProcessingParameterDatabaseSchema,
+                       QgsProcessingParameterDatabaseTable,
+                       QgsProviderRegistry,
+                       QgsProcessingException,
+                       QgsProcessingParameterDefinition,
+                       QgsProviderConnectionException,
+                       QgsDataSourceUri)
+
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+from processing.tools.PrintUtils import printStr
+from processing.tools.StringUtils import (getConnectionStr, getNow)
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.StringUtils import getUUID
+from processing.tools.FileUtils import getParentFolderPath
+from processing.tools.topology.read import (getTopoCheckSQL, getTopoCheckDescription, getTopoCheckNote)
+from processing.tools.SpatiaLite.SpatiaLite import SpatiaLiteUtils
+import sqlite3
+
+pluginPath = os.path.normpath(os.path.join(
+    os.path.split(os.path.dirname(__file__))[0], os.pardir))
+gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
+gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
+
+
+class PP02(GdalAlgorithm):
+    INPUTVECTOR = "INPUTVECTOR"
+    INPUTTARGETVECTOR = "INPUTTARGETVECTOR"
+    OUTPUTVECTOR = 'OUTPUTVECTOR'
+    TOPOLOGYTYPE = "PP02"
+    uid = getUUID()
+    in_table = "topology_in_table"
+    in_table_t = "topology_in_table_t"
+    out_table = "topology_out_table"
+    TOPOLOGYPARAMS = {
+        "intable_s": f"{in_table}_{uid}",
+        "intable_t": f"{in_table_t}_{uid}",
+        "outtable": f"{out_table}_{uid}"
+    }
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTVECTOR,
+                                                              self.tr('待检查数据'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUTTARGETVECTOR,
+                                                              self.tr('目标表'),
+                                                              types=[QgsProcessing.TypeVectorPoint]))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUTVECTOR,
+                                                                  self.tr('输出位置(矢量数据和报告)')))
+
+    def name(self):
+        return self.TOPOLOGYTYPE
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'topology.png'))
+
+    def displayName(self):
+        return self.tr(getTopoCheckNote(self.TOPOLOGYTYPE))
+
+    def shortDescription(self):
+        return self.tr(getTopoCheckDescription(self.TOPOLOGYTYPE))
+
+    def tags(self):
+        t = self.tr('import,into,postgis,database,vector').split(',')
+        t.extend(super().tags())
+        return t
+
+    def group(self):
+        return self.tr('拓扑检查')
+
+    def groupId(self):
+        return 'topology'
+
+    def topologycheck(self, parameters, context, feedback, executing=True):
+        print("拓扑检查开始啦")
+        # TODO 参数设置
+        spatialite_db_path = self.spatialite_db_path  # Spatialite 数据库路径
+        table_name = f"{self.in_table}_{self.uid}"  # 导入后的表名
+        table_t_name = f"{self.in_table_t}_{self.uid}"  # 导入后的目标表名
+        outtable_name = f"{self.out_table}_{self.uid}"  # 分析执行后的表名
+        output_vector_path = self.parameterAsOutputLayer(parameters, self.OUTPUTVECTOR, context)  # 输出的 SHP 文件路径
+        export_layer_name = outtable_name
+        # TODO 将 vectorlayer导入到Spatialite
+        input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
+        if not input_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_layer, table_name=table_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        input_target_layer = self.parameterAsVectorLayer(parameters, self.INPUTTARGETVECTOR, context)
+        if not input_target_layer.isValid():
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据不可用。"
+            }
+        result = self.importLayerToSpatiaLite(layer=input_target_layer, table_name=table_t_name)
+        if result[0] != QgsVectorFileWriter.NoError:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"图层数据导出到SpatiaLite数据库失败。"
+            }
+        print(f"file imported to Spatialite as table: {table_name}")
+        dbutils = SpatiaLiteUtils(spatialite_db_path)
+        # TODO SQL语句
+        sql = getTopoCheckSQL(self.TOPOLOGYTYPE, self.TOPOLOGYPARAMS)
+        try:
+            dbutils.executescript(f"{sql}")
+        except sqlite3.Error as e:
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": f"SpatiaLite数据库执行SQL语句失败: {e}"
+            }
+        # TODO 获取结果集条目
+        feature_count = dbutils.queryCount(outtable_name)
+        if feature_count == 0:
+            dbutils.resetDb()
+            dbutils.closeDb()
+            return self.topologySuccessWithNone()
+        # TODO 将数据导出为本地矢量文件
+        processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
+                                         "ogr")
+        path = getParentFolderPath(output_vector_path)
+        csv_path = f"{path}\\report.csv"
+        if not processed_layer.isValid():
+            dbutils.closeDb()
+            return {
+                "状态": "拓扑检查失败",
+                "错误信息": "拓扑检查结果图层加载失败。"
+            }
+        else:
+            self.vectorLayerExport(layer=processed_layer, type="CSV", path=csv_path)
+        self.vectorLayerExportToVector(layer=processed_layer, path=output_vector_path)
+        os.startfile(path)
+        dbutils.resetDb()
+        dbutils.closeDb()
+        return self.topologySuccess(count=feature_count, reportpath=csv_path)
+
+    # 判断数据是否为字符串
+    def is_string(self, var):
+        return isinstance(var, str)
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        return []
+
+    def contains_keys(self, obj, keys):
+        if isinstance(obj, dict):
+            return all(key in obj.keys() for key in keys)
+        elif hasattr(type(obj), '__dict__'):
+            return all(key in obj.__dict__ for key in keys)
+        else:
+            raise ValueError("Invalid object type")
+
+    def commandName(self):
+        return "ogr2ogr"

+ 2 - 2
processing/algs/gdal/topologycheck.py

@@ -124,7 +124,7 @@ class TopologyCheck(GdalAlgorithm):
         # TODO 将 vectorlayer导入到Spatialite
         input_layer = self.parameterAsVectorLayer(parameters, self.INPUTVECTOR, context)
         if not input_layer.isValid():
-            print("Failed to load SHP file.")
+            print("图层数据不可用。")
         crs = input_layer.crs().authid()
 
         # TODO 构造连接到Spatialite数据库的URI
@@ -165,7 +165,7 @@ class TopologyCheck(GdalAlgorithm):
         processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer",
                                          "ogr")
         if not processed_layer.isValid():
-            print("Failed to load processed layer.")
+            print("拓扑检查结果图层加载失败。")
 
         # TODO 导出矢量文件参数配置
         export_options = QgsVectorFileWriter.SaveVectorOptions()

+ 39 - 35
processing/gui/Postprocessing.py

@@ -19,6 +19,7 @@ __author__ = 'Victor Olaya'
 __date__ = 'August 2012'
 __copyright__ = '(C) 2012, Victor Olaya'
 
+import os
 import traceback
 from typing import (
     Dict,
@@ -44,7 +45,6 @@ from qgis.core import (
 from processing.core.ProcessingConfig import ProcessingConfig
 from processing.gui.RenderingStyles import RenderingStyles
 
-
 SORT_ORDER_CUSTOM_PROPERTY = '_processing_sort_order'
 
 
@@ -212,42 +212,46 @@ def handleAlgorithmResults(alg: QgsProcessingAlgorithm,
             )
 
         try:
-            layer = QgsProcessingUtils.mapLayerFromString(
-                dest_id,
-                context,
-                typeHint=details.layerTypeHint
-            )
-            if layer is not None:
-                details.setOutputLayerName(layer)
-
-                output_name = determine_output_name(
-                    dest_id, details, alg, context, parameters
+            print(f"开始加载输出图层位置:{dest_id}")
+            if os.path.exists(dest_id) and os.path.isfile(dest_id):
+                layer = QgsProcessingUtils.mapLayerFromString(
+                    dest_id,
+                    context,
+                    typeHint=details.layerTypeHint
                 )
-                post_process_layer(output_name, layer, alg)
-
-                # Load layer to layer tree root or to a specific group
-                results_group = get_layer_tree_results_group(details, context)
-
-                # note here that we may not retrieve an owned layer -- eg if the
-                # output layer already exists in the destination project
-                owned_map_layer = context.temporaryLayerStore().takeMapLayer(layer)
-                if owned_map_layer:
-                    details.project.addMapLayer(owned_map_layer, False)
-
-                    # we don't add the layer to the tree yet -- that's done
-                    # later, after we've sorted all added layers
-                    layer_tree_layer = create_layer_tree_layer(owned_map_layer, details)
-                    added_layers.append((results_group, layer_tree_layer))
-
-                if details.postProcessor():
-                    # we defer calling the postProcessor set in the context
-                    # until the layer has been added to the project's layer
-                    # tree, just in case the postProcessor contains logic
-                    # relating to layer tree handling
-                    layers_to_post_process.append((layer, details))
-
+                if layer is not None:
+                    details.setOutputLayerName(layer)
+
+                    output_name = determine_output_name(
+                        dest_id, details, alg, context, parameters
+                    )
+                    post_process_layer(output_name, layer, alg)
+
+                    # Load layer to layer tree root or to a specific group
+                    results_group = get_layer_tree_results_group(details, context)
+
+                    # note here that we may not retrieve an owned layer -- eg if the
+                    # output layer already exists in the destination project
+                    owned_map_layer = context.temporaryLayerStore().takeMapLayer(layer)
+                    if owned_map_layer:
+                        details.project.addMapLayer(owned_map_layer, False)
+
+                        # we don't add the layer to the tree yet -- that's done
+                        # later, after we've sorted all added layers
+                        layer_tree_layer = create_layer_tree_layer(owned_map_layer, details)
+                        added_layers.append((results_group, layer_tree_layer))
+
+                    if details.postProcessor():
+                        # we defer calling the postProcessor set in the context
+                        # until the layer has been added to the project's layer
+                        # tree, just in case the postProcessor contains logic
+                        # relating to layer tree handling
+                        layers_to_post_process.append((layer, details))
+
+                else:
+                    wrong_layers.append(str(dest_id))
             else:
-                wrong_layers.append(str(dest_id))
+                print(f"输出图层位置不存在:{dest_id}")
         except Exception:
             QgsMessageLog.logMessage(
                 QCoreApplication.translate(

+ 78 - 0
processing/tools/SpatiaLite/SpatiaLite.py

@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+
+__author__ = 'wanger'
+__date__ = '2024-08-27'
+__copyright__ = '(C) 2024 by siwei'
+__revision__ = '1.0'
+
+import sqlite3
+
+
+class SpatiaLiteUtils:
+    def __init__(
+            self,
+            dbpath: str
+    ):
+        self.dbpath = dbpath
+        # 连接到数据库
+        self.conn = sqlite3.connect(dbpath)
+        self.cursor = self.conn.cursor()
+        self.conn.enable_load_extension(True)
+        self.conn.execute("PRAGMA synchronous = OFF")
+        self.conn.execute("PRAGMA cache_size = -20000")  # In KB
+        self.conn.execute("PRAGMA temp_store = MEMORY")
+        self.conn.execute("SELECT load_extension('mod_spatialite');")
+        print("mod_spatialite loaded successfully.")
+
+    def execute(self, sql):
+        self.cursor.execute(sql)
+        rows = self.cursor.fetchall()
+        return rows
+
+    def executescript(self,sql):
+        self.cursor.executescript(sql)
+        print(f"Script executed successfully.{sql}")
+
+    def enable_load_extension(self, bool):
+        self.conn.enable_load_extension(bool)
+
+    def queryCount(self, tablename):
+        self.cursor.execute(f"SELECT count(1) FROM {tablename};")
+        rows = self.cursor.fetchall()
+        return rows[0][0]
+
+    #重置数据库
+    def resetDb(self):
+        # 获取所有表名,排除系统表
+        self.cursor.execute("""-- 删除所有表
+        select 'drop table if exists ' || name || ';' 
+        from sqlite_master 
+        where type='table' and name not like 'sqlite_%' and name like '%topology%'
+        
+        union all 
+        -- 删除所有索引
+        select 'drop index if exists ' || name || ';'
+        from sqlite_master
+        where type='index' and name like '%topology%'
+        
+        union all 
+        -- 删除所有视图
+        select 'drop view if exists ' || name || ';'
+        from sqlite_master
+        where type='view' and name like '%temp%'
+        
+        union all 
+        -- 删除所有触发器
+        select 'drop trigger if exists ' || name || ';'
+        from sqlite_master
+        where type='trigger' and name like '%topology%';""")
+        tables = self.cursor.fetchall()
+        # 循环删除每个表
+        for sql in tables:
+            self.cursor.execute(sql[0])
+        # 提交更改并关闭连接
+        self.conn.commit()
+
+    def closeDb(self):
+        self.cursor.close()
+        self.conn.close()

二進制
processing/tools/symbology-style.db


+ 19 - 8
processing/tools/topology/read.py

@@ -1,3 +1,5 @@
+import os
+
 import yaml
 
 topoCheckData = None
@@ -10,11 +12,17 @@ def read_yaml_file(filepath):
     return data
 
 
-# 调用示例
-topoCheckData = read_yaml_file(
-    "D:\\Program Files\\QGIS 3.34.9\\apps\\qgis-ltr\\python\\plugins\\processing\\tools\\topology\\topoCheck.yaml")
-print(topoCheckData)
-print(topoCheckData["topoCheck"]["A03"])
+current_file_path = os.path.abspath(__file__)
+# 获取当前脚本所在的目录
+current_dir = os.path.dirname(current_file_path)
+topoCheckData = read_yaml_file(f"{current_dir}\\topoCheck.yaml")
+# print(topoCheckData)
+# print(topoCheckData["topoCheck"]["A03"])
+# tempdata = topoCheckData["topoCheck"]
+# print(f"标识码  名称  说明")
+# for attr in tempdata:
+#     print(
+#         f"{attr}  {tempdata[attr]['note']}  {tempdata[attr]['UI']['description'].replace('说明: ', '').replace('说明:', '').replace('<br/>', '')}")
 
 
 def getTopoCheckSQL(type, my_dict):
@@ -25,21 +33,24 @@ def getTopoCheckSQL(type, my_dict):
         value = my_dict[key]
         k = f"@{key}@"
         tempSql = tempSql.replace(k, value)
+    print(tempSql)
     return tempSql
 
-#获取description
+
+# 获取description
 def getTopoCheckDescription(type):
     # sqllist = []
     data = topoCheckData["topoCheck"][type]
     description = data["UI"]["description"]
     return description
 
-#获取note
+
+# 获取note
 def getTopoCheckNote(type):
     # sqllist = []
     data = topoCheckData["topoCheck"][type]
     note = data["note"]
-    return note
+    return f"{type}:{note}"
 
 # my_dict = {
 #     "intable_s": "topology_table",

文件差異過大導致無法顯示
+ 488 - 515
processing/tools/topology/topoCheck.yaml


+ 2 - 2
processing/tools/topology/topology.py

@@ -21,7 +21,7 @@ export_layer_name = table_name
 # 加载 SHP 文件
 shp_layer = QgsVectorLayer(shp_file_path, "shp_layer", "ogr")
 if not shp_layer.isValid():
-    print("Failed to load SHP file.")
+    print("图层数据不可用。")
     exit()
 
 # 获取 SHP 文件的 CRS(坐标参考系)
@@ -68,7 +68,7 @@ print("SQL execution completed.")
 # 加载处理后的表
 processed_layer = QgsVectorLayer(f"{spatialite_db_path}|layername={export_layer_name}", "processed_layer", "ogr")
 if not processed_layer.isValid():
-    print("Failed to load processed layer.")
+    print("拓扑检查结果图层加载失败。")
     exit()
 
 # 导出为 SHP 文件

部分文件因文件數量過多而無法顯示