浏览代码

拖拽更新

Gogs 6 月之前
父节点
当前提交
742ad85cf5

文件差异内容过多而无法显示
+ 0 - 0
QGIS/QGIS3.ini


+ 2 - 2
QGIS/QGISCUSTOMIZATION3.ini

@@ -480,8 +480,8 @@ Toolbars\mMapNavToolBar\mActionZoomOut=true
 Toolbars\mMapNavToolBar\mActionZoomToLayers=true
 Toolbars\mMapNavToolBar\mActionZoomToSelected=true
 Toolbars\mMeshToolBar=false
-Toolbars\mPluginToolBar=false
-Toolbars\mPluginToolBar\mActionShowPythonDialog=false
+Toolbars\mPluginToolBar=true
+Toolbars\mPluginToolBar\mActionShowPythonDialog=true
 Toolbars\mRasterToolBar=false
 Toolbars\mRasterToolBar\mActionDecreaseBrightness=true
 Toolbars\mRasterToolBar\mActionDecreaseContrast=true

+ 63 - 26
python/plugins/ResourceTree/ui/PostgreSQL.py

@@ -74,6 +74,8 @@ class PostgreSQL:
         self.cur.close()
         self.conn.close()
 
+    def fetchone(self):
+        return self.cur.fetchone()
 
     def getManagerTables(self, username='admin'):
         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" ' \
@@ -82,33 +84,58 @@ class PostgreSQL:
         rows = self.cur.fetchall()
         return rows
 
+    def dropTable(self, tablename):
+        try:
+            drop_sql = sql.SQL("DROP TABLE IF EXISTS {}").format(sql.Identifier(tablename))
+            self.cur.execute(drop_sql)
+        except Exception as e:
+            print(f"删除表 {tablename} 失败: {e}")
+
+
     def getZyml(self):
+        """获取资源目录数据,按sort字段排序"""
         self.cur.execute("""
-                         SELECT *
-                         FROM (SELECT t.bsm::text, t.name::text, t.pbsm::text, ''::text AS type, t.sort::integer
-                               FROM t_vector_zyml t
-                               ORDER BY t.sort) AS a
-                         UNION ALL
-                         SELECT s.name::text AS bsm, CASE
-                                                         WHEN s.table_alias IS NULL OR s.table_alias = '' THEN s.name
-                                                         ELSE s.table_alias
-                             END::text AS name, s.xmlx::text AS pbsm, s.sjlx::text AS type, row_number() OVER (ORDER BY cnt DESC)::integer AS sort
-                         FROM (SELECT s.*, count(*) OVER (PARTITION BY s.xmlx) AS cnt
-                               FROM t_vector_storage s
-                                        JOIN t_vector_zyml z ON s.xmlx = z.bsm OR s.xmlx = z.pbsm) s
-                         """)
+            SELECT *
+            FROM (
+                SELECT 
+                    t.bsm::text, 
+                    t.name::text, 
+                    t.pbsm::text, 
+                    ''::text AS type, 
+                    CASE 
+                        WHEN t.sort IS NULL OR t.sort = '' THEN 9999
+                        ELSE CAST(t.sort AS INTEGER)
+                    END AS sort
+                FROM t_vector_zyml t
+                ORDER BY t.pbsm, 
+                    CASE 
+                        WHEN t.sort IS NULL OR t.sort = '' THEN 9999
+                        ELSE CAST(t.sort AS INTEGER)
+                    END
+            ) AS a
+            UNION ALL
+            SELECT 
+                s.name::text AS bsm, 
+                CASE
+                    WHEN s.table_alias IS NULL OR s.table_alias = '' THEN s.name
+                    ELSE s.table_alias
+                END::text AS name, 
+                s.xmlx::text AS pbsm, 
+                s.sjlx::text AS type, 
+                row_number() OVER (ORDER BY cnt DESC)::integer AS sort
+            FROM (
+                SELECT s.*, count(*) OVER (PARTITION BY s.xmlx) AS cnt
+                FROM t_vector_storage s
+                JOIN t_vector_zyml z ON s.xmlx = z.bsm OR s.xmlx = z.pbsm
+            ) s
+            ORDER BY pbsm, sort
+        """)
         columns = [desc[0] for desc in self.cur.description]
         return [dict(zip(columns, row)) for row in self.cur.fetchall()]
 
-    def dropTable(self, tablename):
-        self.cur.execute(
-            "delete from t_vector_storage where name = '{}'".format(tablename))
-        self.conn.commit()
-        self.cur.execute("drop table {}".format(tablename))
-        self.conn.commit()
-
     def addZyml(self, uid, pid, name):
-        # 注意:CAST sort AS INTEGER
+        """添加新的资源目录节点"""
+        # 获取同级节点的最大sort值
         self.cur.execute("SELECT COALESCE(MAX(CAST(sort AS INTEGER)), -1) + 1 FROM t_vector_zyml WHERE pbsm = %s",
                          (pid,))
         sort_val = self.cur.fetchone()[0]
@@ -118,16 +145,26 @@ class PostgreSQL:
             (uid, name, pid, sort_val)
         )
         self.conn.commit()
+        print(f"添加新节点: {name} (bsm: {uid}, 父节点: {pid}, 排序: {sort_val})")
+
+    def updateZymlOrder(self, bsm, pbsm, sort_index):
+        """更新资源目录节点的父节点和排序"""
+        self.cur.execute(
+            "UPDATE t_vector_zyml SET pbsm = %s, sort = %s WHERE bsm = %s",
+            (pbsm, str(sort_index), bsm)  # 将整数转换为字符串存储
+        )
+
+    def deleteZyml(self, bsm):
+        """删除资源目录节点"""
+        # 先删除所有子节点
+        self.cur.execute("DELETE FROM t_vector_zyml WHERE pbsm = %s", (bsm,))
+        # 再删除自身
+        self.cur.execute("DELETE FROM t_vector_zyml WHERE bsm = %s", (bsm,))
 
     def renameZyml(self, id, name):
         self.cur.execute("update t_vector_zyml set name = '{}' where bsm = '{}'".format(name, id))
         self.conn.commit()
 
-    def deleteZyml(self, id):
-        self.cur.execute(
-            "delete from t_vector_zyml where bsm in (WITH RECURSIVE a AS ( SELECT g.bsm, g.pbsm FROM t_vector_zyml g WHERE bsm = '{}' UNION ALL SELECT d.bsm, d.pbsm FROM t_vector_zyml d JOIN a ON a.bsm = d.pbsm ) SELECT bsm FROM a order by a.bsm)".format(
-                id))
-        self.conn.commit()
 
     def getResourceAttr(self, tablename):
         self.cur.execute(

+ 432 - 76
python/plugins/ResourceTree/ui/ResourceTree.py

@@ -8,6 +8,7 @@ import subprocess
 from PyQt5.QtWidgets import QMessageBox
 import psycopg2
 import redis
+from types import MethodType
 from PyQt5 import QtCore, QtGui, QtWidgets
 from PyQt5.QtCore import QSize, QUrl, Qt, QTimer
 from PyQt5.QtGui import QIcon, QDrag
@@ -23,12 +24,15 @@ from qgis.utils import iface
 from qgis.core import QgsRectangle, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProject, QgsVectorLayer
 from qgis import processing
 from .CombinedDialog import CombinedDialog
+from PyQt5.QtWidgets import QAbstractItemView
+
 
 # from .ModelWebView import ModelWebView
 
 current_directory = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))  # 获取当前路径
 
 
+
 class FormDialog(QDialog):
     def __init__(self, data):
         super().__init__()
@@ -121,6 +125,7 @@ class Ui_ResourceDockWidget(object):
         # **修改3: 延迟初始化树结构**
         self.setupButtons()
         self.setupTreeWidget()
+        self.setup_tree_drag_drop()
 
         ResourceDockWidget.setWidget(self.dockWidgetContents)
         self.retranslateUi(ResourceDockWidget)
@@ -594,7 +599,7 @@ class Ui_ResourceDockWidget(object):
             pid = ""
             if self.currentItem is not None:
                 pid = self.getNodeId(self.currentItem)
-            # **修改17: 使用优化的数据库连接**
+            # **修改17: 使用优化的数据库连接**PostgreSQL
             pg = self.get_db_connection()
             if pg is None:
                 QMessageBox.warning(None, "错误", "数据库连接失败")
@@ -609,6 +614,432 @@ class Ui_ResourceDockWidget(object):
             item.setText(1, uid)
             item.setText(2, "")
 
+    # === 以下为新增支持资源目录排序及保存的函数 ===
+
+    def save_tree_sort_order(self):
+        """保存树形结构的排序顺序到数据库"""
+        pg = self.get_db_connection()
+        if pg is None:
+            QMessageBox.warning(None, "错误", "数据库连接失败")
+            return False
+
+        try:
+            # 开始事务
+            pg.execute("BEGIN")
+
+            def save_node_order(item: QTreeWidgetItem, parent_bsm: str, level=0):
+                bsm = item.text(1)
+                sort_order = 0
+
+                # 获取在父节点中的索引位置作为排序值
+                if parent_bsm == '':  # 顶级节点
+                    for i in range(self.treeWidget.topLevelItemCount()):
+                        if self.treeWidget.topLevelItem(i) == item:
+                            sort_order = i
+                            break
+                else:  # 子节点
+                    parent_item = self.find_item_by_bsm(parent_bsm)
+                    if parent_item:
+                        for i in range(parent_item.childCount()):
+                            if parent_item.child(i) == item:
+                                sort_order = i
+                                break
+
+                # 更新数据库中的父节点和排序
+                pg.execute("UPDATE t_vector_zyml SET pbsm = %s, sort = %s WHERE bsm = %s",
+                           (parent_bsm, sort_order, bsm))
+
+                print(f"{'  ' * level}更新节点: {item.text(0)} (bsm: {bsm}) -> 父节点: {parent_bsm or 'ROOT'}, 排序: {sort_order}")
+
+                # 递归处理子节点
+                for i in range(item.childCount()):
+                    save_node_order(item.child(i), bsm, level + 1)
+
+            # 保存所有顶级节点及其子节点
+            for i in range(self.treeWidget.topLevelItemCount()):
+                top_item = self.treeWidget.topLevelItem(i)
+                save_node_order(top_item, '')  # 顶层节点 pbsm 为空字符串
+
+            # 提交事务
+            pg.execute("COMMIT")
+            print("树形结构排序保存成功")
+            return True
+
+        except Exception as e:
+            # 回滚事务
+            pg.execute("ROLLBACK")
+            print(f"保存树形结构排序失败: {e}")
+            return False
+        finally:
+            pg.close()
+
+    def find_item_by_bsm(self, bsm: str) -> QTreeWidgetItem:
+        """根据bsm查找树形控件中的项目"""
+        def search_item(parent_item):
+            if parent_item.text(1) == bsm:
+                return parent_item
+            for i in range(parent_item.childCount()):
+                result = search_item(parent_item.child(i))
+                if result:
+                    return result
+            return None
+
+        # 搜索顶级项目
+        for i in range(self.treeWidget.topLevelItemCount()):
+            top_item = self.treeWidget.topLevelItem(i)
+            if top_item.text(1) == bsm:
+                return top_item
+            result = search_item(top_item)
+            if result:
+                return result
+        return None
+
+    def setup_tree_drag_drop(self):
+        """设置树形控件的拖拽功能"""
+        # 启用拖拽功能
+        self.treeWidget.setDragDropMode(QAbstractItemView.InternalMove)
+        self.treeWidget.setDefaultDropAction(Qt.MoveAction)
+        self.treeWidget.setDragEnabled(True)
+        self.treeWidget.setAcceptDrops(True)
+        self.treeWidget.setDropIndicatorShown(True)
+
+        # 保存原始的dropEvent方法
+        original_drop_event = self.treeWidget.dropEvent
+
+        def custom_drop_event(event):
+            """自定义拖拽放置事件处理"""
+            # 获取拖拽前的信息
+            dragged_items = self.treeWidget.selectedItems()
+            if not dragged_items:
+                return original_drop_event(event)
+
+            dragged_item = dragged_items[0]
+            old_parent_bsm = dragged_item.text(2)  # 原父节点bsm
+            old_parent_item = None
+            old_position = -1
+
+            # 记录拖拽前的位置信息
+            if old_parent_bsm == '':  # 原来是顶级节点
+                for i in range(self.treeWidget.topLevelItemCount()):
+                    if self.treeWidget.topLevelItem(i) == dragged_item:
+                        old_position = i
+                        break
+            else:  # 原来是子节点
+                old_parent_item = self.find_item_by_bsm(old_parent_bsm)
+                if old_parent_item:
+                    for i in range(old_parent_item.childCount()):
+                        if old_parent_item.child(i) == dragged_item:
+                            old_position = i
+                            break
+
+            # 执行原始的拖拽操作
+            original_drop_event(event)
+
+            # 获取拖拽后的信息
+            new_parent_item = dragged_item.parent()
+            new_parent_bsm = new_parent_item.text(1) if new_parent_item else ''
+            new_position = -1
+
+            if new_parent_item is None:  # 现在是顶级节点
+                for i in range(self.treeWidget.topLevelItemCount()):
+                    if self.treeWidget.topLevelItem(i) == dragged_item:
+                        new_position = i
+                        break
+            else:  # 现在是子节点
+                for i in range(new_parent_item.childCount()):
+                    if new_parent_item.child(i) == dragged_item:
+                        new_position = i
+                        break
+
+            # 更新节点的pbsm字段(用于界面显示同步)
+            dragged_item.setText(2, new_parent_bsm)
+
+            # 判断拖拽类型并处理
+            drag_type = self.get_drag_type(old_parent_bsm, new_parent_bsm, old_position, new_position)
+            print(f"拖拽类型: {drag_type}")
+            print(f"节点 '{dragged_item.text(0)}' 从 {old_parent_bsm or 'ROOT'}[{old_position}] 移动到 {new_parent_bsm or 'ROOT'}[{new_position}]")
+
+            # 实时保存到数据库
+            self.handle_drag_operation(drag_type, dragged_item, old_parent_bsm, new_parent_bsm)
+
+        # 替换dropEvent方法
+        self.treeWidget.dropEvent = custom_drop_event
+
+    def get_drag_type(self, old_parent_bsm, new_parent_bsm, old_position, new_position):
+        """判断拖拽操作类型"""
+        if old_parent_bsm == new_parent_bsm:
+            return "同级排序"  # 同级目录拖动改变顺序
+        elif old_parent_bsm == None and new_parent_bsm != None:
+            return "父变子"    # 父节点变子节点
+        elif old_parent_bsm != None and new_parent_bsm == None:
+            return "子变父"    # 子节点变父节点
+        else:
+            return "跨级移动"  # 不同层级间的移动
+
+    def handle_drag_operation(self, drag_type, dragged_item, old_parent_bsm, new_parent_bsm):
+        """处理不同类型的拖拽操作并实时保存"""
+        print(f"\n=== 开始处理拖拽操作: {drag_type} ===")
+
+        pg = self.get_db_connection()
+        if pg is None:
+            print("错误: 无法获取数据库连接")
+            QMessageBox.warning(None, "错误", "数据库连接失败")
+            return False
+
+        try:
+            # 测试数据库连接
+            pg.execute("SELECT 1")
+            test_result = pg.fetchone()
+            print(f"数据库连接测试: {test_result}")
+
+            # 显式开始事务
+            pg.execute("BEGIN")
+            print("事务已开始")
+
+            # 获取被拖动节点的BSM
+            dragged_bsm = dragged_item.text(1)
+            print(f"被拖动节点BSM: {dragged_bsm}")
+
+            # 查询拖拽前的数据库状态
+            pg.execute("SELECT pbsm, sort FROM t_vector_zyml WHERE bsm = %s", (dragged_bsm,))
+            before_result = pg.fetchone()
+            print(f"拖拽前数据库状态: {before_result}")
+
+            success = False
+
+            if drag_type == "同级排序":
+                # 同级目录拖动改变顺序:只需要重新排序同级的所有节点
+                success = self.update_sibling_sort_order(pg, new_parent_bsm)
+                print(f"同级排序操作结果: {success}")
+
+            elif drag_type in ["父变子", "子变父", "跨级移动"]:
+                # 这三种操作都需要更新父子关系
+                print(f"执行{drag_type}操作: 节点{dragged_bsm} 从 {old_parent_bsm or 'ROOT'} 移动到 {new_parent_bsm or 'ROOT'}")
+
+                # 1. 更新被拖动节点的父节点关系
+                update_sql = "UPDATE t_vector_zyml SET pbsm = %s WHERE bsm = %s"
+                print(f"执行SQL: {update_sql} with params: ({new_parent_bsm}, {dragged_bsm})")
+
+                pg.execute(update_sql, (new_parent_bsm, dragged_bsm))
+                affected_rows = pg.rowcount if hasattr(pg, 'rowcount') else 'unknown'
+                print(f"父节点关系更新完成, 影响行数: {affected_rows}")
+
+                # 验证更新是否成功
+                pg.execute("SELECT pbsm, sort FROM t_vector_zyml WHERE bsm = %s", (dragged_bsm,))
+                after_parent_update = pg.fetchone()
+                print(f"父节点更新后数据库状态: {after_parent_update}")
+
+                # 2. 更新新父节点下所有子节点的排序
+                success1 = self.update_sibling_sort_order(pg, new_parent_bsm)
+                print(f"新父节点排序更新结果: {success1}")
+
+                # 3. 更新原父节点下剩余子节点的排序
+                success2 = self.update_sibling_sort_order(pg, old_parent_bsm)
+                print(f"原父节点排序更新结果: {success2}")
+
+                success = success1 and success2
+
+            if success:
+                # 提交事务
+                pg.execute("COMMIT")
+                print("事务提交成功")
+
+                # 最终验证
+                verify_pg = self.get_db_connection()
+                if verify_pg:
+                    verify_pg.execute("SELECT pbsm, sort FROM t_vector_zyml WHERE bsm = %s", (dragged_bsm,))
+                    final_result = verify_pg.fetchone()
+                    print(f"最终验证结果: {final_result}")
+                    verify_pg.close()
+
+                print(f"拖拽操作保存成功: {drag_type}")
+                return True
+            else:
+                # 回滚事务
+                pg.execute("ROLLBACK")
+                print("操作失败,事务已回滚")
+                return False
+
+        except Exception as e:
+            # 回滚事务
+            try:
+                pg.execute("ROLLBACK")
+                print("异常发生,事务已回滚")
+            except:
+                print("回滚事务失败")
+
+            print(f"拖拽操作保存失败: {e}")
+            import traceback
+            print(f"详细错误信息: {traceback.format_exc()}")
+            QMessageBox.warning(None, "错误", f"保存失败: {str(e)}")
+            return False
+        finally:
+            pg.close()
+            print("数据库连接已关闭")
+            print("=== 拖拽操作处理结束 ===\n")
+
+    def update_sibling_sort_order(self, pg, parent_bsm):
+        """更新指定父节点下所有子节点的排序"""
+        try:
+            print(f"  >>> 开始更新父节点 '{parent_bsm or 'ROOT'}' 下的子节点排序...")
+
+            # 获取界面中的实际排序
+            sibling_items = []
+
+            if parent_bsm == '':  # 顶级节点
+                for i in range(self.treeWidget.topLevelItemCount()):
+                    item = self.treeWidget.topLevelItem(i)
+                    sibling_items.append((item.text(1), i, item.text(0)))  # (bsm, sort_order, name)
+            else:  # 子节点
+                parent_item = self.find_item_by_bsm(parent_bsm)
+                if parent_item:
+                    for i in range(parent_item.childCount()):
+                        item = parent_item.child(i)
+                        sibling_items.append((item.text(1), i, item.text(0)))  # (bsm, sort_order, name)
+                else:
+                    print(f"  !!! 未找到父节点: {parent_bsm}")
+                    return False
+
+            print(f"  >>> 找到 {len(sibling_items)} 个同级节点需要更新排序")
+
+            # 批量更新排序
+            update_count = 0
+            for bsm, sort_order, name in sibling_items:
+                update_sql = "UPDATE t_vector_zyml SET sort = %s WHERE bsm = %s"
+                print(f"    -> 更新节点 {name}({bsm}) 的排序为 {sort_order}")
+
+                pg.execute(update_sql, (sort_order, bsm))
+                affected_rows = pg.rowcount if hasattr(pg, 'rowcount') else 'unknown'
+                print(f"       影响行数: {affected_rows}")
+
+                # 验证单个更新是否成功
+                pg.execute("SELECT sort FROM t_vector_zyml WHERE bsm = %s", (bsm,))
+                verify_result = pg.fetchone()
+                if verify_result:
+                    actual_sort = verify_result[0]
+                    if actual_sort == sort_order:
+                        print(f"       ✓ 验证成功: {actual_sort}")
+                        update_count += 1
+                    else:
+                        print(f"       ✗ 验证失败: 期望{sort_order}, 实际{actual_sort}")
+                else:
+                    print(f"       ✗ 验证失败: 未找到记录")
+
+            print(f"  >>> 完成父节点 '{parent_bsm or 'ROOT'}' 下的排序更新,成功更新 {update_count}/{len(sibling_items)} 个节点")
+            return update_count == len(sibling_items)
+
+        except Exception as e:
+            print(f"  !!! 更新同级排序失败: {e}")
+            import traceback
+            print(f"  !!! 详细错误: {traceback.format_exc()}")
+            return False
+
+    def sort_tree_items(self, parent_item):
+        """对指定父节点下的子项进行排序"""
+        child_count = parent_item.childCount()
+        if child_count <= 1:
+            return
+
+        children = [parent_item.child(i) for i in range(child_count)]
+
+        def sort_key(item):
+            try:
+                return int(item.data(0, Qt.UserRole + 1))
+            except:
+                return 9999
+
+        children.sort(key=sort_key)
+
+        # 清除原有子项并重新添加
+        for i in reversed(range(child_count)):
+            parent_item.takeChild(i)
+        for child in children:
+            parent_item.addChild(child)
+
+    def initializeTreeData(self):
+        """初始化树形数据"""
+        if not self._tree_initialized:
+            try:
+                tree = Tree()
+                temp_tree = tree.initTreeWidget(self.dbcoon)
+
+                # 清空现有数据
+                self.treeWidget.clear()
+
+                # 添加新数据
+                for i in range(temp_tree.topLevelItemCount()):
+                    item = temp_tree.topLevelItem(i).clone()
+                    self.treeWidget.addTopLevelItem(item)
+                    self.sort_tree_items(item)  # 对一级节点排序其子项
+
+                # 设置拖拽功能
+                self.setup_tree_drag_drop()
+
+                self._tree_initialized = True
+                print("树形数据初始化完成,拖拽功能已启用")
+            except Exception as e:
+                print(f"初始化树形数据失败: {e}")
+                error_item = QTreeWidgetItem(self.treeWidget)
+                error_item.setText(0, "数据加载失败,请点击刷新重试")
+
+    def refreshTreeWidget(self):
+        """刷新树形控件"""
+        try:
+            print("开始刷新树形控件...")
+
+            # 清空并重新初始化
+            self.treeWidget.clear()
+            self._tree_initialized = False
+            self.initializeTreeData()
+
+            print("树形控件刷新完成")
+        except Exception as e:
+            print(f"刷新树形控件失败: {e}")
+            QMessageBox.warning(None, "错误", f"刷新失败: {str(e)}")
+
+    def test_database_connection(self):
+        """测试数据库连接和基本操作"""
+        print("=== 测试数据库连接 ===")
+        pg = self.get_db_connection()
+        if pg is None:
+            print("数据库连接失败")
+            return False
+
+        try:
+            # 测试基本查询
+            pg.execute("SELECT COUNT(*) FROM t_vector_zyml")
+            count = pg.fetchone()[0]
+            print(f"表中总记录数: {count}")
+
+            # 测试更新操作
+            pg.execute("SELECT bsm, pbsm, sort FROM t_vector_zyml LIMIT 1")
+            test_record = pg.fetchone()
+            if test_record:
+                bsm, pbsm, sort_val = test_record
+                print(f"测试记录: bsm={bsm}, pbsm={pbsm}, sort={sort_val}")
+
+                # 尝试更新(然后回滚)
+                pg.execute("BEGIN")
+                pg.execute("UPDATE t_vector_zyml SET sort = sort + 1 WHERE bsm = %s", (bsm,))
+                affected = pg.rowcount if hasattr(pg, 'rowcount') else 'unknown'
+                print(f"测试更新影响行数: {affected}")
+                pg.execute("ROLLBACK")
+                print("测试更新已回滚")
+
+            print("数据库连接测试通过")
+            return True
+
+        except Exception as e:
+            print(f"数据库连接测试失败: {e}")
+            return False
+        finally:
+            pg.close()
+
+    def on_tree_item_dropped(self):
+        self.save_tree_sort_order()
+
+
+
     def getNodeType(self, node):
         return node.text(2)
 
@@ -1176,82 +1607,7 @@ class Ui_ResourceDockWidget(object):
             iface.mapCanvas().setExtent(transformed_rect)
         iface.mapCanvas().refresh()
 
-    # === 以下为新增支持资源目录排序及保存的函数 ===
-
-    def save_tree_sort_order(self):
-        pg = self.get_db_connection()
-        if pg is None:
-            QMessageBox.warning(None, "错误", "数据库连接失败")
-            return
-
-        # 遍历顶层节点(一级目录)
-        for i in range(self.treeWidget.topLevelItemCount()):
-            top_item = self.treeWidget.topLevelItem(i)
-            top_bsm = top_item.text(1)
-            try:
-                pg.execute("UPDATE t_vector_zyml SET sort = %s WHERE bsm = %s", (i, top_bsm))
-            except Exception as e:
-                print(f"更新一级目录排序失败: {top_bsm} -> {e}")
-
-            # 遍历当前一级目录的子节点(二级目录或数据项)
-            for j in range(top_item.childCount()):
-                child_item = top_item.child(j)
-                child_bsm = child_item.text(1)
-                child_pbsm = child_item.text(2)  # pbsm
-                try:
-                    pg.execute("UPDATE t_vector_zyml SET sort = %s WHERE bsm = %s", (j, child_bsm))
-                except Exception as e:
-                    print(f"更新子节点排序失败: {child_bsm} -> {e}")
-
-    def sort_tree_items(self, parent_item):
-        child_count = parent_item.childCount()
-        if child_count <= 1:
-            return
-
-        children = [parent_item.child(i) for i in range(child_count)]
 
-        def sort_key(item):
-            try:
-                return int(item.data(0, Qt.UserRole + 1))
-            except:
-                return 9999
-
-        children.sort(key=sort_key)
-
-        for i in reversed(range(child_count)):
-            parent_item.takeChild(i)
-        for child in children:
-            parent_item.addChild(child)
-
-    def initializeTreeData(self):
-        if not self._tree_initialized:
-            try:
-                tree = Tree()
-                temp_tree = tree.initTreeWidget(self.dbcoon)
-
-                for i in range(temp_tree.topLevelItemCount()):
-                    item = temp_tree.topLevelItem(i).clone()
-                    self.treeWidget.addTopLevelItem(item)
-                    self.sort_tree_items(item)  # 对一级节点排序其子项
-
-                self._tree_initialized = True
-            except Exception as e:
-                print(f"初始化树形数据失败: {e}")
-                error_item = QTreeWidgetItem(self.treeWidget)
-                error_item.setText(0, "数据加载失败,请点击刷新重试")
-
-    def refreshTreeWidget(self):
-        try:
-            self.save_tree_sort_order()
-            self.treeWidget.clear()
-            self._tree_initialized = False
-            self.initializeTreeData()
-        except Exception as e:
-            print(f"刷新树形控件失败: {e}")
-            QMessageBox.warning(None, "错误", f"刷新失败: {str(e)}")
-
-    def on_tree_item_dropped(self):
-        self.save_tree_sort_order()
 
 
 

+ 21 - 8
python/plugins/ResourceTree/ui/TreeWidget.py

@@ -3,6 +3,7 @@ from PyQt5.QtCore import Qt
 from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem
 from .PostgreSQL import PostgreSQL
 
+
 class Tree:
     type = ""
 
@@ -10,16 +11,29 @@ class Tree:
         self.type = type
 
     def createTree(self, data, parent, parentid):
+        """递归创建树形结构"""
+        # 先获取当前层级的所有节点并按sort排序
+        current_level_nodes = []
         for row in data:
-            if (parentid is None and row['pbsm'] == '') or (parentid is not None and row['pbsm'] == parentid):
-                item = QTreeWidgetItem(parent)
-                item.setText(0, row['name'])
-                item.setText(1, row['bsm'])
-                item.setText(2, row['pbsm'])
-                item.setData(0, Qt.UserRole + 1, int(row['sort']) if row['sort'] is not None else 9999)
-                self.createTree(data, item, row['bsm'])
+            if (parentid == '' and row['pbsm'] == '') or (row['pbsm'] == parentid):
+                current_level_nodes.append(row)
+
+        # 按sort字段排序
+        current_level_nodes.sort(key=lambda x: int(x['sort']) if x['sort'] is not None else 9999)
+
+        # 创建当前层级的节点
+        for row in current_level_nodes:
+            item = QTreeWidgetItem(parent)
+            item.setText(0, row['name'])
+            item.setText(1, row['bsm'])
+            item.setText(2, row['pbsm'])
+            item.setData(0, Qt.UserRole + 1, int(row['sort']) if row['sort'] is not None else 9999)
+
+            # 递归创建子节点
+            self.createTree(data, item, row['bsm'])
 
     def initTreeWidget(self, dbcoon):
+        """初始化QTreeWidget"""
         try:
             print("初始化 QTreeWidget...")
             tree = QTreeWidget()
@@ -55,4 +69,3 @@ class Tree:
             print("initTreeWidget 初始化失败:", e)
             print(traceback.format_exc())
             raise e  # 抛出给外层捕获
-

二进制
python/plugins/ResourceTree/ui/__pycache__/PostgreSQL.cpython-312.pyc


二进制
python/plugins/ResourceTree/ui/__pycache__/ResourceTree.cpython-312.pyc


二进制
python/plugins/ResourceTree/ui/__pycache__/TreeWidget.cpython-312.pyc


部分文件因为文件数量过多而无法显示