Gogs 2 nedēļas atpakaļ
vecāks
revīzija
3b58377429

+ 1 - 1
encrypt/siwei_config.json

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

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

@@ -20,133 +20,15 @@ __date__ = 'August 2012'
 __copyright__ = '(C) 2012, Victor Olaya'
 __copyright__ = '(C) 2012, Victor Olaya'
 
 
 import os
 import os
+import importlib
 
 
 from PyQt5.QtGui import QIcon
 from PyQt5.QtGui import QIcon
-from osgeo import gdal
 from processing.core.ProcessingConfig import ProcessingConfig, Setting
 from processing.core.ProcessingConfig import ProcessingConfig, Setting
 from qgis.PyQt.QtCore import QCoreApplication
 from qgis.PyQt.QtCore import QCoreApplication
 from qgis.core import (QgsApplication,
 from qgis.core import (QgsApplication,
                        QgsProcessingProvider,
                        QgsProcessingProvider,
                        QgsRuntimeProfiler)
                        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(
 pluginPath = os.path.normpath(os.path.join(
     os.path.split(os.path.dirname(__file__))[0], os.pardir))
     os.path.split(os.path.dirname(__file__))[0], os.pardir))
 
 
@@ -156,6 +38,7 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
     def __init__(self):
     def __init__(self):
         super().__init__()
         super().__init__()
         self.algs = []
         self.algs = []
+        self._algorithm_definitions = None
         QgsApplication.processingRegistry().addAlgorithmAlias('qgis:buildvirtualvector', 'gdal:buildvirtualvector')
         QgsApplication.processingRegistry().addAlgorithmAlias('qgis:buildvirtualvector', 'gdal:buildvirtualvector')
 
 
     def load(self):
     def load(self):
@@ -180,7 +63,12 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
         return '数管工具集'
         return '数管工具集'
 
 
     def longName(self):
     def longName(self):
-        version = GdalUtils.readableVersion()
+        # 延迟导入GdalUtils,只在需要时才加载
+        try:
+            from .GdalUtils import GdalUtils
+            version = GdalUtils.readableVersion()
+        except ImportError:
+            version = 'Unknown'
         return f'数管工具集 ({version})'
         return f'数管工具集 ({version})'
 
 
     def id(self):
     def id(self):
@@ -191,141 +79,193 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
 
 
     def icon(self):
     def icon(self):
         return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'tools.png'))
         return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'tools.png'))
-        # return QgsApplication.getThemeIcon("/providerGdal.svg")
 
 
     def svgIconPath(self):
     def svgIconPath(self):
         return os.path.join(pluginPath, 'images', 'dbms', 'tools.png')
         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):
     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):
     def supportedOutputRasterLayerExtensions(self):
-        return GdalUtils.getSupportedOutputRasterExtensions()
+        """延迟加载GdalUtils"""
+        try:
+            from .GdalUtils import GdalUtils
+            return GdalUtils.getSupportedOutputRasterExtensions()
+        except ImportError:
+            return []
 
 
     def supportsNonFileBasedOutput(self):
     def supportsNonFileBasedOutput(self):
         """
         """
@@ -336,4 +276,4 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
     def tr(self, string, context=''):
     def tr(self, string, context=''):
         if context == '':
         if context == '':
             context = 'GdalAlgorithmProvider'
             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']
             defaultValue=siwei_config.CONFIG['db']['host']
         ))
         ))
 
 
+
+
+
+
         self.addParameter(QgsProcessingParameterDatabaseSchema(
         self.addParameter(QgsProcessingParameterDatabaseSchema(
             self.SCHEMA,
             self.SCHEMA,
             self.tr('模式'),
             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  *
 *   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     *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *   (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.StringUtils import getConnectionStr
 from processing.tools.GeoServer.Geoserver import Geoserver
 from processing.tools.GeoServer.Geoserver import Geoserver
 from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
 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
 from processing.tools.system import isWindows
 
 
@@ -94,11 +94,12 @@ class Postgisrestore(GdalAlgorithm):
         self.addParameter(QgsProcessingParameterEnum(name=self.RESTORETABLE,
         self.addParameter(QgsProcessingParameterEnum(name=self.RESTORETABLE,
                                                      description=self.tr('目标数据源'),
                                                      description=self.tr('目标数据源'),
                                                      options=tablenames))
                                                      options=tablenames))
-        redis = Redis()
-        tablename = redis.get("curRestoreTable")
-        print(tablename)
+        
+        # 使用状态管理器替代 Redis
+        tablename = get_state("curRestoreTable")
+        print(f"当前恢复表: {tablename}")
+        
         if tablename is not None:
         if tablename is not None:
-            tablename = tablename.decode('utf-8')
             versions = pgconn.getTableVersions(tablename=tablename)
             versions = pgconn.getTableVersions(tablename=tablename)
             curversion = pgconn.getTableCurVersion(tablename=tablename)
             curversion = pgconn.getTableCurVersion(tablename=tablename)
             tableversion_param = QgsProcessingParameterString(
             tableversion_param = QgsProcessingParameterString(
@@ -149,6 +150,10 @@ class Postgisrestore(GdalAlgorithm):
         pgconn = PostgreSQL(schema='base')
         pgconn = PostgreSQL(schema='base')
         tableinfo = self.tables[parameters[self.RESTORETABLE]]
         tableinfo = self.tables[parameters[self.RESTORETABLE]]
         tablename = tableinfo[1]
         tablename = tableinfo[1]
+        
+        # 设置当前恢复表到状态管理器
+        set_state("curRestoreTable", tablename)
+        
         # 判断回退版本关系
         # 判断回退版本关系
         curversion = parameters[self.CURVERSION]
         curversion = parameters[self.CURVERSION]
         targetversion = self.versionlist[parameters[self.RESTOREVERSION]]
         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)
         # self.addParameter(self.zymlParams)
 
 
     def name(self):
     def name(self):
-        return 'Dpostgistogeoserver'
+        return 'postgistogeoserver'
 
 
     def icon(self):
     def icon(self):
         return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'publishserver.png'))
         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  *
 *   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     *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *   (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.StringUtils import (getConnectionStr, getNow)
 from processing.tools.GeoServer.Geoserver import Geoserver
 from processing.tools.GeoServer.Geoserver import Geoserver
 from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
 from processing.tools.PostgreSQL.PostgreSQL import PostgreSQL
+from processing.tools.Login.StateManager import set_state, get_state
 from processing.tools.system import isWindows
 from processing.tools.system import isWindows
 
 
 pluginPath = os.path.normpath(os.path.join(
 pluginPath = os.path.normpath(os.path.join(
@@ -139,6 +140,10 @@ class Postgisupdate(GdalAlgorithm):
         tableinfo = self.tables[parameters[self.TARGET]]
         tableinfo = self.tables[parameters[self.TARGET]]
         tablename = tableinfo[1]
         tablename = tableinfo[1]
         ywlx = tableinfo[3]
         ywlx = tableinfo[3]
+        
+        # 设置当前更新表到状态管理器
+        set_state("curUpdateTable", tablename)
+        
         pgconn = PostgreSQL(schema='base')
         pgconn = PostgreSQL(schema='base')
         print("===========备份表===========")
         print("===========备份表===========")
         # pgconn.resetBackTable(tablename=tablename)
         # 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()