Gogs hace 2 semanas
padre
commit
3b58377429

+ 1 - 1
encrypt/siwei_config.json

@@ -8,7 +8,7 @@
     "schema_base": "base",
     "user": "postgres",
     "password": "postgis",
-    "name": "real3d"
+    "name": "datamanager"
   },
   "redis": {
     "host": "192.168.60.2",

+ 189 - 249
processing/algs/gdal/GdalAlgorithmProvider.py

@@ -20,133 +20,15 @@ __date__ = 'August 2012'
 __copyright__ = '(C) 2012, Victor Olaya'
 
 import os
+import importlib
 
 from PyQt5.QtGui import QIcon
-from osgeo import gdal
 from processing.core.ProcessingConfig import ProcessingConfig, Setting
 from qgis.PyQt.QtCore import QCoreApplication
 from qgis.core import (QgsApplication,
                        QgsProcessingProvider,
                        QgsRuntimeProfiler)
 
-from .AssignProjection import AssignProjection
-from .Buffer import Buffer
-from .ClipRasterByExtent import ClipRasterByExtent
-from .ClipRasterByMask import ClipRasterByMask
-from .ClipVectorByExtent import ClipVectorByExtent
-from .ClipVectorByMask import ClipVectorByMask
-from .ColorRelief import ColorRelief
-from .Datasources2Vrt import Datasources2Vrt
-from .Dissolve import Dissolve
-from .ExecuteSql import ExecuteSql
-from .ExportRasterByMask import ExportRasterByMask
-from .ExportVectorByMask import ExportVectorByMask
-from .GdalUtils import GdalUtils
-from .GridAverage import GridAverage
-from .GridDataMetrics import GridDataMetrics
-from .GridInverseDistance import GridInverseDistance
-from .GridInverseDistanceNearestNeighbor import GridInverseDistanceNearestNeighbor
-from .GridLinear import GridLinear
-from .GridNearestNeighbor import GridNearestNeighbor
-from .LicenseMake import LicenseMake
-from .OffsetCurve import OffsetCurve
-from .OgrToPostGis import OgrToPostGis
-from .OneSideBuffer import OneSideBuffer
-# from .spotfileupload import SpotfileUpload
-# from .spotfiledownload import SpotfileDownload
-# from .spotfiledelete import SpotfileDelete
-from .PointsAlongLines import PointsAlongLines
-from .Topology.A00 import A00
-from .Topology.A01 import A01
-from .Topology.A02 import A02
-from .Topology.A03 import A03
-from .Topology.A04 import A04
-from .Topology.A05 import A05
-from .Topology.AA01 import AA01
-from .Topology.AA02 import AA02
-from .Topology.AA03 import AA03
-from .Topology.AA04 import AA04
-from .Topology.AA05 import AA05
-from .Topology.AL01 import AL01
-from .Topology.AP01 import AP01
-from .Topology.AP02 import AP02
-from .Topology.L00 import L00
-from .Topology.L01 import L01
-from .Topology.L02 import L02
-from .Topology.L03 import L03
-from .Topology.L04 import L04
-from .Topology.L05 import L05
-from .Topology.L06 import L06
-from .Topology.L07 import L07
-from .Topology.L08 import L08
-from .Topology.L09 import L09
-from .Topology.L10 import L10
-from .Topology.LA01 import LA01
-from .Topology.LA02 import LA02
-from .Topology.LA03 import LA03
-from .Topology.LL01 import LL01
-from .Topology.LL02 import LL02
-from .Topology.LL03 import LL03
-from .Topology.LL04 import LL04
-from .Topology.LP01 import LP01
-from .Topology.P00 import P00
-from .Topology.P01 import P01
-from .Topology.PA01 import PA01
-from .Topology.PA02 import PA02
-from .Topology.PA03 import PA03
-from .Topology.PL01 import PL01
-from .Topology.PL02 import PL02
-from .Topology.PP01 import PP01
-from .Topology.PP02 import PP02
-from .VectorProject import VectorProject
-from .aspect import aspect
-from .buildvrt import buildvrt
-from .contour import contour, contour_polygon
-from .extractprojection import ExtractProjection
-from .fillnodata import fillnodata
-from .gdal2tiles import gdal2tiles
-from .gdal2xyz import gdal2xyz
-from .gdaladdo import gdaladdo
-from .gdalcalc import gdalcalc
-from .gdalinfo import gdalinfo
-from .gdaltindex import gdaltindex
-from .gdbtopostgislist import GdbToPostGisList
-from .hillshade import hillshade
-from .merge import merge
-from .nearblack import nearblack
-from .ogr2ogr import ogr2ogr
-from .ogr2ogrtopostgislist import Ogr2OgrToPostGisList
-from .ogrinfo import ogrinfo
-from .pansharp import pansharp
-from .pct2rgb import pct2rgb
-from .polygonize import polygonize
-from .postgisrestore import Postgisrestore
-from .postgistogeoserver import Postgistogeoserver
-from .postgisupdate import Postgisupdate
-from .proximity import proximity
-from .rasterize import rasterize
-from .rasterize_over import rasterize_over
-from .rasterize_over_fixed_value import rasterize_over_fixed_value
-from .rastertopostgislist import Ogr2PostGisList
-from .ImportOSGBToPostGIS import ImportOSGBToPostGIS
-from .ImportTableToPostGIS import ImportTableToPostGIS
-from .ImportSingleOSGBToPostGIS import ImportSingleOSGBToPostGIS
-from .DataStorageStatistics import DataStorageStatistics
-
-from .rearrange_bands import rearrange_bands
-from .retile import retile
-from .rgb2pct import rgb2pct
-from .roughness import roughness
-from .sieve import sieve
-from .slope import slope
-from .tpi import tpi
-from .translate import translate
-from .tri import tri
-from .viewshed import viewshed
-from .warp import warp
-
-# from .ogr2ogrtabletopostgislist import Ogr2OgrTableToPostGisList
-
 pluginPath = os.path.normpath(os.path.join(
     os.path.split(os.path.dirname(__file__))[0], os.pardir))
 
@@ -156,6 +38,7 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
     def __init__(self):
         super().__init__()
         self.algs = []
+        self._algorithm_definitions = None
         QgsApplication.processingRegistry().addAlgorithmAlias('qgis:buildvirtualvector', 'gdal:buildvirtualvector')
 
     def load(self):
@@ -180,7 +63,12 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
         return '数管工具集'
 
     def longName(self):
-        version = GdalUtils.readableVersion()
+        # 延迟导入GdalUtils,只在需要时才加载
+        try:
+            from .GdalUtils import GdalUtils
+            version = GdalUtils.readableVersion()
+        except ImportError:
+            version = 'Unknown'
         return f'数管工具集 ({version})'
 
     def id(self):
@@ -191,141 +79,193 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
 
     def icon(self):
         return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'tools.png'))
-        # return QgsApplication.getThemeIcon("/providerGdal.svg")
 
     def svgIconPath(self):
         return os.path.join(pluginPath, 'images', 'dbms', 'tools.png')
-        # return QgsApplication.iconPath("providerGdal.svg")
+
+    def _get_algorithm_definitions(self):
+        """获取算法定义列表,使用延迟加载"""
+        if self._algorithm_definitions is None:
+            self._algorithm_definitions = [
+                # GDAL Raster Tools
+                ('AssignProjection', '.AssignProjection'),
+                ('aspect', '.aspect'),
+                ('buildvrt', '.buildvrt'),
+                ('ClipRasterByExtent', '.ClipRasterByExtent'),
+                ('ClipRasterByMask', '.ClipRasterByMask'),
+                ('ColorRelief', '.ColorRelief'),
+                ('contour', '.contour'),
+                ('contour_polygon', '.contour'),
+                ('Datasources2Vrt', '.Datasources2Vrt'),
+                ('fillnodata', '.fillnodata'),
+                ('gdalinfo', '.gdalinfo'),
+                ('gdal2tiles', '.gdal2tiles'),
+                ('gdal2xyz', '.gdal2xyz'),
+                ('gdaladdo', '.gdaladdo'),
+                ('gdalcalc', '.gdalcalc'),
+                ('gdaltindex', '.gdaltindex'),
+                ('GridAverage', '.GridAverage'),
+                ('GridDataMetrics', '.GridDataMetrics'),
+                ('GridInverseDistance', '.GridInverseDistance'),
+                ('GridInverseDistanceNearestNeighbor', '.GridInverseDistanceNearestNeighbor'),
+                ('GridLinear', '.GridLinear'),
+                ('GridNearestNeighbor', '.GridNearestNeighbor'),
+                ('hillshade', '.hillshade'),
+                ('merge', '.merge'),
+                ('nearblack', '.nearblack'),
+                ('pct2rgb', '.pct2rgb'),
+                ('polygonize', '.polygonize'),
+                ('proximity', '.proximity'),
+                ('rasterize', '.rasterize'),
+                ('rearrange_bands', '.rearrange_bands'),
+                ('retile', '.retile'),
+                ('rgb2pct', '.rgb2pct'),
+                ('roughness', '.roughness'),
+                ('sieve', '.sieve'),
+                ('slope', '.slope'),
+                ('translate', '.translate'),
+                ('tpi', '.tpi'),
+                ('tri', '.tri'),
+                ('warp', '.warp'),
+                ('pansharp', '.pansharp'),
+                ('ExtractProjection', '.extractprojection'),
+                ('rasterize_over', '.rasterize_over'),
+                ('rasterize_over_fixed_value', '.rasterize_over_fixed_value'),
+
+                # OGR Vector Tools
+                ('Buffer', '.Buffer'),
+                ('ClipVectorByExtent', '.ClipVectorByExtent'),
+                ('ClipVectorByMask', '.ClipVectorByMask'),
+                ('Dissolve', '.Dissolve'),
+                ('ExecuteSql', '.ExecuteSql'),
+                ('OffsetCurve', '.OffsetCurve'),
+                ('ogr2ogr', '.ogr2ogr'),
+                ('ogrinfo', '.ogrinfo'),
+                ('OneSideBuffer', '.OneSideBuffer'),
+                ('PointsAlongLines', '.PointsAlongLines'),
+                ('VectorProject', '.VectorProject'),
+
+                # PostGIS Tools
+                ('OgrToPostGis', '.OgrToPostGis'),
+                ('Ogr2OgrToPostGisList', '.ogr2ogrtopostgislist'),
+                ('Ogr2PostGisList', '.rastertopostgislist'),
+                ('Postgisupdate', '.postgisupdate'),
+                ('Postgisrestore', '.postgisrestore'),
+                ('Postgistogeoserver', '.postgistogeoserver'),
+                ('ImportOSGBToPostGIS', '.ImportOSGBToPostGIS'),
+                ('ImportTableToPostGIS', '.ImportTableToPostGIS'),
+                ('ImportSingleOSGBToPostGIS', '.ImportSingleOSGBToPostGIS'),
+                ('DataStorageStatistics', '.DataStorageStatistics'),
+                ('GdbToPostGisList', '.gdbtopostgislist'),
+
+                # Export Tools
+                ('ExportVectorByMask', '.ExportVectorByMask'),
+                ('ExportRasterByMask', '.ExportRasterByMask'),
+
+                # Other Tools
+                ('LicenseMake', '.LicenseMake'),
+
+                # Topology Tools
+                ('A00', '.Topology.A00'),
+                ('A01', '.Topology.A01'),
+                ('A02', '.Topology.A02'),
+                ('A03', '.Topology.A03'),
+                ('A04', '.Topology.A04'),
+                ('A05', '.Topology.A05'),
+                ('P00', '.Topology.P00'),
+                ('P01', '.Topology.P01'),
+                ('L00', '.Topology.L00'),
+                ('L01', '.Topology.L01'),
+                ('L02', '.Topology.L02'),
+                ('L03', '.Topology.L03'),
+                ('L04', '.Topology.L04'),
+                ('L05', '.Topology.L05'),
+                ('L06', '.Topology.L06'),
+                ('L07', '.Topology.L07'),
+                ('L08', '.Topology.L08'),
+                ('L09', '.Topology.L09'),
+                ('L10', '.Topology.L10'),
+                ('PP01', '.Topology.PP01'),
+                ('PP02', '.Topology.PP02'),
+                ('PL01', '.Topology.PL01'),
+                ('PL02', '.Topology.PL02'),
+                ('PA01', '.Topology.PA01'),
+                ('PA02', '.Topology.PA02'),
+                ('PA03', '.Topology.PA03'),
+                ('LP01', '.Topology.LP01'),
+                ('LL01', '.Topology.LL01'),
+                ('LL02', '.Topology.LL02'),
+                ('LL03', '.Topology.LL03'),
+                ('LL04', '.Topology.LL04'),
+                ('LA01', '.Topology.LA01'),
+                ('LA02', '.Topology.LA02'),
+                ('LA03', '.Topology.LA03'),
+                ('AP01', '.Topology.AP01'),
+                ('AP02', '.Topology.AP02'),
+                ('AL01', '.Topology.AL01'),
+                ('AA01', '.Topology.AA01'),
+                ('AA02', '.Topology.AA02'),
+                ('AA03', '.Topology.AA03'),
+                ('AA04', '.Topology.AA04'),
+                ('AA05', '.Topology.AA05'),
+            ]
+
+        return self._algorithm_definitions
+
+    def _load_algorithm_class(self, class_name, module_path):
+        """延迟加载算法类"""
+        try:
+            module = importlib.import_module(module_path, package=__package__)
+            return getattr(module, class_name)
+        except (ImportError, AttributeError) as e:
+            print(f"Warning: Could not load algorithm {class_name} from {module_path}: {e}")
+            return None
+
+    def _load_viewshed_if_supported(self):
+        """检查GDAL版本并加载viewshed算法"""
+        try:
+            from osgeo import gdal
+            if int(gdal.VersionInfo()) > 3010000:
+                viewshed_class = self._load_algorithm_class('viewshed', '.viewshed')
+                if viewshed_class:
+                    return viewshed_class()
+        except Exception as e:
+            print(f"Warning: Could not check GDAL version or load viewshed: {e}")
+        return None
 
     def loadAlgorithms(self):
-        self.algs = [
-            AssignProjection(),
-            aspect(),
-            buildvrt(),
-            ClipRasterByExtent(),
-            ClipRasterByMask(),
-            ColorRelief(),
-            contour(),
-            contour_polygon(),
-            Datasources2Vrt(),
-            fillnodata(),
-            gdalinfo(),
-            gdal2tiles(),
-            gdal2xyz(),
-            gdaladdo(),
-            gdalcalc(),
-            gdaltindex(),
-            GridAverage(),
-            GridDataMetrics(),
-            GridInverseDistance(),
-            GridInverseDistanceNearestNeighbor(),
-            GridLinear(),
-            GridNearestNeighbor(),
-            hillshade(),
-            ImportOSGBToPostGIS(),
-            ImportTableToPostGIS(),
-            ImportSingleOSGBToPostGIS(),
-            DataStorageStatistics(),
-            merge(),
-            nearblack(),
-            pct2rgb(),
-            polygonize(),
-            proximity(),
-            rasterize(),
-            rearrange_bands(),
-            retile(),
-            rgb2pct(),
-            roughness(),
-            sieve(),
-            slope(),
-            translate(),
-            tpi(),
-            tri(),
-            warp(),
-            pansharp(),
-            # rasterize(),
-            ExtractProjection(),
-            rasterize_over(),
-            rasterize_over_fixed_value(),
-            # ----- OGR tools -----
-            Buffer(),
-            ClipVectorByExtent(),
-            ClipVectorByMask(),
-            Dissolve(),
-            ExecuteSql(),
-            OffsetCurve(),
-            ogr2ogr(),
-            ogrinfo(),
-            OgrToPostGis(),
-            Ogr2OgrToPostGisList(),
-            Ogr2PostGisList(),
-            OneSideBuffer(),
-            PointsAlongLines(),
-            Postgisupdate(),
-            Postgisrestore(),
-            Postgistogeoserver(),
-            # SpotfileUpload(),
-            # SpotfileDownload(),
-            # SpotfileDelete(),
-            ExportVectorByMask(),
-            GdbToPostGisList(),
-            ExportRasterByMask(),
-            VectorProject(),
-            LicenseMake(),
-            # TopologyCheck(),
-            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(),
-        ]
-
-        if int(gdal.VersionInfo()) > 3010000:
-            self.algs.append(viewshed())
-
-        for a in self.algs:
-            self.addAlgorithm(a)
+        """使用延迟加载方式加载算法"""
+        self.algs = []
+
+        # 获取算法定义
+        algorithm_definitions = self._get_algorithm_definitions()
+
+        # 延迟加载每个算法
+        for class_name, module_path in algorithm_definitions:
+            algorithm_class = self._load_algorithm_class(class_name, module_path)
+            if algorithm_class:
+                try:
+                    algorithm_instance = algorithm_class()
+                    self.algs.append(algorithm_instance)
+                except Exception as e:
+                    print(f"Warning: Could not instantiate algorithm {class_name}: {e}")
+
+        # 检查并加载viewshed算法(需要GDAL版本检查)
+        viewshed_instance = self._load_viewshed_if_supported()
+        if viewshed_instance:
+            self.algs.append(viewshed_instance)
+
+        # 将所有算法添加到提供者
+        for algorithm in self.algs:
+            self.addAlgorithm(algorithm)
 
     def supportedOutputRasterLayerExtensions(self):
-        return GdalUtils.getSupportedOutputRasterExtensions()
+        """延迟加载GdalUtils"""
+        try:
+            from .GdalUtils import GdalUtils
+            return GdalUtils.getSupportedOutputRasterExtensions()
+        except ImportError:
+            return []
 
     def supportsNonFileBasedOutput(self):
         """
@@ -336,4 +276,4 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
     def tr(self, string, context=''):
         if context == '':
             context = 'GdalAlgorithmProvider'
-        return QCoreApplication.translate(context, string)
+        return QCoreApplication.translate(context, string)

+ 4 - 0
processing/algs/gdal/ImportSingleOSGBToPostGIS.py

@@ -54,6 +54,10 @@ class ImportSingleOSGBToPostGIS(QgsProcessingAlgorithm):
             defaultValue=siwei_config.CONFIG['db']['host']
         ))
 
+
+
+
+
         self.addParameter(QgsProcessingParameterDatabaseSchema(
             self.SCHEMA,
             self.tr('模式'),

+ 11 - 6
processing/algs/gdal/postgisrestore.py

@@ -9,7 +9,7 @@
 ***************************************************************************
 *                                                                         *
 *   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  *
+*   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.                                   *
 *                                                                         *
@@ -52,7 +52,7 @@ from processing.tools.PrintUtils import printStr
 from processing.tools.StringUtils import getConnectionStr
 from processing.tools.GeoServer.Geoserver import Geoserver
 from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
-from processing.tools.Login.Redis import Redis
+from processing.tools.Login.StateManager import set_state, get_state
 
 from processing.tools.system import isWindows
 
@@ -94,11 +94,12 @@ class Postgisrestore(GdalAlgorithm):
         self.addParameter(QgsProcessingParameterEnum(name=self.RESTORETABLE,
                                                      description=self.tr('目标数据源'),
                                                      options=tablenames))
-        redis = Redis()
-        tablename = redis.get("curRestoreTable")
-        print(tablename)
+        
+        # 使用状态管理器替代 Redis
+        tablename = get_state("curRestoreTable")
+        print(f"当前恢复表: {tablename}")
+        
         if tablename is not None:
-            tablename = tablename.decode('utf-8')
             versions = pgconn.getTableVersions(tablename=tablename)
             curversion = pgconn.getTableCurVersion(tablename=tablename)
             tableversion_param = QgsProcessingParameterString(
@@ -149,6 +150,10 @@ class Postgisrestore(GdalAlgorithm):
         pgconn = PostgreSQL(schema='base')
         tableinfo = self.tables[parameters[self.RESTORETABLE]]
         tablename = tableinfo[1]
+        
+        # 设置当前恢复表到状态管理器
+        set_state("curRestoreTable", tablename)
+        
         # 判断回退版本关系
         curversion = parameters[self.CURVERSION]
         targetversion = self.versionlist[parameters[self.RESTOREVERSION]]

+ 192 - 0
processing/algs/gdal/postgisrestore.py.bak

@@ -0,0 +1,192 @@
+# -*- coding: utf-8 -*-
+"""
+***************************************************************************
+    postgisrestore.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  *
+*   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 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 (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
+from processing.tools.GeoServer.Geoserver import Geoserver
+from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.Login.StateManager import set_state, get_state
+
+from processing.tools.system import isWindows
+
+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 Postgisrestore(GdalAlgorithm):
+    LOGIN_USER = "admin"
+    UPDATEFILE = 'UPDATEFILE'
+    RESTORETABLE = 'RESTORETABLE'
+    RESTOREVERSION = 'RESTOREVERSION'
+    CURVERSION = "CURVERSION"
+    ALLOWOVERLAP = "ALLOWOVERLAP"
+    DATABASE = 'DATABASE'
+    INPUTFILE = 'INPUTFILE'
+    SCHEMA = 'SCHEMA'
+    TABLE = 'TABLE'
+    HOST = 'HOST'
+    DBNAME = 'DBNAME'
+    PORT = 'PORT'
+    USER = 'USER'
+    PASSWORD = 'PASSWORD'
+    selectedValue = "selectedValue"
+    tables = []
+    checklogs = []
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        pgconn = PostgreSQL(schema='base')
+        self.tables = pgconn.getManagerTables(username=self.LOGIN_USER)
+        tablenames = []
+        for row in self.tables:
+            tablenames.append(row[2])
+        self.addParameter(QgsProcessingParameterEnum(name=self.RESTORETABLE,
+                                                     description=self.tr('目标数据源'),
+                                                     options=tablenames))
+        
+        # 使用状态管理器替代 Redis
+        tablename = get_state("curRestoreTable")
+        print(f"当前恢复表: {tablename}")
+        
+        if tablename is not None:
+            versions = pgconn.getTableVersions(tablename=tablename)
+            curversion = pgconn.getTableCurVersion(tablename=tablename)
+            tableversion_param = QgsProcessingParameterString(
+                self.CURVERSION,
+                self.tr('当前版本号'), defaultValue=curversion)
+            self.addParameter(tableversion_param)
+            self.versionlist = []
+            for row in versions:
+                self.versionlist.append(row[0])
+            self.addParameter(QgsProcessingParameterEnum(name=self.RESTOREVERSION,
+                                                         description=self.tr('目标版本'),
+                                                         options=self.versionlist))
+
+        pgconn.close()
+
+    def name(self):
+        return 'postgisrestore'
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'restore.png'))
+
+    def displayName(self):
+        return self.tr('版本回退')
+
+    def shortDescription(self):
+        return self.tr('回退数据库版本')
+
+    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 'updatedata'
+
+    def setSelectedValue(self, v):
+        printStr(v)
+        self.selectedValue = v
+
+    def getSelectedValue(self):
+        return self.selectedValue
+
+    def restoreVector(self, parameters, context, feedback, executing=True):
+        print("版本回退开始啦")
+        pgconn = PostgreSQL(schema='base')
+        tableinfo = self.tables[parameters[self.RESTORETABLE]]
+        tablename = tableinfo[1]
+        
+        # 设置当前恢复表到状态管理器
+        set_state("curRestoreTable", tablename)
+        
+        # 判断回退版本关系
+        curversion = parameters[self.CURVERSION]
+        targetversion = self.versionlist[parameters[self.RESTOREVERSION]]
+        message = "版本回退成功"
+        if curversion == targetversion:
+            message = "版本相同不需要操作"
+        elif curversion > targetversion:
+            print("需要删除近期版本更新的数据")
+            pgconn.deleteVectorRecords(tablename=tablename, rksj_sw=targetversion)
+        else:
+            pgconn.insertVectorRecords(tablename=tablename, curversion=curversion, targetversion=targetversion)
+            print("需要插入近期版本更新的数据")
+        # print("===========备份表===========")
+        # pgconn.restoreBackTable(tablename=tablename)
+        pgconn.close()
+        return {
+            "状态": message
+        }
+
+    # 判断数据是否为字符串
+    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"

+ 1 - 1
processing/algs/gdal/postgistogeoserver.py

@@ -182,7 +182,7 @@ class Postgistogeoserver(GdalAlgorithm):
         # self.addParameter(self.zymlParams)
 
     def name(self):
-        return 'Dpostgistogeoserver'
+        return 'postgistogeoserver'
 
     def icon(self):
         return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'publishserver.png'))

+ 6 - 1
processing/algs/gdal/postgisupdate.py

@@ -9,7 +9,7 @@
 ***************************************************************************
 *                                                                         *
 *   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  *
+*   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.                                   *
 *                                                                         *
@@ -52,6 +52,7 @@ 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.Login.StateManager import set_state, get_state
 from processing.tools.system import isWindows
 
 pluginPath = os.path.normpath(os.path.join(
@@ -139,6 +140,10 @@ class Postgisupdate(GdalAlgorithm):
         tableinfo = self.tables[parameters[self.TARGET]]
         tablename = tableinfo[1]
         ywlx = tableinfo[3]
+        
+        # 设置当前更新表到状态管理器
+        set_state("curUpdateTable", tablename)
+        
         pgconn = PostgreSQL(schema='base')
         print("===========备份表===========")
         # pgconn.resetBackTable(tablename=tablename)

+ 211 - 0
processing/tools/Login/README_StateManager.md

@@ -0,0 +1,211 @@
+# 状态管理器使用说明
+
+## 概述
+
+`StateManager` 是一个用于替代 Redis 的状态管理解决方案,专门为 QGIS 处理算法设计。它使用文件系统和内存缓存来存储状态信息,提供了与 Redis 类似的功能,但不需要外部依赖。
+
+## 主要特性
+
+- **内存缓存**: 快速访问,提高性能
+- **文件持久化**: 数据持久存储,支持程序重启
+- **自动过期**: 支持设置数据过期时间
+- **线程安全**: 适合多线程环境
+- **无外部依赖**: 纯 Python 实现,无需安装额外软件
+
+## 基本用法
+
+### 1. 导入状态管理器
+
+```python
+from processing.tools.Login.StateManager import set_state, get_state, delete_state
+```
+
+### 2. 设置状态
+
+```python
+# 设置状态,使用默认过期时间(30分钟)
+set_state("current_table", "my_table_name")
+
+# 设置状态,指定过期时间(60秒)
+set_state("temp_data", "some_value", 60)
+```
+
+### 3. 获取状态
+
+```python
+# 获取状态
+table_name = get_state("current_table")
+if table_name:
+    print(f"当前表: {table_name}")
+else:
+    print("未找到当前表信息")
+```
+
+### 4. 删除状态
+
+```python
+# 删除特定状态
+delete_state("current_table")
+
+# 清空所有状态
+from processing.tools.Login.StateManager import clear_all_states
+clear_all_states()
+```
+
+## 在算法中的使用
+
+### PostGIS 恢复算法
+
+```python
+def restoreVector(self, parameters, context, feedback, executing=True):
+    # 设置当前恢复表
+    set_state("curRestoreTable", tablename)
+    
+    # 执行恢复逻辑...
+```
+
+### PostGIS 更新算法
+
+```python
+def updateVector(self, parameters, context, feedback, executing=True):
+    # 设置当前更新表
+    set_state("curUpdateTable", tablename)
+    
+    # 执行更新逻辑...
+```
+
+## 高级用法
+
+### 1. 使用上下文管理器
+
+```python
+from processing.tools.Login.StateManager import get_state_manager
+
+with get_state_manager() as sm:
+    sm.set("key1", "value1")
+    sm.set("key2", "value2")
+    # 自动清理过期数据
+```
+
+### 2. 检查状态是否存在
+
+```python
+from processing.tools.Login.StateManager import get_state_manager
+
+sm = get_state_manager()
+if sm.exists("my_key"):
+    print("键存在且未过期")
+```
+
+### 3. 设置过期时间
+
+```python
+from processing.tools.Login.StateManager import get_state_manager
+
+sm = get_state_manager()
+sm.expire("my_key", 120)  # 设置2分钟后过期
+```
+
+## 配置选项
+
+### 缓存目录
+
+默认情况下,状态管理器使用系统临时目录。可以通过以下方式自定义:
+
+```python
+from processing.tools.Login.StateManager import StateManager
+
+# 使用自定义目录
+sm = StateManager(cache_dir="/path/to/custom/cache")
+
+# 使用相对路径
+sm = StateManager(cache_dir="./cache")
+```
+
+### 默认过期时间
+
+默认过期时间为 30 分钟,可以在创建实例时修改:
+
+```python
+sm = StateManager()
+sm.default_expire = 60 * 60  # 设置为1小时
+```
+
+## 性能考虑
+
+- **内存缓存**: 提供最快的访问速度
+- **文件持久化**: 在程序重启后保持数据
+- **自动清理**: 定期清理过期数据,避免内存泄漏
+- **批量操作**: 支持批量获取和设置操作
+
+## 错误处理
+
+状态管理器包含完善的错误处理机制:
+
+- 文件读写失败时自动回退到内存缓存
+- 网络或权限问题时优雅降级
+- 详细的错误日志记录
+
+## 迁移指南
+
+### 从 Redis 迁移
+
+1. **替换导入语句**:
+   ```python
+   # 旧代码
+   from processing.tools.Login.Redis import Redis
+   
+   # 新代码
+   from processing.tools.Login.StateManager import set_state, get_state
+   ```
+
+2. **替换方法调用**:
+   ```python
+   # 旧代码
+   redis = Redis()
+   redis.set("key", "value")
+   value = redis.get("key")
+   
+   # 新代码
+   set_state("key", "value")
+   value = get_state("key")
+   ```
+
+3. **移除连接管理**:
+   ```python
+   # 旧代码
+   redis = Redis()
+   # ... 使用 redis
+   redis.close()
+   
+   # 新代码 - 无需手动管理连接
+   set_state("key", "value")
+   ```
+
+## 注意事项
+
+1. **数据持久性**: 文件缓存存储在临时目录中,系统重启后可能被清理
+2. **并发访问**: 支持多线程访问,但需要注意文件锁
+3. **磁盘空间**: 确保缓存目录有足够的磁盘空间
+4. **权限**: 确保程序有权限读写缓存目录
+
+## 故障排除
+
+### 常见问题
+
+1. **权限错误**: 检查缓存目录的读写权限
+2. **磁盘空间不足**: 清理缓存目录或更改存储位置
+3. **性能问题**: 检查内存使用情况,适当调整缓存策略
+
+### 调试模式
+
+启用详细日志记录:
+
+```python
+import logging
+logging.basicConfig(level=logging.DEBUG)
+```
+
+## 总结
+
+`StateManager` 提供了一个轻量级、高性能的状态管理解决方案,完全替代了 Redis 的功能。它特别适合 QGIS 处理算法的使用场景,提供了简单易用的 API 和可靠的性能表现。 

+ 239 - 0
processing/tools/Login/StateManager.py

@@ -0,0 +1,239 @@
+# -*- coding: utf-8 -*-
+
+__author__ = 'wanger'
+__date__ = '2024-11-20'
+__copyright__ = '(C) 2024 by siwei'
+__revision__ = '1.0'
+
+import os
+import json
+import time
+from typing import Optional, Any, Dict
+import tempfile
+from pathlib import Path
+
+
+class StateManager:
+    """
+    状态管理器,替代 Redis 的功能
+    使用文件系统和内存缓存来存储状态信息
+    """
+    
+    def __init__(self, cache_dir: Optional[str] = None):
+        """
+        初始化状态管理器
+        
+        Args:
+            cache_dir: 缓存目录,如果为 None 则使用系统临时目录
+        """
+        if cache_dir is None:
+            self.cache_dir = Path(tempfile.gettempdir()) / "qgis_processing_cache"
+        else:
+            self.cache_dir = Path(cache_dir)
+        
+        # 确保缓存目录存在
+        self.cache_dir.mkdir(parents=True, exist_ok=True)
+        
+        # 内存缓存,提高性能
+        self._memory_cache = {}
+        self._cache_expiry = {}
+        
+        # 默认过期时间(30分钟)
+        self.default_expire = 60 * 30
+    
+    def set(self, key: str, value: Any, expire: Optional[int] = None) -> None:
+        """
+        设置键值对
+        
+        Args:
+            key: 键名
+            value: 值
+            expire: 过期时间(秒),如果为 None 则使用默认值
+        """
+        if expire is None:
+            expire = self.default_expire
+        
+        # 存储到内存缓存
+        self._memory_cache[key] = value
+        self._cache_expiry[key] = time.time() + expire
+        
+        # 存储到文件系统(持久化)
+        cache_file = self.cache_dir / f"{key}.json"
+        try:
+            cache_data = {
+                'value': value,
+                'expire': time.time() + expire,
+                'created': time.time()
+            }
+            with open(cache_file, 'w', encoding='utf-8') as f:
+                json.dump(cache_data, f, ensure_ascii=False, indent=2)
+        except Exception as e:
+            print(f"写入缓存文件失败: {e}")
+    
+    def get(self, key: str) -> Optional[Any]:
+        """
+        获取键值
+        
+        Args:
+            key: 键名
+            
+        Returns:
+            值,如果不存在或已过期则返回 None
+        """
+        # 首先检查内存缓存
+        if key in self._memory_cache:
+            if time.time() < self._cache_expiry.get(key, 0):
+                return self._memory_cache[key]
+            else:
+                # 已过期,从内存缓存中删除
+                del self._memory_cache[key]
+                del self._cache_expiry[key]
+        
+        # 检查文件系统缓存
+        cache_file = self.cache_dir / f"{key}.json"
+        if cache_file.exists():
+            try:
+                with open(cache_file, 'r', encoding='utf-8') as f:
+                    cache_data = json.load(f)
+                
+                # 检查是否过期
+                if time.time() < cache_data.get('expire', 0):
+                    # 未过期,加载到内存缓存
+                    value = cache_data['value']
+                    self._memory_cache[key] = value
+                    self._cache_expiry[key] = cache_data['expire']
+                    return value
+                else:
+                    # 已过期,删除文件
+                    cache_file.unlink(missing_ok=True)
+            except Exception as e:
+                print(f"读取缓存文件失败: {e}")
+                cache_file.unlink(missing_ok=True)
+        
+        return None
+    
+    def delete(self, key: str) -> bool:
+        """
+        删除键值
+        
+        Args:
+            key: 键名
+            
+        Returns:
+            是否成功删除
+        """
+        # 从内存缓存中删除
+        if key in self._memory_cache:
+            del self._memory_cache[key]
+        if key in self._cache_expiry:
+            del self._cache_expiry[key]
+        
+        # 从文件系统中删除
+        cache_file = self.cache_dir / f"{key}.json"
+        try:
+            if cache_file.exists():
+                cache_file.unlink()
+                return True
+        except Exception as e:
+            print(f"删除缓存文件失败: {e}")
+        
+        return False
+    
+    def exists(self, key: str) -> bool:
+        """
+        检查键是否存在且未过期
+        
+        Args:
+            key: 键名
+            
+        Returns:
+            是否存在
+        """
+        return self.get(key) is not None
+    
+    def expire(self, key: str, seconds: int) -> bool:
+        """
+        设置键的过期时间
+        
+        Args:
+            key: 键名
+            seconds: 过期时间(秒)
+            
+        Returns:
+            是否成功设置
+        """
+        value = self.get(key)
+        if value is not None:
+            self.set(key, value, seconds)
+            return True
+        return False
+    
+    def clear(self) -> None:
+        """清空所有缓存"""
+        # 清空内存缓存
+        self._memory_cache.clear()
+        self._cache_expiry.clear()
+        
+        # 清空文件系统缓存
+        try:
+            for cache_file in self.cache_dir.glob("*.json"):
+                cache_file.unlink()
+        except Exception as e:
+            print(f"清空缓存文件失败: {e}")
+    
+    def get_all_keys(self) -> list:
+        """获取所有键名"""
+        keys = []
+        try:
+            for cache_file in self.cache_dir.glob("*.json"):
+                key = cache_file.stem
+                if self.exists(key):
+                    keys.append(key)
+        except Exception as e:
+            print(f"获取键名列表失败: {e}")
+        
+        return keys
+    
+    def close(self) -> None:
+        """关闭状态管理器"""
+        # 清理过期的内存缓存
+        current_time = time.time()
+        expired_keys = [key for key, expiry in self._cache_expiry.items() 
+                       if current_time >= expiry]
+        
+        for key in expired_keys:
+            del self._memory_cache[key]
+            del self._cache_expiry[key]
+    
+    def __enter__(self):
+        return self
+    
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self.close()
+
+
+# 全局状态管理器实例
+_global_state_manager = None
+
+def get_state_manager() -> StateManager:
+    """获取全局状态管理器实例"""
+    global _global_state_manager
+    if _global_state_manager is None:
+        _global_state_manager = StateManager()
+    return _global_state_manager
+
+def set_state(key: str, value: Any, expire: Optional[int] = None) -> None:
+    """设置全局状态"""
+    get_state_manager().set(key, value, expire)
+
+def get_state(key: str) -> Optional[Any]:
+    """获取全局状态"""
+    return get_state_manager().get(key)
+
+def delete_state(key: str) -> bool:
+    """删除全局状态"""
+    return get_state_manager().delete(key)
+
+def clear_all_states() -> None:
+    """清空所有全局状态"""
+    get_state_manager().clear()