|
|
@@ -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
|