feat: 将动画启用控制权交给前端用户

后端不再主动启用动画,改为由前端通过开关控制动画状态
移除后端冗余的动画禁用逻辑,仅根据前端状态传递动画对象
This commit is contained in:
dmy
2026-03-03 16:09:03 +08:00
parent a65ce23cee
commit 07063ec638
4 changed files with 26 additions and 16 deletions

View File

@@ -105,9 +105,8 @@ def run_egm(para: Parameter, animation=None) -> dict:
avr_n_sf = 0 # 考虑电压的影响计算的跳闸率
ground_angels = para.ground_angels
# 动画对象:如果传入了 animation 则使用,否则不启用动画
# 注意:动画的启用由前端用户通过"启用动画"开关控制,后端不主动启用
animate = animation
if animate:
animate.enable(True) # 启用动画
# animate.show()
for ground_angel in ground_angels:
logger.info(f"地面倾角{ground_angel/math.pi*180:.3f}°")

View File

@@ -211,6 +211,7 @@ const animationApi = {
enabled.value = enable
onEnableChange(enable)
},
isEnabled: () => enabled.value,
initFig,
clear,
addRgLine,

View File

@@ -537,7 +537,12 @@ const calculate = async () => {
if (window.pywebview) {
// 后台线程启动计算,实时日志通过 addLogFromBackend 推送
// 结果通过 receiveResult 回调接收
await window.pywebview.api.calculate(params)
// 传递动画启用状态
const paramsWithAnimation = {
...params,
animation_enabled: animationRef.value?.isEnabled() ?? false
}
await window.pywebview.api.calculate(paramsWithAnimation)
// 不在这里设置 calculating = false等待 receiveResult 回调
} else {
// 开发模式下的模拟

View File

@@ -27,11 +27,13 @@ class WebAnimation:
"""
Web 动画类,将 Python 端的 Animation 调用映射到前端 JavaScript
对应 Animation.vue 的功能
注意:动画的启用/禁用由前端用户通过"启用动画"开关控制,
后端只负责发送绘制指令,前端根据 enabled 状态决定是否执行
"""
def __init__(self, window=None):
self._window = window
self._disable = True # 默认禁用
def set_window(self, window):
"""设置窗口对象"""
@@ -39,17 +41,16 @@ class WebAnimation:
def enable(self, enabled: bool):
"""
启用/禁用动画
对应 animation.py 的 enable 方法和 Animation.vue 的 enable 方法
启用/禁用动画(由前端用户控制)
此方法保留以兼容接口,但实际启用状态由前端控制
"""
self._disable = not enabled
if self._window:
js_code = f'if(window.animationApi){{window.animationApi.enable({str(enabled).lower()})}}'
self._window.evaluate_js(js_code)
def init_fig(self):
"""初始化画布"""
if self._disable or not self._window:
if not self._window:
return
js_code = 'if(window.animationApi){window.animationApi.initFig()}'
self._window.evaluate_js(js_code)
@@ -59,7 +60,7 @@ class WebAnimation:
添加地线保护弧RS 圆)
对应 animation.py 的 add_rs 方法
"""
if self._disable or not self._window:
if not self._window:
return
js_code = f'if(window.animationApi){{window.animationApi.addRs({rs}, {rs_x}, {rs_y})}}'
self._window.evaluate_js(js_code)
@@ -69,7 +70,7 @@ class WebAnimation:
添加导线暴露弧RC 圆)
对应 animation.py 的 add_rc 方法
"""
if self._disable or not self._window:
if not self._window:
return
js_code = f'if(window.animationApi){{window.animationApi.addRc({rc}, {rc_x}, {rc_y})}}'
self._window.evaluate_js(js_code)
@@ -82,7 +83,7 @@ class WebAnimation:
Args:
line_func: 一个函数,接收 x 返回 y
"""
if self._disable or not self._window:
if not self._window:
return
# 生成线上的点,传递给前端
# 由于无法直接传递函数,我们预先计算一些点
@@ -111,7 +112,7 @@ class WebAnimation:
添加暴露弧区域(两条红线)
对应 animation.py 的 add_expose_area 方法
"""
if self._disable or not self._window:
if not self._window:
return
js_code = f'''if(window.animationApi){{
window.animationApi.addExposeArea(
@@ -124,7 +125,7 @@ class WebAnimation:
def clear(self):
"""清除画布"""
if self._disable or not self._window:
if not self._window:
return
js_code = 'if(window.animationApi){window.animationApi.clear()}'
self._window.evaluate_js(js_code)
@@ -134,7 +135,7 @@ class WebAnimation:
暂停并刷新
对应 animation.py 的 pause 方法
"""
if self._disable or not self._window:
if not self._window:
return
js_code = 'if(window.animationApi){window.animationApi.pause()}'
self._window.evaluate_js(js_code)
@@ -341,8 +342,12 @@ class EGMWebApp:
logger.info("开始执行 EGM 计算...")
# 调用 main.py 的核心计算函数,传递 animation 对象
result = run_egm(para, self.animation)
# 根据前端动画启用状态决定是否传递 animation 对象
animation_enabled = params.get('animation_enabled', False)
animation_obj = self.animation if animation_enabled else None
# 调用 main.py 的核心计算函数
result = run_egm(para, animation_obj)
self.add_log("info", "EGM 计算完成")