ソースを参照

拖拽更新保存

Gogs 6 ヶ月 前
コミット
5f1d310518

ファイルの差分が大きいため隠しています
+ 0 - 0
QGIS/QGIS3.ini


+ 20 - 6
python/plugins/ResourceTree/ui/PostgreSQL.py

@@ -10,6 +10,8 @@ from typing import Optional
 import os
 import psycopg2
 import uuid
+from psycopg2 import sql
+
 
 
 class PostgreSQL:
@@ -21,7 +23,7 @@ class PostgreSQL:
             port: Optional[str] = "5432",  # default port during pg installation
             user: Optional[str] = "postgres",  # default user during pg installation
             password: Optional[str] = "postgis",  # default password during pg installation
-            dbname: Optional[str] = "real3d",  # default dbname during pg installation
+            dbname: Optional[str] = "datamanager",  # default dbname during pg installation
             schema: Optional[str] = None
     ):
         # 配置数据库连接参数并指定schema
@@ -84,14 +86,23 @@ class PostgreSQL:
         rows = self.cur.fetchall()
         return rows
 
+    def deleteVectorStorage(self, sjywz):
+        try:
+            self.cur.execute("DELETE FROM t_vector_storage WHERE sjywz = %s", (sjywz,))
+            self.conn.commit()
+        except Exception as e:
+            self.conn.rollback()
+            print(f"删除元数据记录失败: {e}")
+
     def dropTable(self, tablename):
         try:
             drop_sql = sql.SQL("DROP TABLE IF EXISTS {}").format(sql.Identifier(tablename))
             self.cur.execute(drop_sql)
+            self.conn.commit()  # 必须提交,否则删除无效
         except Exception as e:
+            self.conn.rollback()
             print(f"删除表 {tablename} 失败: {e}")
 
-
     def getZyml(self):
         """获取资源目录数据,按sort字段排序"""
         self.cur.execute("""
@@ -156,10 +167,13 @@ class PostgreSQL:
 
     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,))
+        try:
+            self.cur.execute("DELETE FROM t_vector_zyml WHERE pbsm = %s", (bsm,))
+            self.cur.execute("DELETE FROM t_vector_zyml WHERE bsm = %s", (bsm,))
+            self.conn.commit()  # 添加这一行:提交事务
+        except Exception as e:
+            self.conn.rollback()
+            raise e
 
     def renameZyml(self, id, name):
         self.cur.execute("update t_vector_zyml set name = '{}' where bsm = '{}'".format(name, id))

+ 128 - 143
python/plugins/ResourceTree/ui/ResourceTree.py

@@ -98,7 +98,7 @@ class Ui_ResourceDockWidget(object):
     redis_client = None
     tableattr = None
     dbcoon = {
-        "dbname": "real3d",
+        "dbname": "datamanager",
         "user": "postgres",
         "password": "postgis",
         "host": "192.168.60.2",
@@ -505,6 +505,8 @@ class Ui_ResourceDockWidget(object):
                 QMessageBox.warning(None, "错误", "数据库连接失败")
                 return
             pg.dropTable(id)
+            # 删除元数据记录
+            pg.deleteVectorStorage(id)
             self.delete_node_and_children_with_widgets(self.currentItem)
 
     def actionDeleteTableHandler1(self):
@@ -519,7 +521,7 @@ class Ui_ResourceDockWidget(object):
                 conn_params = {
                     'host': "192.168.60.2",
                     'port': "5432",
-                    'dbname': "real3d",
+                    'dbname': "datamanager",
                     'user': "postgres",
                     'password': "postgis"
                 }
@@ -557,19 +559,23 @@ class Ui_ResourceDockWidget(object):
         self.deleteMenu()
         self.currentItem = self.treeWidget.currentItem()
         id = self.getNodeId(self.currentItem)
-        # msgBox = QMessageBox()
-        # # 自定义按钮
-        # msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
-        # msgBox.setButtonText(QMessageBox.Yes, "确定")
-        # msgBox.setButtonText(QMessageBox.No, "取消")
-        question = QMessageBox.question(None, '删除确认', '确认删除此项目录吗?')
+        print(id)
+
+        question = QMessageBox.question(None, '删除确认', '确认删除此项目录吗?', QMessageBox.Yes | QMessageBox.No)
         if question == QMessageBox.Yes:
-            # **修改16: 使用优化的数据库连接**
             pg = self.get_db_connection()
             if pg is None:
                 QMessageBox.warning(None, "错误", "数据库连接失败")
                 return
-            pg.deleteZyml(id)
+
+            try:
+                pg.deleteZyml(id)  # 确保这个方法执行了 DELETE 操作
+            except Exception as e:
+                QMessageBox.critical(None, "删除失败", f"数据库删除操作失败: {e}")
+                pg.conn.rollback()
+                return
+
+            # 删除界面上的节点
             self.delete_node_and_children_with_widgets(self.currentItem)
 
     def delete_node_and_children_with_widgets(self, item):
@@ -708,6 +714,11 @@ class Ui_ResourceDockWidget(object):
 
         def custom_drop_event(event):
             """自定义拖拽放置事件处理"""
+
+            def is_data_node(layertype):
+                valid_layertypes = {"vector", "raster", "osgb", "table"}
+                return str(layertype).strip().lower() in valid_layertypes
+
             # 获取拖拽前的信息
             dragged_items = self.treeWidget.selectedItems()
             if not dragged_items:
@@ -715,54 +726,96 @@ class Ui_ResourceDockWidget(object):
 
             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
+            # ==== 获取拖拽目标节点 ====
+            drop_position = event.pos()
+            item_at_position = self.treeWidget.itemAt(drop_position)
+
+            # 确定拖拽行为
+            target_parent_item = None
+            drop_indicator = self.treeWidget.dropIndicatorPosition()
 
-            # 执行原始的拖拽操作
+            if item_at_position is None:
+                target_parent_item = None
+                print("拖拽目标: 顶层")
+            elif drop_indicator == self.treeWidget.OnItem:
+                target_parent_item = item_at_position
+                print(f"拖拽目标: 作为 '{item_at_position.text(0)}' 的子节点")
+            else:
+                target_parent_item = item_at_position.parent()
+                print(
+                    f"拖拽目标: 与 '{item_at_position.text(0)}' 成为兄弟节点,父节点是 '{target_parent_item.text(0) if target_parent_item else 'ROOT'}'")
+
+            # 获取节点类型信息
+            dragged_layertype = self.getNodeType(dragged_item)
+            target_layertype = self.getNodeType(target_parent_item) if target_parent_item else None
+
+            # 判断是否为数据节点
+            is_dragged_data_node = is_data_node(dragged_layertype)
+            is_target_data_node = is_data_node(target_layertype)
+
+            # ==== 拖拽限制 ====
+            if is_dragged_data_node:
+                if target_parent_item is None:
+                    QMessageBox.warning(None, "无效操作", "❌ 数据节点不能拖动为顶层节点,请拖入目录节点中。")
+                    return
+                if is_target_data_node:
+                    QMessageBox.warning(None, "无效操作", "❌ 数据节点不能拖动到其他数据节点下,请拖入目录节点中。")
+                    return
+                print("✅ 允许数据节点拖到目录节点下")
+            else:
+                if is_target_data_node:
+                    QMessageBox.warning(None, "无效操作", "❌ 目录节点不能拖动到数据节点下。")
+                    return
+                print("✅ 允许目录节点拖拽操作")
+
+            # ==== 执行拖拽 ====
             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}]")
+            if is_dragged_data_node:
+                print(
+                    f"数据节点 '{dragged_item.text(0)}' 父节点从 {old_parent_bsm or 'ROOT'} 移动到 {new_parent_bsm or 'ROOT'}")
+                self.handle_drag_operation("update_parent_only", dragged_item, old_parent_bsm, new_parent_bsm)
+            else:
+                # 仅目录节点需要记录排序
+                old_position = -1
+                new_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
+                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
+
+                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)
+                self.handle_drag_operation(drag_type, dragged_item, old_parent_bsm, new_parent_bsm)
 
-        # 替换dropEvent方法
+        # 替换 dropEvent 方法
         self.treeWidget.dropEvent = custom_drop_event
 
     def get_drag_type(self, old_parent_bsm, new_parent_bsm, old_position, new_position):
@@ -787,96 +840,66 @@ class Ui_ResourceDockWidget(object):
             return False
 
         try:
-            # 测试数据库连接
-            pg.execute("SELECT 1")
-            test_result = pg.fetchone()
-            print(f"数据库连接测试: {test_result}")
-
-            # 显式开始事务
+            pg.execute("SELECT 1")  # 测试连接
             pg.execute("BEGIN")
             print("事务已开始")
 
-            # 获取被拖动节点的BSM
             dragged_bsm = dragged_item.text(1)
-            print(f"被拖动节点BSM: {dragged_bsm}")
+            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}")
+            print(f"拖拽前状态: {pg.fetchone()}")
 
             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. 更新被拖动节点的父节点关系
+                # 更新 t_vector_zyml 的 pbsm
                 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. 更新新父节点下所有子节点的排序
+                print(f"更新 t_vector_zyml: bsm={dragged_bsm}, pbsm={new_parent_bsm}")
+
+                # ➕ 如果是数据节点,还要更新 t_vector_storage.xmlx 字段
+                dragged_layertype = self.getNodeType(dragged_item)
+                if dragged_layertype and dragged_layertype.strip() != "":
+                    update_storage_sql = "UPDATE base.t_vector_storage SET xmlx = %s WHERE name = %s"
+                    dragged_name = dragged_item.text(1)  # name = bsm
+                    print(f"同步更新 t_vector_storage.xmlx -> {dragged_name} 为目录 {new_parent_bsm}")
+                    pg.execute(update_storage_sql, (new_parent_bsm, dragged_name))
+                    pg.execute("SELECT xmlx FROM base.t_vector_storage WHERE name = %s", (dragged_name,))
+                    print(f"验证更新结果: {pg.fetchone()}")
+
+                # 同步排序
                 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}")
+                print("事务提交成功 ✅ 拖拽操作已保存")
                 return True
             else:
-                # 回滚事务
                 pg.execute("ROLLBACK")
-                print("操作失败,事务回滚")
+                print("事务回滚 ❌ 拖拽保存失败")
                 return False
 
         except Exception as e:
-            # 回滚事务
             try:
                 pg.execute("ROLLBACK")
-                print("异常发生,事务已回滚")
             except:
-                print("回滚事务失败")
-
-            print(f"拖拽操作保存失败: {e}")
+                pass
+            print(f"异常: {e}")
             import traceback
-            print(f"详细错误信息: {traceback.format_exc()}")
+            print(traceback.format_exc())
             QMessageBox.warning(None, "错误", f"保存失败: {str(e)}")
             return False
         finally:
             pg.close()
             print("数据库连接已关闭")
-            print("=== 拖拽操作处理结束 ===\n")
+            print("=== 拖拽处理结束 ===\n")
 
     def update_sibling_sort_order(self, pg, parent_bsm):
         """更新指定父节点下所有子节点的排序"""
@@ -997,44 +1020,6 @@ class Ui_ResourceDockWidget(object):
             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()
 
@@ -1230,7 +1215,7 @@ class Ui_ResourceDockWidget(object):
             # **修改20: 添加连接超时和错误处理**
             conn = psycopg2.connect(
                 host='192.168.60.2', port='5432',
-                dbname='real3d', user='postgres', password='postgis',
+                dbname='datamanager', user='postgres', password='postgis',
                 connect_timeout=10)  # 添加连接超时
             conn.autocommit = True
             cursor = conn.cursor()
@@ -1397,7 +1382,7 @@ class Ui_ResourceDockWidget(object):
             conn = psycopg2.connect(
                 host="192.168.60.2",
                 port="5432",
-                dbname="real3d",
+                dbname="datamanager",
                 user="postgres",
                 password="postgis",
                 connect_timeout=10
@@ -1424,7 +1409,7 @@ class Ui_ResourceDockWidget(object):
                 layer_name = table
 
             uri = (
-                f"dbname='real3d' host=192.168.60.2 port=5432 user='postgres' "
+                f"dbname='datamanager' host=192.168.60.2 port=5432 user='postgres' "
                 f"password='postgis' sslmode=disable table=\"{schema}\".\"{table}\" sql="
             )
 
@@ -1453,7 +1438,7 @@ class Ui_ResourceDockWidget(object):
             conn_params = {
                 'host': "192.168.60.2",
                 'port': "5432",
-                'dbname': "real3d",
+                'dbname': "datamanager",
                 'user': "postgres",
                 'password': "postgis",
                 'connect_timeout': 10

BIN
python/plugins/ResourceTree/ui/__pycache__/PostgreSQL.cpython-312.pyc


BIN
python/plugins/ResourceTree/ui/__pycache__/ResourceTree.cpython-312.pyc


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません