diff --git a/Storage/customs/gitlihang/output-ocr-result-log/README.md b/Storage/customs/gitlihang/output-ocr-result-log/README.md
new file mode 100644
index 0000000..f5453f1
--- /dev/null
+++ b/Storage/customs/gitlihang/output-ocr-result-log/README.md
@@ -0,0 +1,89 @@
+# PR Send Data wps
+
+在UI日志界面上显示OCR结果
+
+## 功能
+
+ - 通过logger日志模块,将ocr结果输出到UI,方便用户查看关键OCR节点结果。
+
+
+## 文件说明
+
+ - `logger.py`:日志输出模块。
+ - `returnOCR.py`:Python脚本。
+
+
+## 使用方式
+### 输出及click动作(暂时只写了click动作,其他动作暂未写)。
+ """
+"接受进入的副本名称": {
+ "recognition": "OCR",
+ "expected": [
+ ""
+ ],
+ "roi": [
+ 441,
+ 25,
+ 411,
+ 70
+ ]
+ },
+
+"活动-三界奇缘-结束": {
+ "action": "Custom",
+ "custom_action": "returnOCR",
+ "custom_action_param": {
+ "recognition_name": "接受进入的副本名称",
+ "action_key": "Click",
+ "return_text": "同意进入副本名称:",
+ "click_target": [
+ 727,
+ 621,
+ 190,
+ 64
+ ]
+ }
+ }
+ 自定义返回ocr识别结果,根据action_key执行不同的动作,
+ action_key: 动作名称,用于判断动作类型,如Click、Move等
+ recognition_name: task任务名称,用于指定识别任务名称,返回该节点的结果。
+ return_text: 输出的描述,用于指定返回的描述
+ click_target: 点击坐标,格式为[x1, y1, x2, y2],仅在action_key为Click时使用。如果不提供click_target,则默认点击识别结果的中心位置。
+
+ """
+### 只输出,无动作
+```
+"活动-三界奇缘-正确率": {
+ "recognition": "OCR",
+ "expected": [],
+ "roi": [
+ 320,
+ 69,
+ 116,
+ 51
+ ]
+ },
+ "活动-三界奇缘-结束": {
+
+ "action": "Custom",
+ "custom_action": "returnOCR",
+ "custom_action_param": {
+ "recognition_name": "活动-三界奇缘-正确率",
+ "action_key": "",
+ "return_text": "三界奇缘结果正确率:"
+ }
+ },
+```
+## 依赖
+
+ - json
+ - loguru
+
+
+
+## 注意事项
+
+ - 注意的值"custom_action_param"
+
+
+feat(customs): 新增在UI日志界面上显示OCR结果。
\ No newline at end of file
diff --git a/Storage/customs/gitlihang/output-ocr-result-log/action/__init__.py b/Storage/customs/gitlihang/output-ocr-result-log/action/__init__.py
new file mode 100644
index 0000000..fb575e8
--- /dev/null
+++ b/Storage/customs/gitlihang/output-ocr-result-log/action/__init__.py
@@ -0,0 +1 @@
+from .returnOCR import *
diff --git a/Storage/customs/gitlihang/output-ocr-result-log/action/returnOCR.py b/Storage/customs/gitlihang/output-ocr-result-log/action/returnOCR.py
new file mode 100644
index 0000000..88b786c
--- /dev/null
+++ b/Storage/customs/gitlihang/output-ocr-result-log/action/returnOCR.py
@@ -0,0 +1,74 @@
+from maa.agent.agent_server import AgentServer
+from maa.custom_action import CustomAction
+from maa.context import Context
+import json
+
+from utils import logger
+
+@AgentServer.custom_action("returnOCR")
+class ReturnOCR(CustomAction):
+ """
+ 自定义返回ocr识别结果,根据action_key执行不同的动作
+ "custom_action_param": {
+ "action_key": "Click",
+ "recognition_name": "识别输出测试",
+ "return_text": "输出的描述"
+ "click_target": [] # 点击坐标,格式为[x1, y1, x2, y2],仅在action_key为Click时使用
+ }
+ action_key: 动作名称,用于判断动作类型,如Click、Move等
+ recognition_name: task任务名称,用于指定识别任务名称,返回该节点的结果。
+ return_text: 输出的描述,用于指定返回的描述
+ click_target: 点击坐标,格式为[x1, y1, x2, y2],仅在action_key为Click时使用。如果不提供click_target,则默认点击识别结果的中心位置。
+
+ """
+ def run(
+ self,
+ context: Context,
+ argv: CustomAction.RunArg,
+ ) -> CustomAction.RunResult:
+ # logger.info("进入returnOCR")
+ # 解析自定义参数,并判断是否为空
+ argv_dict: dict = json.loads(argv.custom_action_param)
+ if not argv_dict:
+ return CustomAction.RunResult(success=True)
+ # 获取自定义参数
+ action_key = argv_dict.get("action_key", "")
+ recognition_name = argv_dict.get("recognition_name", "")
+ return_text = argv_dict.get("return_text", "")
+ click_target = argv_dict.get("click_target", [])
+
+ # 获取ocr识别结果数据
+ image = context.tasker.controller.post_screencap().wait().get()
+ reco_result = context.run_recognition(
+ recognition_name,
+ image
+ )
+ # 打印OCR识别结果
+ if reco_result and reco_result.hit:
+ best_result = reco_result.best_result
+ # 输出到ui界面
+ logger.info(f"{return_text}: {best_result.text}")
+ # 根据action_key执行不同的动作
+ if action_key == "Click":
+ # 点击传入参数中的坐标位置
+ if click_target:
+ box = click_target
+ center_x = box[0] + box[2] // 2
+ center_y = box[1] + box[3] // 2
+ logger.debug(f"点击位置: ({center_x}, {center_y})")
+ context.tasker.controller.post_click(center_x, center_y).wait()
+ # 点击最佳识别结果的中心位置
+ elif best_result:
+ box = best_result.box
+ center_x = box[0] + box[2] // 2
+ center_y = box[1] + box[3] // 2
+ logger.debug(f"点击位置: ({center_x}, {center_y})")
+ context.tasker.controller.post_click(center_x, center_y).wait()
+ else:
+ logger.warning("没有识别到结果,无法执行点击")
+ elif action_key == "":
+ logger.debug(f"仅返回OCR数据,不执行动作: {action_key}")
+ else:
+ logger.warning(f"OCR识别失败 - 任务名称: {recognition_name}")
+
+ return CustomAction.RunResult(success=True)
\ No newline at end of file
diff --git a/Storage/customs/gitlihang/output-ocr-result-log/maahub_meta.json b/Storage/customs/gitlihang/output-ocr-result-log/maahub_meta.json
new file mode 100644
index 0000000..b8b300a
--- /dev/null
+++ b/Storage/customs/gitlihang/output-ocr-result-log/maahub_meta.json
@@ -0,0 +1,20 @@
+{
+ "id": "gitlihang/output-ocr-result-log",
+ "title": "在UI日志界面上显示OCR结果",
+ "description": "在UI界面上显示OCR识别结果,方便用户查看任务进度和结果。",
+ "author": "gitlihang",
+ "source": "Maa_MHXY_MG",
+ "sourceGithub": "https://github.com/gitlihang/Maa_MHXY_MG",
+ "tags": ["ocr-result", "log", "ui"],
+ "createdAt": "2026-06-04",
+ "updatedAt": "2026-06-04",
+ "version": "1.0.0",
+ "mfwVersion": "5.X",
+ "entry": "main.py",
+ "readme": "./README.md",
+ "status": "stable",
+ "type": "custom",
+ "language": "python",
+ "runtime": "python 3.12.10",
+ "dependencies": ["loguru","json"]
+}
diff --git a/Storage/customs/gitlihang/output-ocr-result-log/main.py b/Storage/customs/gitlihang/output-ocr-result-log/main.py
new file mode 100644
index 0000000..e69de29
diff --git a/Storage/customs/gitlihang/output-ocr-result-log/pipeline.json b/Storage/customs/gitlihang/output-ocr-result-log/pipeline.json
new file mode 100644
index 0000000..7505e2e
--- /dev/null
+++ b/Storage/customs/gitlihang/output-ocr-result-log/pipeline.json
@@ -0,0 +1,20 @@
+{
+ "OCR识别接口": {
+ "recognition": "OCR",
+ "expected": [],
+ "roi": [
+ 320,
+ 69,
+ 116,
+ 51
+ ]
+ },"活动-三界奇缘-结束": {
+ "action": "Custom",
+ "custom_action": "returnOCR",
+ "custom_action_param": {
+ "recognition_name": "OCR识别接口",
+ "action_key": "",
+ "return_text": "三界奇缘结果正确率:"
+ }
+ }
+}
diff --git a/Storage/customs/gitlihang/output-ocr-result-log/utils/__init__.py b/Storage/customs/gitlihang/output-ocr-result-log/utils/__init__.py
new file mode 100644
index 0000000..7823c3c
--- /dev/null
+++ b/Storage/customs/gitlihang/output-ocr-result-log/utils/__init__.py
@@ -0,0 +1 @@
+from .logger import logger
\ No newline at end of file
diff --git a/Storage/customs/gitlihang/output-ocr-result-log/utils/logger.py b/Storage/customs/gitlihang/output-ocr-result-log/utils/logger.py
new file mode 100644
index 0000000..8ac9d3f
--- /dev/null
+++ b/Storage/customs/gitlihang/output-ocr-result-log/utils/logger.py
@@ -0,0 +1,84 @@
+import os
+import sys
+
+try:
+ from loguru import logger as _logger
+
+ def setup_logger(log_dir="debug/custom", console_level="INFO"):
+ """设置 loguru logger
+
+ Args:
+ log_dir: 日志文件目录
+ console_level: 控制台输出等级 (DEBUG, INFO, WARNING, ERROR)
+ """
+ os.makedirs(log_dir, exist_ok=True)
+ _logger.remove()
+
+ # 定义日志级别的简短格式
+ def format_level(record):
+ level_map = {
+ "INFO": "info",
+ "ERROR": "err",
+ "WARNING": "warn",
+ "DEBUG": "debug",
+ "CRITICAL": "critical",
+ "SUCCESS": "success",
+ "TRACE": "trace",
+ }
+ record["extra"]["level_short"] = level_map.get(
+ record["level"].name, record["level"].name.lower()
+ )
+ return True
+
+ _logger.add(
+ sys.stderr,
+ format="{extra[level_short]}:{message}",
+ colorize=True,
+ level=console_level,
+ filter=format_level,
+ )
+ _logger.add(
+ f"{log_dir}/{{time:YYYY-MM-DD}}.log",
+ rotation="00:00", # midnight
+ retention="2 weeks",
+ compression="zip",
+ level="DEBUG",
+ format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {name}:{function}:{line} | {message}",
+ encoding="utf-8",
+ enqueue=True,
+ backtrace=True, # 包含完整的异常回溯信息
+ diagnose=True, # 包含变量值信息
+ )
+ return _logger
+
+ def change_console_level(level="DEBUG"):
+ """动态修改控制台日志等级"""
+ setup_logger(console_level=level)
+ _logger.info(f"控制台日志等级已更改为: {level}")
+
+ logger = setup_logger()
+except ImportError:
+ import logging
+
+ class ShortLevelFormatter(logging.Formatter):
+ """自定义 Formatter,使用简短的日志级别名称"""
+
+ level_map = {
+ "INFO": "info",
+ "ERROR": "err",
+ "WARNING": "warn",
+ "DEBUG": "debug",
+ "CRITICAL": "critical",
+ }
+
+ def format(self, record):
+ record.level_short = self.level_map.get(
+ record.levelname, record.levelname.lower()
+ )
+ return super().format(record)
+
+ handler = logging.StreamHandler(sys.stderr)
+ handler.setFormatter(ShortLevelFormatter("%(level_short)s:%(message)s"))
+ logging.root.addHandler(handler)
+ logging.root.setLevel(logging.INFO)
+ logger = logging
\ No newline at end of file