Эх сурвалжийг харах

资源目录、软件授权、许可生成工具等提交

wanger 8 сар өмнө
parent
commit
eb71ea053e

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

@@ -106,7 +106,7 @@ class ExportRasterByMask(GdalAlgorithm):
                                                                   self.tr('导出位置')))
 
     def name(self):
-        return '栅格数据分发'
+        return 'rasterexport'
 
     def displayName(self):
         return self.tr('栅格数据分发')

+ 30 - 5
processing/algs/gdal/GdalAlgorithm.py

@@ -57,17 +57,34 @@ class GdalAlgorithm(QgsProcessingAlgorithm):
 
     def __init__(self):
         super().__init__()
+        # TODO wanger GdalAlgorithm全局参数配置
         self.output_values = {}
+        self.pgcoon = {
+            "host": "127.0.0.1",
+            "schema": "vector",
+            "port": "5432",
+            "user": "postgres",
+            "password": "postgres",
+            "dbname": "real3d"
+        }
+        self.geoservercoon = {
+            "url": "http://127.0.0.1:28085/geoserver",
+            "username": "admin",
+            "password": "geoserver",
+            "defaultworkspace": "demo",
+            "cachestart": "0",
+            "cacheend": "15"
+        }
 
     def icon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'tools.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'tool.png'))
         # return QgsApplication.getThemeIcon("/providerGdal.svg")
 
     def tags(self):
         return ['ogr', 'gdal', self.commandName()]
 
     def svgIconPath(self):
-        return os.path.join(pluginPath, 'images', 'dbms', 'tools.png')
+        return os.path.join(pluginPath, 'images', 'dbms', 'tool.png')
         # return QgsApplication.iconPath("providerGdal.svg")
 
     def createInstance(self, config={}):
@@ -148,6 +165,12 @@ class GdalAlgorithm(QgsProcessingAlgorithm):
         self.output_values[name] = value
 
     def processAlgorithm(self, parameters, context, feedback):
+        # TODO wanger 生成许可文件
+        if parameters.get("LICENSEHOST") is not None:
+            self.generateLicense(parameters)
+            return {
+                "许可文件路径": parameters.get("OUTPUT")
+            }
         # TODO wanger 上传图斑文件数据包
         if parameters.get("SPOTFILE") is not None:
             filepath = parameters.get("SPOTFILE")
@@ -203,9 +226,11 @@ class GdalAlgorithm(QgsProcessingAlgorithm):
                 # 获取输入栅格图层
                 raster_layer = self.parameterAsRasterLayer(parameters, self.INPUTRASTER, context)
                 file = raster_layer.source()
-                result = geoSer.publishGeoService(parameters, context, feedback, commands, zymlbsm, layer_group_join, file)
+                result = geoSer.publishGeoService(parameters, context, feedback, commands, zymlbsm, layer_group_join,
+                                                  file)
             else:
-                result = geoSer.publishGeoService(parameters, context, feedback, commands, zymlbsm, layer_group_join, None)
+                result = geoSer.publishGeoService(parameters, context, feedback, commands, zymlbsm, layer_group_join,
+                                                  None)
             return result
 
         # === 获取gdal命令参数执行并输出log开始 ===
@@ -249,7 +274,7 @@ class GdalAlgorithm(QgsProcessingAlgorithm):
                 ogrLayer = raster_layer.source()
             print(ogrLayer)
             pgconn.metadataStorage(parameters, ssxzqh, fileliststr, self.ywlxs[parameters.get("VECTOR_YWLX")],
-                                   self.depts[parameters.get("VECTOR_GLBM")], ogrLayer)
+                                   self.depts[parameters.get("VECTOR_GLBM")], ogrLayer, self.zymls[parameters.get("VECTOR_ZYML")])
             pgconn.close()
         return results
 

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

@@ -122,7 +122,7 @@ class GdalParametersPanel(ParametersPanel):
             layout.addWidget(self.vectorupdate)
             gdalHidden = True
             loop = False
-        elif algname == "postgisrestore" or algname == "spotfileupload" or algname == "spotfiledownload" or algname == "spotfiledelete":
+        elif algname == "postgisrestore" or algname == "spotfileupload" or algname == "spotfiledownload" or algname == "spotfiledelete" or algname == "licensemake":
             gdalHidden = True
             loop = False
 

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

@@ -98,6 +98,7 @@ from .PointsAlongLines import PointsAlongLines
 from .ExportVectorByMask import ExportVectorByMask
 from .ExportRasterByMask import ExportRasterByMask
 from .VectorProject import VectorProject
+from .LicenseMake import LicenseMake
 
 # from .ogr2ogrtabletopostgislist import Ogr2OgrTableToPostGisList
 
@@ -219,7 +220,8 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
             SpotfileDelete(),
             ExportVectorByMask(),
             ExportRasterByMask(),
-            VectorProject()
+            VectorProject(),
+            LicenseMake()
             # Ogr2OgrTableToPostGisList(),
         ]
 

+ 118 - 0
processing/algs/gdal/LicenseMake.py

@@ -0,0 +1,118 @@
+"""
+***************************************************************************
+    LicenseMake.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) 2012, siwei'
+
+import os
+from cryptography.fernet import Fernet
+from PyQt5.QtGui import QIcon
+
+from qgis._core import QgsCoordinateReferenceSystem, QgsProcessingParameterCrs, QgsProcessingParameterFileDestination
+from qgis.core import (QgsProcessing,
+                       QgsProcessingAlgorithm,
+                       QgsProcessingParameterDefinition,
+                       QgsProcessingParameterString,
+                       QgsProcessingParameterDateTime,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterVectorDestination)
+from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
+from processing.algs.gdal.GdalUtils import GdalUtils
+
+pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
+
+
+class LicenseMake(GdalAlgorithm):
+    HOST = 'LICENSEHOST'
+    Date = 'LICENSEDATE'
+    OUTPUT = 'OUTPUT'
+
+    def __init__(self):
+        super().__init__()
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterString(self.HOST,
+                                                       self.tr('服务器机器名')))
+        self.addParameter(
+            QgsProcessingParameterDateTime(self.Date, '许可到期时间', type=QgsProcessingParameterDateTime.Type.Date))
+
+        # 创建一个输出参数,指定为文本文件类型
+        output_parameter = QgsProcessingParameterFileDestination(
+            self.OUTPUT,
+            self.tr('导出位置'),
+            '.txt', defaultValue='license.txt')
+        self.addParameter(output_parameter)
+
+    def name(self):
+        return 'licensemake'
+
+    def displayName(self):
+        return self.tr('生成许可文件')
+
+    def group(self):
+        return self.tr('软件许可')
+
+    def groupId(self):
+        return 'licensetools'
+
+    def icon(self):
+        return QIcon(os.path.join(pluginPath, 'images', 'dbms', 'certification.png'))
+
+    def commandName(self):
+        return 'ogr2ogr'
+
+    def generateLicense(self, parameters):
+        print("咱这块正在生成许可文件呢,别着急")
+        outputpath = parameters.get("OUTPUT")
+        custom_format = "yyyy-MM-dd"
+        licensedate = parameters.get("LICENSEDATE").toString(custom_format)
+        print(f"许可到期时间:{licensedate}")
+        licensehost = parameters.get("LICENSEHOST")
+        print(f"许可计算机机器名:{licensehost}")
+        params = {
+            "host": licensehost,
+            "license": licensedate
+        }
+        # 生成一个密钥
+        key = Fernet.generate_key()
+        # 使用密钥创建一个Fernet对象
+        cipher_suite = Fernet(key)
+        # 需要加密的数据
+        message = str(params).encode("utf-8")
+        #
+        # # 加密数据
+        encrypted_message = cipher_suite.encrypt(message)
+        print(f"加密的消息: {encrypted_message}")
+        # 要写入的文本内容
+        text_lines = [key.decode("utf-8"), encrypted_message.decode("utf-8")]
+        # 打开文件进行写入
+        with open(outputpath, 'w') as file:
+            # 遍历文本行并写入文件
+            for line in text_lines:
+                file.write(line + "\n")  # 添加换行符
+
+    def getConsoleCommands(self, parameters, context, feedback, executing=True):
+        print(parameters)
+        arguments = [
+
+        ]
+        arguments = [
+
+        ]
+
+        return [self.commandName(), GdalUtils.escapeAndJoin(arguments)]

+ 15 - 5
processing/algs/gdal/ogr2ogrtopostgislist.py

@@ -24,6 +24,7 @@ import os
 from PyQt5.QtGui import QIcon
 from PyQt5.QtWidgets import QMessageBox
 
+from qgis._core import QgsProcessingParameterDefinition
 from qgis.core import (QgsProcessing,
                        QgsProcessingParameterFeatureSource,
                        QgsProcessingParameterString,
@@ -100,6 +101,7 @@ class Ogr2OgrToPostGisList(GdalAlgorithm):
     SOURCE_TYPE = 'SOURCE_TYPE'
     XZQH_FIELD = 'XZQH_FIELD'
     VECTOR_GLBM = 'VECTOR_GLBM'
+    VECTOR_ZYML = 'VECTOR_ZYML'
     Metadata_storage = 'Metadata_storage'
     XLK = 'XLK'
     XLKXZX = ['选择一', '选择二', '选择三', '选择四', '选择五']
@@ -115,11 +117,12 @@ class Ogr2OgrToPostGisList(GdalAlgorithm):
                                                               types=[QgsProcessing.TypeVector]))
         db_param = QgsProcessingParameterProviderConnection(
             self.DATABASE,
-            self.tr('数据库'), 'postgres')
+            self.tr('数据库'), provider='postgres',
+            defaultValue=self.pgcoon["host"])
         self.addParameter(db_param)
         schema_param = QgsProcessingParameterDatabaseSchema(
             self.SCHEMA,
-            self.tr('模式'), defaultValue='public', connectionParameterName=self.DATABASE,
+            self.tr('模式'), defaultValue=self.pgcoon["schema"], connectionParameterName=self.DATABASE,
             optional=False)
         self.addParameter(schema_param)
         table_param = QgsProcessingParameterString(
@@ -159,6 +162,12 @@ class Ogr2OgrToPostGisList(GdalAlgorithm):
             self.depts.append(row[0])
         self.addParameter(QgsProcessingParameterEnum(name=self.VECTOR_GLBM,
                                                      description=self.tr('管理部门'), options=self.depts))
+        rows = pgconn.getVectorZyml()
+        self.zymls = []
+        for row in rows:
+            self.zymls.append(row[1])
+        self.addParameter(QgsProcessingParameterEnum(name=self.VECTOR_ZYML,
+                                                     description=self.tr('资源目录'), options=self.zymls))
         # self.addParameter(QgsProcessingParameterEnum(self.XLK,
         #                                              self.tr('下拉框'), options=self.XLKXZX,
         #                                              defaultValue=0))
@@ -182,9 +191,10 @@ class Ogr2OgrToPostGisList(GdalAlgorithm):
                                                   defaultValue=crs,
                                                   optional=False)
         self.addParameter(crs_parameter)
-        self.addParameter(QgsProcessingParameterString(self.SOURCE_TYPE,
-                                                       self.tr('数据源类型'), "vector",
-                                                       optional=False))
+        string = QgsProcessingParameterString(self.SOURCE_TYPE,
+                                              self.tr('数据源类型'), "vector",
+                                              optional=False)
+        self.addParameter(string)
         # self.addParameter(QgsProcessingParameterString(self.SHAPE_ENCODING,
         #                                                self.tr('Shape encoding'), "", optional=True))
         #

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

@@ -132,23 +132,23 @@ class Postgistogeoserver(GdalAlgorithm):
                                                        self.tr('服务名称'), "",
                                                        optional=False))
         self.addParameter(QgsProcessingParameterString(self.GeoServer_URI,
-                                                       self.tr('服务器地址'), self.GeoServerConfig.get("url"),
+                                                       self.tr('服务器地址'), self.geoservercoon["url"],
                                                        optional=False))
         self.addParameter(QgsProcessingParameterString(self.GeoServer_USERNAME,
-                                                       self.tr('服务器用户名'), self.GeoServerConfig.get("username"),
+                                                       self.tr('服务器用户名'), self.geoservercoon["username"],
                                                        optional=False))
         self.addParameter(QgsProcessingParameterString(self.GeoServer_PASSWORD,
-                                                       self.tr('服务器密码'), self.GeoServerConfig.get("password"),
+                                                       self.tr('服务器密码'), self.geoservercoon["password"],
                                                        optional=False))
         self.addParameter(QgsProcessingParameterString(self.GeoServer_WORKSPACE,
                                                        self.tr('服务器工作空间'),
-                                                       self.GeoServerConfig.get("defaultworkspace"),
+                                                       self.geoservercoon["defaultworkspace"],
                                                        optional=False))
         # 图层组配置
-        geo = Geoserver(self.GeoServerConfig["url"], username=self.GeoServerConfig["username"],
-                        password=self.GeoServerConfig["password"])
+        geo = Geoserver(service_url=self.geoservercoon["url"], username=self.geoservercoon["username"],
+                        password=self.geoservercoon["password"])
         self.groups = []
-        requestgroups = geo.get_layergroups(self.GeoServerConfig.get("defaultworkspace"))
+        requestgroups = geo.get_layergroups(self.geoservercoon["defaultworkspace"])
         if requestgroups["layerGroups"] != "":
             groups = requestgroups["layerGroups"]["layerGroup"]
             for group in groups:
@@ -163,10 +163,10 @@ class Postgistogeoserver(GdalAlgorithm):
         self.addParameter(QgsProcessingParameterBoolean(self.GeoServer_Caching,
                                                         self.tr('数据切片'), defaultValue=False))
         self.addParameter(QgsProcessingParameterString(self.GeoServer_Caching_Start,
-                                                       self.tr('开始级别'), "0",
+                                                       self.tr('开始级别'), self.geoservercoon["cachestart"],
                                                        optional=True))
         self.addParameter(QgsProcessingParameterString(self.GeoServer_Caching_Stop,
-                                                       self.tr('终止级别'), "18",
+                                                       self.tr('终止级别'), self.geoservercoon["cacheend"],
                                                        optional=True))
         server_parameter = QgsProcessingParameterBoolean(self.Publish_Service,
                                                          self.tr('服务发布'), defaultValue=True)

+ 18 - 6
processing/algs/gdal/rastertopostgislist.py

@@ -101,6 +101,7 @@ class Ogr2PostGisList(GdalAlgorithm):
     VECTOR_YWLX = 'VECTOR_YWLX'
     SOURCE_TYPE = 'SOURCE_TYPE'
     VECTOR_GLBM = 'VECTOR_GLBM'
+    VECTOR_ZYML = 'VECTOR_ZYML'
     VECTOR_NODATA = 'VECTOR_NODATA'
     XZQH_FIELD = 'XZQH_FIELD'
     Metadata_storage = 'Metadata_storage'
@@ -121,11 +122,12 @@ class Ogr2PostGisList(GdalAlgorithm):
                                                             [QgsProcessing.TypeRaster]))
         db_param = QgsProcessingParameterProviderConnection(
             self.DATABASE,
-            self.tr('数据库'), 'postgres')
+            self.tr('数据库'), provider='postgres',
+            defaultValue=self.pgcoon["host"])
         self.addParameter(db_param)
         schema_param = QgsProcessingParameterDatabaseSchema(
             self.SCHEMA,
-            self.tr('模式'), defaultValue='public', connectionParameterName=self.DATABASE,
+            self.tr('模式'), defaultValue=self.pgcoon["schema"], connectionParameterName=self.DATABASE,
             optional=False)
         self.addParameter(schema_param)
         table_param = QgsProcessingParameterString(
@@ -157,6 +159,12 @@ class Ogr2PostGisList(GdalAlgorithm):
         # self.addParameter(QgsProcessingParameterString(self.VECTOR_XMLX,
         #                                                self.tr('项目类型'), "",
         #                                                optional=False))
+        rows = pgconn.getVectorZyml()
+        self.zymls = []
+        for row in rows:
+            self.zymls.append(row[1])
+        self.addParameter(QgsProcessingParameterEnum(name=self.VECTOR_ZYML,
+                                                     description=self.tr('资源目录'), options=self.zymls))
         self.addParameter(QgsProcessingParameterString(self.VECTOR_NODATA,
                                                        self.tr('无效值'), "0,0,0,0,0,0",
                                                        optional=True))
@@ -171,11 +179,15 @@ class Ogr2PostGisList(GdalAlgorithm):
                                                      self.tr('分块存储大小,如栅格文件大于1G必须分块存储'),
                                                      options=self.Raster_T_List,
                                                      optional=False, defaultValue=3))
-        self.addParameter(QgsProcessingParameterString(self.SOURCE_TYPE,
+        string = QgsProcessingParameterString(self.SOURCE_TYPE,
                                                        self.tr('数据源类型'), "raster",
-                                                       optional=False))
-        self.addParameter(QgsProcessingParameterBoolean(self.Metadata_storage,
-                                                        self.tr('元数据入库'), defaultValue=True))
+                                                       optional=False)
+        # string.setFlags(QgsProcessingParameterString.FlagReadOnly)
+        self.addParameter(string)
+        metadata = QgsProcessingParameterBoolean(self.Metadata_storage,
+                                                        self.tr('元数据入库'), defaultValue=True)
+        # metadata.setEnable(False)
+        self.addParameter(metadata)
         self.addParameter(QgsProcessingParameterBoolean(self.INDEX,
                                                         self.tr('不创建数据索引'), defaultValue=False))
 

BIN
processing/images/dbms/certification.png


BIN
processing/images/dbms/tool.png


+ 14 - 6
processing/tools/PostgreSQL/PostgreSQL.py

@@ -80,29 +80,31 @@ class PostgreSQL:
 
     # 保存元数据信息
     def insertVectorStorage(self, id, name, year, xmlx, sjly, xzqh, xzqh_field, ywlx, sjlx, sjywz, glbm, table_alias):
-        sql = "insert into {} (id, name, year, xmlx, sjly, xzqh, xzqh_field, ywlx, sjlx, sjywz, glbm, table_alias)  values ('{}','{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}')".format(
+        sql = "insert into {} (id, name, year, xmlx, sjly, xzqh, xzqh_field, ywlx, sjlx, sjywz, glbm, table_alias)  values ('{}','{}', '{}', (select bsm from t_vector_zyml where name = '{}'), '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}')".format(
             self.Vector_Storage, id, name, year.toString("yyyy"), xmlx, sjly, xzqh, xzqh_field, ywlx, sjlx, sjywz, glbm,
             table_alias)
         self.cur.execute(sql)
         self.conn.commit()
 
     # 元数据入库,参数parameters
-    def metadataStorage(self, parameters, ssxzqh, fileliststr, ywlx, glbm, ogrLayer):
+    def metadataStorage(self, parameters, ssxzqh, fileliststr, ywlx, glbm, ogrLayer, zyml):
         record_id = ""
         id = uuid.uuid4().__str__()
         id = id.replace("-", "")
         # print(parameters)
         if (parameters.get("TABLE") is None or parameters.get("TABLE") == "") and ogrLayer is not None:
-            record_id = parameters.get("SCHEMA") + "." + getInputFileName(ogrLayer)
+            record_id = parameters.get("SCHEMA") + "." + getInputFileName(ogrLayer).lower()
         else:
             record_id = parameters.get("SCHEMA") + "." + parameters.get("TABLE")
         table_alias = parameters.get("TABLE_ALIAS")
         if table_alias != '' and table_alias is not None:  # 配置表别名
             self.setTableAlias(table=self.getTableName(recordid=record_id),
                                alias=table_alias)
+        else:
+            table_alias = ''
         self.deleteVectorStorage(name=record_id)
         self.insertVectorStorage(id=id, name=record_id, year=parameters.get("VECTOR_YEAR"),
-                                 xmlx=parameters.get("VECTOR_XMLX"), sjly=parameters.get("VECTOR_SJLY"),
+                                 xmlx=zyml, sjly=parameters.get("VECTOR_SJLY"),
                                  xzqh=ssxzqh, xzqh_field=parameters.get("XZQH_FIELD"),
                                  ywlx=ywlx, sjlx=parameters.get("SOURCE_TYPE"), sjywz=ogrLayer,
                                  glbm=glbm, table_alias=table_alias)
@@ -175,6 +177,12 @@ class PostgreSQL:
         rows = self.cur.fetchall()
         return rows
 
+    def getVectorZyml(self):
+        self.cur.execute(
+            "select bsm,name from t_vector_zyml t order by t.sort,t.name")
+        rows = self.cur.fetchall()
+        return rows
+
     # 获取行政区划
     def getXzqh(self):
         self.cur.execute(
@@ -198,8 +206,8 @@ class PostgreSQL:
 
     # 根据用户名称查询有权限维护的数据库表,返回别名或者表名
     def getManagerTables(self, username):
-        sql = f'select t.id "id",name "name", case when t.table_alias is not null then  t.table_alias else t.name end as "alias", t.ywlx "ywlx" ' \
-              f'from {self.Vector_Storage} t where t.glbm = (select dept_name from sys_dept d where d.dept_id = (select dept_id from sys_user u where u.user_name = \'{username}\' ))'
+        sql = f'select t.id "id",name "name", case when t.table_alias != \'\' then  t.table_alias else t.name end as "alias", t.ywlx "ywlx" ' \
+              f'from {self.Vector_Storage} t where t.glbm = (select dept_name from sys_dept d where d.dept_id = (select dept_id from sys_user u where u.user_name = \'{username}\' )) and t.sjlx = \'vector\''
         self.cur.execute(sql)
         rows = self.cur.fetchall()
         return rows

+ 97 - 1
processing/tools/QGS/load.py

@@ -1,6 +1,60 @@
 from PyQt5.QtCore import QObject, QEvent, Qt
-from PyQt5.QtWidgets import QToolBar
+from PyQt5.QtWidgets import QToolBar, QMessageBox
 from qgis.utils import iface
+from cryptography.fernet import Fernet
+import json
+import os
+import platform
+import winreg
+import datetime
+import socket
+
+
+def get_qgis_install_dir():
+    # 尝试从环境变量获取
+    qgis_env = os.getenv('QGIS_PREFIX_PATH')
+    if qgis_env:
+        return f'{qgis_env.replace("apps/qgis-ltr", "")}bin'
+    # 尝试从Windows注册表获取
+    if platform.system() == "Windows":
+        sub_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\QGIS')
+        try:
+            qgis_dir, _ = winreg.QueryValueEx(sub_key, 'QGIS_PREFIX_PATH')
+            return qgis_dir
+        except WindowsError:
+            pass
+    # 常见的安装路径
+    default_paths = [
+        os.path.join(os.path.expanduser('~'), 'AppData\Local\QGIS\QGIS3'),
+        r'C:\Program Files\QGIS 3.X',
+        r'C:\Program Files (x86)\QGIS 3.X',
+    ]
+    for path in default_paths:
+        if os.path.exists(path):
+            return path
+    return None
+
+
+def str_to_time(time_str):
+    return datetime.datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")
+
+
+def str_to_dict(string):
+    # 去除首尾的花括号
+    string = string.strip("{}")
+    # 分割每个键值对
+    pairs = string.split(", ")
+    # 创建空字典
+    result = {}
+    # 遍历键值对并添加到字典中
+    for pair in pairs:
+        key, value = pair.split(": ")
+        # 去除键和值两边的引号
+        key = key.strip("'")
+        value = value.strip("'")
+        # 添加到字典中
+        result[key] = value
+    return result
 
 
 def on_initialization_completed():
@@ -22,6 +76,48 @@ def on_initialization_completed():
     # 安装事件过滤器到地图画布
     main_window.installEventFilter(event_filter)
 
+    # 程序许可验证
+    machine_name = socket.gethostname()
+    current_time = datetime.datetime.now()
+    qgis_dir = get_qgis_install_dir()
+    licensepath = f"{qgis_dir}\\license.txt"
+    # 打开文件并读取内容
+    text = []
+    with open(licensepath, 'r') as file:
+        for line in file:
+            text.append(line.replace('\n', ' '))
+    # 打印文件内容
+    print(text)
+
+    try:
+        # 尝试执行的代码
+        fernet = Fernet(text[0].encode("utf-8"))
+        decrypted_message = fernet.decrypt(text[1].encode("utf-8"))
+        license = decrypted_message.decode('utf-8')
+        licenseDict = str_to_dict(license)
+        host = licenseDict["host"]
+        date = licenseDict["license"]
+
+        time_str = f"{date} 23:59:59"
+        licensetime = str_to_time(time_str)
+        if host != machine_name:
+            licenseError("机器名错误!")
+            exit(1)
+        elif current_time > licensetime:
+            licenseError("许可已过期!")
+            exit(1)
+        else:
+            print("许可正常")
+            # print(f"解密的消息: {decrypted_message.decode('utf-8')}")
+    except Exception as e:
+        # 处理异常的代码
+        licenseError("许可文件解析问题!")
+        exit(1)
+
+
+def licenseError(message):
+    QMessageBox.critical(None, 'Error', message)
+
 
 class ClickEventFilter(QObject):
     def __init__(self, parent=None):