Compare commits

..

4 Commits

Author SHA1 Message Date
dmy
c54ad369a4 feat: 新增电价参数配置功能
- 在Excel模板中新增电价参数项(默认0.4元/kWh)
- GUI界面显示电价参数,支持从Excel读取
- 核心计算逻辑集成电价参数,为后续经济性分析做准备
- 支持自定义电价或使用默认值
2026-01-06 11:43:41 +08:00
dmy
86e0e21b58 feat: 方案对比结果表格新增总长度列
- 在方案对比结果中新增'总长度(m)'列
- 自动计算每个方案的海缆总长度
- 支持按总长度排序,方便方案比选
2026-01-06 11:25:43 +08:00
dmy
60a9a57cee feat: 方案对比结果区域改为可折叠显示
- 将方案对比结果卡片改为可折叠的expansion组件
- 添加analytics图标,提升界面美观度
- 默认展开状态,方便用户查看
- 优化卡片样式,移除内边距并添加overflow-hidden
2026-01-06 11:16:53 +08:00
dmy
db6114ef57 feat: 优化电缆规格显示和更新项目配置
- GUI电缆规格表格新增'是否为可选'列,支持显示可选电缆标识
- 修复信息容器初始化问题,确保提示文本正确显示
- 更新使用说明文档,修正适用对象和技术支持信息
- 添加项目配置文件(.gitignore, .python-version, pyproject.toml, uv.lock)
- 添加版本管理脚本(make_version.py)
- 添加Excel数据文件和使用说明PDF文档
2026-01-06 10:01:11 +08:00
12 changed files with 2423 additions and 48 deletions

14
.gitignore vendored Normal file
View File

@@ -0,0 +1,14 @@
# Python-generated files
__pycache__/
*.py[oc]
build/
dist/
wheels/
*.egg-info
# Virtual environments
.venv
# Build artifacts
version_info.txt
version.py

1
.python-version Normal file
View File

@@ -0,0 +1 @@
cpython-3.12.12-windows-x86_64-none

View File

@@ -53,7 +53,8 @@ def create_template(output_file='windfarm_template.xlsx'):
# Create System Parameters data # Create System Parameters data
param_data = [ param_data = [
{'Parameter': 'Voltage (kV) / 电压 (kV)', 'Value': 66}, {'Parameter': 'Voltage (kV) / 电压 (kV)', 'Value': 66},
{'Parameter': 'Power Factor / 功率因数', 'Value': 0.95} {'Parameter': 'Power Factor / 功率因数', 'Value': 0.95},
{'Parameter': 'Electricity Price (元/kWh) / 电价 (元/kWh)', 'Value': 0.4}
] ]
df_params = pd.DataFrame(param_data) df_params = pd.DataFrame(param_data)

118
gui.py
View File

@@ -128,6 +128,21 @@ def index():
pf_str += " (默认)" pf_str += " (默认)"
params_text.append(pf_str) params_text.append(pf_str)
# 获取电价
ep = 0.4 # Default
is_default_ep = True
if (
state.get("system_params")
and "electricity_price" in state["system_params"]
):
ep = state["system_params"]["electricity_price"]
is_default_ep = False
ep_str = f"电价: {ep} 元/kWh"
if is_default_ep:
ep_str += " (默认)"
params_text.append(ep_str)
for p in params_text: for p in params_text:
ui.chip(p, icon="bolt").props("outline color=primary") ui.chip(p, icon="bolt").props("outline color=primary")
@@ -164,6 +179,12 @@ def index():
"field": "cost", "field": "cost",
"align": "center", "align": "center",
}, },
{
"name": "is_optional",
"label": "是否为可选",
"field": "is_optional",
"align": "center",
},
] ]
rows = [] rows = []
for spec in state["cable_specs"]: for spec in state["cable_specs"]:
@@ -174,6 +195,7 @@ def index():
"capacity": spec[1], "capacity": spec[1],
"resistance": spec[2], "resistance": spec[2],
"cost": spec[3], "cost": spec[3],
"is_optional": "Y" if len(spec) > 4 and spec[4] else "",
} }
) )
ui.table(columns=columns, rows=rows).classes("w-full").props( ui.table(columns=columns, rows=rows).classes("w-full").props(
@@ -791,10 +813,14 @@ def index():
elif "No Max" in original_name: elif "No Max" in original_name:
note += "不包含可选电缆型号,且可使用的最大截面电缆降一档截面。" note += "不包含可选电缆型号,且可使用的最大截面电缆降一档截面。"
# 计算总长度
total_length = sum(d["length"] for d in res["eval"]["details"])
row_dict = { row_dict = {
"name": name_display, "name": name_display,
"cost_wan": f"{res['cost'] / 10000:.2f}", "cost_wan": f"{res['cost'] / 10000:.2f}",
"loss_kw": f"{res['loss']:.2f}", "loss_kw": f"{res['loss']:.2f}",
"total_length": f"{total_length:.2f}",
"note": note, "note": note,
"original_name": res["name"], "original_name": res["name"],
} }
@@ -914,50 +940,56 @@ def index():
.style("max-height: 400px; overflow-y: auto;") .style("max-height: 400px; overflow-y: auto;")
): ):
refs["info_container"] = ui.column().classes("w-full") refs["info_container"] = ui.column().classes("w-full")
ui.label("请上传 Excel 文件以查看系统参数和电缆规格...").classes( with refs["info_container"]:
"text-gray-500 italic" ui.label("请上传 Excel 文件以查看系统参数和电缆规格...").classes(
) "text-gray-500 italic"
)
with ui.card().classes("w-full p-4 shadow-md"): with ui.card().classes("w-full p-0 shadow-md overflow-hidden"):
ui.label("方案对比结果 (点击行查看拓扑详情)").classes( with ui.expansion(
"text-xl font-semibold mb-2" "方案对比结果 (点击行查看拓扑详情)", icon="analytics", value=True
) ).classes("w-full").props("header-class=\"text-xl font-semibold\""):
columns = [ columns = [
{ {
"name": "name", "name": "name",
"label": "方案名称", "label": "方案名称",
"field": "name", "field": "name",
"required": True, "required": True,
"align": "left", "align": "left",
}, },
{ {
"name": "cost_wan", "name": "cost_wan",
"label": "总投资 (万元)", "label": "总投资 (万元)",
"field": "cost_wan", "field": "cost_wan",
"sortable": True, "sortable": True,
}, },
{ {
"name": "loss_kw", "name": "loss_kw",
"label": "线损 (kW)", "label": "线损 (kW)",
"field": "loss_kw", "field": "loss_kw",
"sortable": True, "sortable": True,
}, },
{ {
"name": "note", "name": "total_length",
"label": "备注", "label": "总长度 (m)",
"field": "note", "field": "total_length",
"align": "left", "sortable": True,
}, },
] {
# 使用内置的 selection='single' 结合行点击事件实现背景高亮 "name": "note",
# 这样可以完全由 Python 事件逻辑控制,不依赖 CSS 伪类 "label": "备注",
refs["results_table"] = ui.table( "field": "note",
columns=columns, "align": "left",
rows=[], }, ]
selection="single", # 使用内置的 selection='single' 结合行点击事件实现背景高亮
row_key="original_name", # 这样可以完全由 Python 事件逻辑控制,不依赖 CSS 伪类
).classes("w-full hide-selection-column") refs["results_table"] = ui.table(
refs["results_table"].on("row-click", handle_row_click) columns=columns,
rows=[],
selection="single",
row_key="original_name",
).classes("w-full hide-selection-column")
refs["results_table"].on("row-click", handle_row_click)
with ui.card().classes("w-full p-4 shadow-md"): with ui.card().classes("w-full p-4 shadow-md"):
ui.label("拓扑可视化").classes("text-xl font-semibold mb-2") ui.label("拓扑可视化").classes("text-xl font-semibold mb-2")
refs["plot_container"] = ui.column().classes("w-full items-center") refs["plot_container"] = ui.column().classes("w-full items-center")

11
main.py
View File

@@ -18,6 +18,7 @@ plt.rcParams['axes.unicode_minus'] = False
# 常量定义 # 常量定义
VOLTAGE_LEVEL = 66000 # 66kV VOLTAGE_LEVEL = 66000 # 66kV
POWER_FACTOR = 0.95 POWER_FACTOR = 0.95
ELECTRICITY_PRICE = 0.4 # 元/kWh
# 1. 生成风电场数据(实际应用中替换为真实坐标) # 1. 生成风电场数据(实际应用中替换为真实坐标)
def generate_wind_farm_data(n_turbines=30, seed=42, layout='random', spacing=800): def generate_wind_farm_data(n_turbines=30, seed=42, layout='random', spacing=800):
@@ -224,8 +225,15 @@ def load_data_from_excel(file_path):
system_params['voltage'] = val system_params['voltage'] = val
elif 'factor' in key or '功率因数' in key: elif 'factor' in key or '功率因数' in key:
system_params['power_factor'] = val system_params['power_factor'] = val
elif 'price' in key or '电价' in key:
system_params['electricity_price'] = val
except ValueError: except ValueError:
pass pass
# 设置默认电价(如果参数表中未提供)
if 'electricity_price' not in system_params:
system_params['electricity_price'] = ELECTRICITY_PRICE
if system_params: if system_params:
print(f"成功加载系统参数: {system_params}") print(f"成功加载系统参数: {system_params}")
except Exception as e: except Exception as e:
@@ -1107,7 +1115,8 @@ def compare_design_methods(excel_path=None, n_clusters_override=None, interactiv
voltage = system_params.get('voltage', VOLTAGE_LEVEL) voltage = system_params.get('voltage', VOLTAGE_LEVEL)
power_factor = system_params.get('power_factor', POWER_FACTOR) power_factor = system_params.get('power_factor', POWER_FACTOR)
print(f"使用的系统参数: 电压={voltage} V, 功率因数={power_factor}") electricity_price = system_params.get('electricity_price', ELECTRICITY_PRICE)
print(f"使用的系统参数: 电压={voltage} V, 功率因数={power_factor}, 电价={electricity_price} 元/kWh")
# 准备三种电缆方案 # 准备三种电缆方案
# 原始 specs 是 5 元素元组: (section, capacity, resistance, cost, is_optional) # 原始 specs 是 5 元素元组: (section, capacity, resistance, cost, is_optional)

55
make_version.py Normal file
View File

@@ -0,0 +1,55 @@
# make_version.py
import datetime
import os
def create_version_file():
# 1. 生成版本号 (示例:使用 年.月.日.0)
today = datetime.date.today()
# 格式:(2026, 1, 5, 0)
ver_tuple = (today.year, today.month, today.day, 0)
ver_str = f"{today.year}.{today.month}.{today.day}.0"
# 2. 定义版本信息结构 (PyInstaller 格式)
# 语言代码 2052 = 简体中文, 字符集 1200 = Unicode
content = f"""# UTF-8
VSVersionInfo(
ffi=FixedFileInfo(
filevers={ver_tuple},
prodvers={ver_tuple},
mask=0x3f,
flags=0x0,
OS=0x40004,
fileType=0x1,
subtype=0x0,
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
u'080404b0',
[StringStruct(u'CompanyName', u'中能建西北院海上能源业务开发部'),
StringStruct(u'FileDescription', u'海上风电场集电线路设计优化系统'),
StringStruct(u'FileVersion', u'{ver_str}'),
StringStruct(u'InternalName', u'WindFarmOptimizer'),
StringStruct(u'LegalCopyright', u'Copyright (c) {today.year}'),
StringStruct(u'OriginalFilename', u'海上风电场集电线路设计优化系统.exe'),
StringStruct(u'ProductName', u'海上风电场集电线路设计优化系统'),
StringStruct(u'ProductVersion', u'{ver_str}')])
]),
VarFileInfo([VarStruct(u'Translation', [2052, 1200])])
]
)
"""
with open("version_info.txt", "w", encoding="utf-8") as f:
f.write(content)
# 3. 同时生成一个 python 文件供 gui.py 调用
with open("version.py", "w", encoding="utf-8") as f:
f.write(f'VERSION = "v{ver_str}"\n')
print(f"已生成版本信息文件: version_info.txt 和 version.py (版本: v{ver_str})")
if __name__ == "__main__":
create_version_file()

23
pyproject.toml Normal file
View File

@@ -0,0 +1,23 @@
[project]
name = "windfarm"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"ezdxf>=1.4.3",
"matplotlib>=3.10.8",
"networkx>=3.6.1",
"nicegui>=3.4.1",
"numpy>=2.4.0",
"openpyxl>=3.1.5",
"pandas>=2.3.3",
"pywebview>=6.1",
"scikit-learn>=1.8.0",
"scipy>=1.16.3",
]
[dependency-groups]
dev = [
"pyinstaller>=6.17.0",
]

2240
uv.lock generated Normal file

File diff suppressed because it is too large Load Diff

0
使用说明/pandoc Normal file
View File

View File

@@ -1,7 +1,7 @@
# 海上风电场集电线路设计优化软件 - 操作手册 # 海上风电场集电线路设计优化软件 - 操作手册
**文档版本:** v1.0 **文档版本:** v1.0
**适用对象:** 海上能源业务开发部 - 电气专业 **适用对象:** 海上能源业务开发部 - 电气专业
**编制日期:** 2026年1月5日 **编制日期:** 2026年1月5日
--- ---
@@ -10,7 +10,7 @@
海上风电集电线路作为风电机组与海上升压站的关键连接纽带,其优化设计对提升风电场全生命周期经济性及降低环境影响具有核心意义,不仅能通过拓扑与路由优化减少建设运维成本、降低线路损耗,还能为深远海、大容量风电场开发提供技术支撑。该优化工作面临拓扑与载流量多约束耦合的技术瓶颈,需综合运用数字化技术、先进优化算法进行应对。 海上风电集电线路作为风电机组与海上升压站的关键连接纽带,其优化设计对提升风电场全生命周期经济性及降低环境影响具有核心意义,不仅能通过拓扑与路由优化减少建设运维成本、降低线路损耗,还能为深远海、大容量风电场开发提供技术支撑。该优化工作面临拓扑与载流量多约束耦合的技术瓶颈,需综合运用数字化技术、先进优化算法进行应对。
本软件专为海上风电场内集电系统35kV/66kV/110kV设计旨在通过多种先进的拓扑优化算法如Esau-Williams、MST、旋转扫描法辅助电气工程师快速完成集电线路的路径规划与经济性比选。 本软件专为海上风电场内集电系统35kV/66kV/110kV设计旨在通过多种先进的拓扑优化算法如Esau-Williams、MST、旋转扫描法辅助电气专业快速完成集电线路的路径规划与经济性比选。
软件能够根据风机坐标、海缆载流量及造价数据,自动计算并生成线损最小、投资最优的接线方案,并支持一键导出 CAD 图纸和海缆长度。 软件能够根据风机坐标、海缆载流量及造价数据,自动计算并生成线损最小、投资最优的接线方案,并支持一键导出 CAD 图纸和海缆长度。
@@ -162,4 +162,4 @@ A: 软件算法以不超过额定载流量为约束条件(默认允许 100%
A: 请双击鼠标滚轮Zoom Extents全屏显示。由于风机坐标通常是大地坐标数值很大如果 CAD 当前视口在 (0,0) 附近,可能会找不到图形。 A: 请双击鼠标滚轮Zoom Extents全屏显示。由于风机坐标通常是大地坐标数值很大如果 CAD 当前视口在 (0,0) 附近,可能会找不到图形。
--- ---
**技术支持:** 海上能源业务开发部 - 数字化小组 **技术支持:** 海上能源业务开发部 - 杜孟远

Binary file not shown.