mirror of
https://github.com/opendatalab/MinerU.git
synced 2026-09-21 12:42:22 +08:00
feat: enhance visibility management for client options and image analysis based on backend selection
This commit is contained in:
+47
-39
@@ -852,11 +852,23 @@ def is_image_analysis_option_visible(backend, effort=DEFAULT_HYBRID_EFFORT):
|
||||
return False
|
||||
|
||||
|
||||
def is_ocr_options_visible(backend):
|
||||
"""判断 OCR 语言和强制 OCR 选项是否展示;Hybrid/VLM 已不需要用户指定语言。"""
|
||||
def is_ocr_language_option_visible(backend: object) -> bool:
|
||||
"""判断 OCR 语言选项是否展示;lang 参数只对 pipeline 后端生效。"""
|
||||
return backend == "pipeline"
|
||||
|
||||
|
||||
def is_force_ocr_option_visible(backend: object) -> bool:
|
||||
"""判断强制 OCR 开关是否展示;Hybrid 不需要 lang,但仍支持强制 OCR。"""
|
||||
if not isinstance(backend, str):
|
||||
return False
|
||||
return backend == "pipeline" or backend.startswith("hybrid")
|
||||
|
||||
|
||||
def frontend_managed_initial_visibility(is_visible: bool):
|
||||
"""转换前端托管显隐控件的初始状态;hidden 会保留 DOM 挂载,避免后续重新挂载。"""
|
||||
return True if is_visible else "hidden"
|
||||
|
||||
|
||||
def should_use_client_side_output_generation(client_side_output_generation):
|
||||
"""判断当前 Gradio 任务是否需要在客户端生成最终输出。"""
|
||||
return client_side_output_generation
|
||||
@@ -1729,22 +1741,25 @@ def main(ctx,
|
||||
def get_backend_info(backend_choice):
|
||||
return i18n(select_backend_info_key(backend_choice))
|
||||
|
||||
# 更新界面函数
|
||||
def update_interface(backend_choice, effort_choice):
|
||||
def build_interface_updates(backend_choice, effort_choice):
|
||||
"""构建 Gradio 后端联动更新,保证所有事件复用同一套显隐规则。"""
|
||||
formula_label_update = gr.update(label=get_formula_label(backend_choice), info=get_formula_info(backend_choice))
|
||||
backend_info_update = gr.update(info=get_backend_info(backend_choice))
|
||||
effort_update = gr.update(visible=is_effort_option_visible(backend_choice))
|
||||
ocr_options_update = gr.update(visible=is_ocr_options_visible(backend_choice))
|
||||
ocr_language_options_update = gr.update(visible=is_ocr_language_option_visible(backend_choice))
|
||||
force_ocr_update = gr.update(visible=is_force_ocr_option_visible(backend_choice))
|
||||
|
||||
return ocr_options_update, formula_label_update, backend_info_update, effort_update
|
||||
return (
|
||||
ocr_language_options_update,
|
||||
force_ocr_update,
|
||||
formula_label_update,
|
||||
backend_info_update,
|
||||
effort_update,
|
||||
)
|
||||
|
||||
def update_client_options_visibility(backend_choice):
|
||||
"""仅更新服务器地址控件显隐,避免隐藏 Row 首次切换到 http-client 时挂载失败。"""
|
||||
return gr.update(visible=is_http_client_backend(backend_choice))
|
||||
|
||||
def update_image_analysis_visibility(backend_choice, effort_choice):
|
||||
"""仅更新图片分析控件显隐;实际开关由 Hybrid 后端兜底处理。"""
|
||||
return gr.update(visible=is_image_analysis_option_visible(backend_choice, effort_choice))
|
||||
def update_interface(backend_choice, effort_choice):
|
||||
"""更新可由 Gradio 稳定管理的基础界面项,易重挂载的控件交给前端状态类处理。"""
|
||||
return build_interface_updates(backend_choice, effort_choice)
|
||||
|
||||
del kwargs
|
||||
_gradio_local_api_server.configure(
|
||||
@@ -1818,8 +1833,12 @@ def main(ctx,
|
||||
label=i18n("backend"),
|
||||
value=preferred_option,
|
||||
info=get_backend_info(preferred_option),
|
||||
elem_classes=["mineru-backend-select"],
|
||||
)
|
||||
with gr.Row(visible=is_http_client_backend(preferred_option)) as client_options:
|
||||
with gr.Row(
|
||||
visible=frontend_managed_initial_visibility(is_http_client_backend(preferred_option)),
|
||||
elem_classes=["mineru-client-options"],
|
||||
) as client_options:
|
||||
url = gr.Textbox(
|
||||
label=i18n("server_url"),
|
||||
value='http://localhost:30000',
|
||||
@@ -1925,8 +1944,11 @@ def main(ctx,
|
||||
image_analysis = gr.Checkbox(
|
||||
label=i18n("image_analysis_enable"),
|
||||
value=True,
|
||||
visible=is_image_analysis_option_visible(preferred_option, DEFAULT_HYBRID_EFFORT),
|
||||
visible=frontend_managed_initial_visibility(
|
||||
is_image_analysis_option_visible(preferred_option, DEFAULT_HYBRID_EFFORT)
|
||||
),
|
||||
info=i18n("image_analysis_info"),
|
||||
elem_classes=["mineru-image-analysis-option"],
|
||||
)
|
||||
hybrid_effort = gr.Radio(
|
||||
list(HYBRID_EFFORT_CHOICES),
|
||||
@@ -1934,15 +1956,21 @@ def main(ctx,
|
||||
value=DEFAULT_HYBRID_EFFORT,
|
||||
visible=is_effort_option_visible(preferred_option),
|
||||
info=i18n("hybrid_effort_info"),
|
||||
elem_classes=["mineru-hybrid-effort"],
|
||||
)
|
||||
with gr.Group(visible=is_ocr_options_visible(preferred_option)) as ocr_options:
|
||||
with gr.Group(visible=is_ocr_language_option_visible(preferred_option)) as ocr_language_options:
|
||||
language = gr.Dropdown(
|
||||
all_lang,
|
||||
label=i18n("ocr_language"),
|
||||
value='ch (Chinese, English, Chinese Traditional)',
|
||||
info=i18n("ocr_language_info"),
|
||||
)
|
||||
is_ocr = gr.Checkbox(label=i18n("force_ocr"), value=False, info=i18n("force_ocr_info"))
|
||||
is_ocr = gr.Checkbox(
|
||||
label=i18n("force_ocr"),
|
||||
value=False,
|
||||
visible=is_force_ocr_option_visible(preferred_option),
|
||||
info=i18n("force_ocr_info"),
|
||||
)
|
||||
|
||||
# 添加事件处理
|
||||
_private_api_kwargs = (
|
||||
@@ -1953,34 +1981,14 @@ def main(ctx,
|
||||
backend.change(
|
||||
fn=update_interface,
|
||||
inputs=[backend, hybrid_effort],
|
||||
outputs=[ocr_options, formula_enable, backend, hybrid_effort],
|
||||
**_private_api_kwargs
|
||||
)
|
||||
# 服务器地址区域单独更新,避免 Gradio load 多输出影响首次切换到 http-client 的隐藏 Row 挂载。
|
||||
backend.change(
|
||||
fn=update_client_options_visibility,
|
||||
inputs=backend,
|
||||
outputs=client_options,
|
||||
**_private_api_kwargs
|
||||
)
|
||||
# 图片分析显隐单独更新,避免 Gradio load 多输出影响首次 medium -> high 的隐藏组件挂载。
|
||||
backend.change(
|
||||
fn=update_image_analysis_visibility,
|
||||
inputs=[backend, hybrid_effort],
|
||||
outputs=image_analysis,
|
||||
outputs=[ocr_language_options, is_ocr, formula_enable, backend, hybrid_effort],
|
||||
**_private_api_kwargs
|
||||
)
|
||||
# 添加demo.load事件,在页面加载时触发一次界面更新
|
||||
demo.load(
|
||||
fn=update_interface,
|
||||
inputs=[backend, hybrid_effort],
|
||||
outputs=[ocr_options, formula_enable, backend, hybrid_effort],
|
||||
**_private_api_kwargs
|
||||
)
|
||||
hybrid_effort.change(
|
||||
fn=update_image_analysis_visibility,
|
||||
inputs=[backend, hybrid_effort],
|
||||
outputs=image_analysis,
|
||||
outputs=[ocr_language_options, is_ocr, formula_enable, backend, hybrid_effort],
|
||||
**_private_api_kwargs
|
||||
)
|
||||
clear_bu.add([input_file, md, doc_show, md_text, content_list_json, output_file, is_ocr, office_html, status_panel])
|
||||
|
||||
Vendored
+10
@@ -169,6 +169,16 @@ body.mineru-advanced-popover-open .mineru-advanced-popover {
|
||||
visibility: hidden !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
.mineru-client-options,
|
||||
.mineru-image-analysis-option {
|
||||
display: none !important;
|
||||
}
|
||||
body.mineru-show-client-options .gradio-container .contain .mineru-client-options.mineru-client-options {
|
||||
display: flex !important;
|
||||
}
|
||||
body.mineru-show-image-analysis .gradio-container .contain .mineru-image-analysis-option.mineru-image-analysis-option {
|
||||
display: block !important;
|
||||
}
|
||||
.mineru-advanced-popover ul.options {
|
||||
border-radius: 8px !important;
|
||||
box-shadow: var(--mineru-popover-dropdown-shadow) !important;
|
||||
|
||||
Vendored
+50
@@ -6,6 +6,8 @@
|
||||
window.__mineruAdvancedPopoverInstalled = POPOVER_SCRIPT_VERSION;
|
||||
|
||||
const POPOVER_OPEN_CLASS = "mineru-advanced-popover-open";
|
||||
const CLIENT_OPTIONS_VISIBLE_CLASS = "mineru-show-client-options";
|
||||
const IMAGE_ANALYSIS_VISIBLE_CLASS = "mineru-show-image-analysis";
|
||||
const OFFICE_PREVIEW_NOTICE_STORAGE_KEY = "mineru.officePreviewNoticeIgnored";
|
||||
const OPEN_DELAY_MS = 120;
|
||||
const CLOSE_DELAY_MS = 280;
|
||||
@@ -91,6 +93,7 @@
|
||||
const refreshMineruCustomHtml = () => {
|
||||
localizeMineruCustomText();
|
||||
applyOfficePreviewNoticePreference();
|
||||
refreshMineruOptionVisibility();
|
||||
};
|
||||
|
||||
// 兼容 Gradio 将 elem_classes 挂到按钮自身或按钮外层容器的两种 DOM 结构。
|
||||
@@ -98,10 +101,51 @@
|
||||
"button.mineru-advanced-open, .mineru-advanced-open button, .mineru-advanced-open"
|
||||
);
|
||||
const findPopover = () => document.querySelector(".mineru-advanced-popover");
|
||||
const findBackendRoot = () => document.querySelector(".mineru-backend-select");
|
||||
const findEffortRoot = () => document.querySelector(".mineru-hybrid-effort");
|
||||
let openTimer = null;
|
||||
let closeTimer = null;
|
||||
let visibilityTimer = null;
|
||||
let hoverHandlersInstalled = false;
|
||||
|
||||
// 读取 Gradio Dropdown 当前值;value 属性比可见文本更稳定,避免中英文文案影响判断。
|
||||
const getBackendValue = () => {
|
||||
const backendRoot = findBackendRoot();
|
||||
const backendControl = backendRoot?.querySelector('[role="listbox"]');
|
||||
return (backendControl?.value || backendControl?.textContent || "").trim();
|
||||
};
|
||||
|
||||
// 读取 Hybrid effort 当前值;控件在非 hybrid 后端会被 Gradio 隐藏,缺失时按空值处理。
|
||||
const getEffortValue = () => {
|
||||
const effortRoot = findEffortRoot();
|
||||
const checkedRadio = effortRoot?.querySelector(
|
||||
'input[type="radio"]:checked, input[type="radio"][aria-checked="true"]'
|
||||
);
|
||||
return (checkedRadio?.value || "").trim();
|
||||
};
|
||||
|
||||
// 根据当前 backend/effort 刷新前端状态类,避免依赖 Gradio 重新挂载隐藏组件。
|
||||
const refreshMineruOptionVisibility = () => {
|
||||
const backend = getBackendValue();
|
||||
const effort = getEffortValue();
|
||||
const showClientOptions = backend.endsWith("http-client");
|
||||
const showImageAnalysis = backend.startsWith("vlm")
|
||||
|| (backend.startsWith("hybrid") && effort === "high");
|
||||
|
||||
document.body.classList.toggle(CLIENT_OPTIONS_VISIBLE_CLASS, showClientOptions);
|
||||
document.body.classList.toggle(IMAGE_ANALYSIS_VISIBLE_CLASS, showImageAnalysis);
|
||||
if (document.body.classList.contains(POPOVER_OPEN_CLASS)) {
|
||||
positionPopover();
|
||||
}
|
||||
};
|
||||
|
||||
// Gradio 控件会异步写回 value,延后一帧再读可以覆盖 Dropdown option 点击和 Radio 切换。
|
||||
const queueMineruOptionVisibilityRefresh = () => {
|
||||
requestAnimationFrame(() => {
|
||||
refreshMineruOptionVisibility();
|
||||
requestAnimationFrame(refreshMineruOptionVisibility);
|
||||
});
|
||||
};
|
||||
const findUploadFileInput = () => {
|
||||
const uploadRoot = document.querySelector(".mineru-upload-file");
|
||||
if (!uploadRoot) {
|
||||
@@ -450,6 +494,7 @@
|
||||
if (!(target instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
queueMineruOptionVisibilityRefresh();
|
||||
if (target.closest(".office-preview-ignore-forever")) {
|
||||
const notice = target.closest(".office-preview-notice");
|
||||
if (setOfficePreviewNoticeIgnored()) {
|
||||
@@ -488,11 +533,16 @@
|
||||
|
||||
document.addEventListener("input", (event) => {
|
||||
const target = event.target;
|
||||
queueMineruOptionVisibilityRefresh();
|
||||
if (target instanceof Element && target.closest(".mineru-advanced-popover")) {
|
||||
queueDropdownPosition();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("change", () => {
|
||||
queueMineruOptionVisibilityRefresh();
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape") {
|
||||
closePopover();
|
||||
|
||||
Reference in New Issue
Block a user