'commit'
This commit is contained in:
BIN
WeiXin/Screenshots/T2_history_20260126_091210.jpg
Normal file
BIN
WeiXin/Screenshots/T2_history_20260126_091210.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
BIN
WeiXin/Screenshots/T2_history_20260126_091414.jpg
Normal file
BIN
WeiXin/Screenshots/T2_history_20260126_091414.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
BIN
WeiXin/Screenshots/temp_menu_shot.jpg
Normal file
BIN
WeiXin/Screenshots/temp_menu_shot.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
@@ -4,6 +4,7 @@ import time
|
|||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import WxUtil
|
||||||
|
|
||||||
# 添加项目根目录到 sys.path
|
# 添加项目根目录到 sys.path
|
||||||
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
@@ -29,11 +30,8 @@ def open_chat(target_name="糖豆爸爸"):
|
|||||||
logger.info(f"开始执行 T1: 打开微信并进入 '{target_name}' 的对话框...")
|
logger.info(f"开始执行 T1: 打开微信并进入 '{target_name}' 的对话框...")
|
||||||
|
|
||||||
# 连接设备
|
# 连接设备
|
||||||
try:
|
d = WxUtil.connect_device()
|
||||||
d = u2.connect()
|
if not d:
|
||||||
logger.info(f"设备连接成功: {d.info.get('serial')}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"设备连接失败: {e}")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# 1. 启动微信
|
# 1. 启动微信
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
import uiautomator2 as u2
|
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import asyncio
|
||||||
|
|
||||||
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
if project_root not in sys.path:
|
if project_root not in sys.path:
|
||||||
sys.path.append(project_root)
|
sys.path.append(project_root)
|
||||||
|
|
||||||
|
from WeiXin import WxUtil
|
||||||
from WeiXin.WxUtil import analyze_chat_image
|
from WeiXin.WxUtil import analyze_chat_image
|
||||||
|
|
||||||
# 配置日志
|
# 配置日志
|
||||||
@@ -26,14 +27,11 @@ logging.basicConfig(
|
|||||||
)
|
)
|
||||||
logger = logging.getLogger("T2_GetHistory")
|
logger = logging.getLogger("T2_GetHistory")
|
||||||
|
|
||||||
def get_history(target_name="对方"):
|
async def get_history(target_name="对方"):
|
||||||
logger.info("开始执行 T2: 获取当前屏幕对话历史...")
|
logger.info("开始执行 T2: 获取当前屏幕对话历史...")
|
||||||
|
|
||||||
try:
|
d = WxUtil.connect_device()
|
||||||
d = u2.connect()
|
if not d:
|
||||||
logger.info(f"设备连接成功: {d.info.get('serial')}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"设备连接失败: {e}")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# 截图
|
# 截图
|
||||||
@@ -53,7 +51,11 @@ def get_history(target_name="对方"):
|
|||||||
analyzed_path = os.path.join(screenshot_dir, analyzed_filename)
|
analyzed_path = os.path.join(screenshot_dir, analyzed_filename)
|
||||||
|
|
||||||
# 调用 WxUtil 中的分析函数
|
# 调用 WxUtil 中的分析函数
|
||||||
dialogue_log = analyze_chat_image(save_path, analyzed_path, target_name=target_name)
|
dialogue_log, input_box = await analyze_chat_image(save_path, analyzed_path, device=d, target_name=target_name)
|
||||||
|
|
||||||
|
if dialogue_log == "VOICE_CONVERTING":
|
||||||
|
logger.info("检测到语音正在转文字,T2 任务暂停。")
|
||||||
|
return
|
||||||
|
|
||||||
logger.info("✅ T2 执行完成。历史对话如下:")
|
logger.info("✅ T2 执行完成。历史对话如下:")
|
||||||
if dialogue_log:
|
if dialogue_log:
|
||||||
@@ -66,4 +68,4 @@ def get_history(target_name="对方"):
|
|||||||
logger.error(f"❌ T2 执行失败: {e}")
|
logger.error(f"❌ T2 执行失败: {e}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
get_history()
|
asyncio.run(get_history())
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
import uiautomator2 as u2
|
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
@@ -11,6 +10,7 @@ project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
if project_root not in sys.path:
|
if project_root not in sys.path:
|
||||||
sys.path.append(project_root)
|
sys.path.append(project_root)
|
||||||
|
|
||||||
|
from WeiXin import WxUtil
|
||||||
from WeiXin.WxUtil import find_input_box_center
|
from WeiXin.WxUtil import find_input_box_center
|
||||||
|
|
||||||
# 配置日志
|
# 配置日志
|
||||||
@@ -31,11 +31,8 @@ logger = logging.getLogger("T3_MarkInputBox")
|
|||||||
def mark_input_box():
|
def mark_input_box():
|
||||||
logger.info("开始执行 T3: 标识输入框位置...")
|
logger.info("开始执行 T3: 标识输入框位置...")
|
||||||
|
|
||||||
try:
|
d = WxUtil.connect_device()
|
||||||
d = u2.connect()
|
if not d:
|
||||||
logger.info(f"设备连接成功: {d.info.get('serial')}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"设备连接失败: {e}")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
screenshot_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Screenshots")
|
screenshot_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Screenshots")
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
import uiautomator2 as u2
|
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
@@ -11,6 +10,7 @@ project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
if project_root not in sys.path:
|
if project_root not in sys.path:
|
||||||
sys.path.append(project_root)
|
sys.path.append(project_root)
|
||||||
|
|
||||||
|
from WeiXin import WxUtil
|
||||||
from WeiXin.WxUtil import find_input_box_center, perform_input_action, analyze_chat_image, clean_screenshots_dir, is_in_chat_interface
|
from WeiXin.WxUtil import find_input_box_center, perform_input_action, analyze_chat_image, clean_screenshots_dir, is_in_chat_interface
|
||||||
from Util.LlmUtil import get_llm_response
|
from Util.LlmUtil import get_llm_response
|
||||||
|
|
||||||
@@ -37,8 +37,9 @@ async def generate_and_input():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# 1. 连接设备
|
# 1. 连接设备
|
||||||
d = u2.connect()
|
d = WxUtil.connect_device()
|
||||||
logger.info(f"设备连接成功: {d.info.get('serial')}")
|
if not d:
|
||||||
|
return
|
||||||
|
|
||||||
# 检查界面状态
|
# 检查界面状态
|
||||||
if not is_in_chat_interface(d):
|
if not is_in_chat_interface(d):
|
||||||
@@ -54,14 +55,14 @@ async def generate_and_input():
|
|||||||
d.screenshot(tmp_shot)
|
d.screenshot(tmp_shot)
|
||||||
|
|
||||||
analyzed_shot = os.path.join(screenshot_dir, "t4_temp_history_analyzed.jpg")
|
analyzed_shot = os.path.join(screenshot_dir, "t4_temp_history_analyzed.jpg")
|
||||||
dialogue_log = analyze_chat_image(tmp_shot, analyzed_shot)
|
dialogue_log, input_box = await analyze_chat_image(tmp_shot, analyzed_shot, device=d)
|
||||||
|
|
||||||
# 语音转文字处理
|
# 语音转文字处理
|
||||||
if dialogue_log == "VOICE_CONVERTING":
|
if dialogue_log == "VOICE_CONVERTING":
|
||||||
logger.info("检测到语音正在转文字,等待 3 秒后重新截图分析...")
|
logger.info("检测到语音正在转文字,等待 3 秒后重新截图分析...")
|
||||||
await asyncio.sleep(3)
|
await asyncio.sleep(3)
|
||||||
d.screenshot(tmp_shot)
|
d.screenshot(tmp_shot)
|
||||||
dialogue_log = analyze_chat_image(tmp_shot, analyzed_shot)
|
dialogue_log, input_box = await analyze_chat_image(tmp_shot, analyzed_shot, device=d)
|
||||||
|
|
||||||
history_text = ""
|
history_text = ""
|
||||||
if dialogue_log:
|
if dialogue_log:
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import sys
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import uiautomator2 as u2
|
|
||||||
|
|
||||||
# 添加项目根目录到 sys.path
|
# 添加项目根目录到 sys.path
|
||||||
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
if project_root not in sys.path:
|
if project_root not in sys.path:
|
||||||
sys.path.append(project_root)
|
sys.path.append(project_root)
|
||||||
|
|
||||||
|
from WeiXin import WxUtil
|
||||||
from WeiXin.WxUtil import get_vlm_analysis
|
from WeiXin.WxUtil import get_vlm_analysis
|
||||||
from Util.EasyOcrKit import EasyOcrKit
|
from Util.EasyOcrKit import EasyOcrKit
|
||||||
|
|
||||||
@@ -24,11 +24,8 @@ async def main():
|
|||||||
logger.info("🚀 T6 VLM 语音坐标调试工具启动...")
|
logger.info("🚀 T6 VLM 语音坐标调试工具启动...")
|
||||||
|
|
||||||
# 连接设备
|
# 连接设备
|
||||||
try:
|
d = WxUtil.connect_device()
|
||||||
d = u2.connect()
|
if not d:
|
||||||
logger.info(f"设备已连接: {d.info.get('serial')}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"设备连接失败: {e}")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# 截图目录
|
# 截图目录
|
||||||
|
|||||||
@@ -4,21 +4,24 @@ import sys
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import uiautomator2 as u2
|
|
||||||
|
|
||||||
# 添加项目根目录到 sys.path
|
# 添加项目根目录到 sys.path
|
||||||
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
if project_root not in sys.path:
|
if project_root not in sys.path:
|
||||||
sys.path.append(project_root)
|
sys.path.append(project_root)
|
||||||
|
|
||||||
|
from WeiXin import WxUtil
|
||||||
from WeiXin.WxUtil import find_all_template_matches
|
from WeiXin.WxUtil import find_all_template_matches
|
||||||
|
|
||||||
|
|
||||||
def run_cv_debug():
|
def run_cv_debug():
|
||||||
# 1. 拍照 (获取当前设备屏幕)
|
# 1. 拍照 (获取当前设备屏幕)
|
||||||
print("📸 正在连接设备并截取屏幕...")
|
print("📸 正在连接设备并截取屏幕...")
|
||||||
|
d = WxUtil.connect_device()
|
||||||
|
if not d:
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
d = u2.connect()
|
|
||||||
screenshot_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Screenshots")
|
screenshot_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Screenshots")
|
||||||
if not os.path.exists(screenshot_dir):
|
if not os.path.exists(screenshot_dir):
|
||||||
os.makedirs(screenshot_dir)
|
os.makedirs(screenshot_dir)
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import sys
|
|||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
import uiautomator2 as u2
|
|
||||||
|
|
||||||
# 添加项目根目录到 sys.path
|
# 添加项目根目录到 sys.path
|
||||||
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
if project_root not in sys.path:
|
if project_root not in sys.path:
|
||||||
@@ -15,6 +13,7 @@ if project_root not in sys.path:
|
|||||||
|
|
||||||
from Util import Win32Patch
|
from Util import Win32Patch
|
||||||
|
|
||||||
|
from WeiXin import WxUtil
|
||||||
from WeiXin.WxUtil import perform_input_action, clean_screenshots_dir, find_template_match, find_all_template_matches
|
from WeiXin.WxUtil import perform_input_action, clean_screenshots_dir, find_template_match, find_all_template_matches
|
||||||
from Util.LlmUtil import get_llm_response
|
from Util.LlmUtil import get_llm_response
|
||||||
from Util.EasyOcrKit import EasyOcrKit
|
from Util.EasyOcrKit import EasyOcrKit
|
||||||
@@ -54,7 +53,9 @@ CHECK_INTERVAL = 5 # 检查频率 (秒)
|
|||||||
|
|
||||||
class ChatBot:
|
class ChatBot:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.d = u2.connect()
|
self.d = WxUtil.connect_device()
|
||||||
|
if not self.d:
|
||||||
|
raise Exception("无法连接到设备,任务终止")
|
||||||
self.last_message_text = ""
|
self.last_message_text = ""
|
||||||
self.last_processed_msg = None # 记录上一条已处理/回复过的对方消息内容
|
self.last_processed_msg = None # 记录上一条已处理/回复过的对方消息内容
|
||||||
self.screenshot_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Screenshots")
|
self.screenshot_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Screenshots")
|
||||||
|
|||||||
@@ -25,6 +25,23 @@ ocr_kit = EasyOcrKit()
|
|||||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
logger = logging.getLogger("WxUtil")
|
logger = logging.getLogger("WxUtil")
|
||||||
|
|
||||||
|
def connect_device():
|
||||||
|
"""
|
||||||
|
连接设备并返回设备对象,同时打印详细的设备信息
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
d = u2.connect()
|
||||||
|
# 获取可靠的序列号
|
||||||
|
device_serial = d.serial if hasattr(d, 'serial') else "未知"
|
||||||
|
logger.info(f"设备连接成功: {device_serial}")
|
||||||
|
|
||||||
|
# 获取并打印详细设备信息
|
||||||
|
device_info = d.device_info
|
||||||
|
logger.info(f"详细设备信息: 品牌={device_info.get('brand')}, 型号={device_info.get('model')}, SDK={device_info.get('sdk')}")
|
||||||
|
return d
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"设备连接失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
async def get_vlm_json(image_path, prompt):
|
async def get_vlm_json(image_path, prompt):
|
||||||
"""
|
"""
|
||||||
@@ -249,7 +266,7 @@ async def analyze_chat_image(image_path, output_path, device=None, target_name="
|
|||||||
unconverted_voices = [unconverted_voices[-1]]
|
unconverted_voices = [unconverted_voices[-1]]
|
||||||
|
|
||||||
# 使用传入的 device 或创建新连接
|
# 使用传入的 device 或创建新连接
|
||||||
d = device if device else u2.connect()
|
d = device if device else connect_device()
|
||||||
|
|
||||||
for voice in unconverted_voices:
|
for voice in unconverted_voices:
|
||||||
vx, vy = voice['coordinates']
|
vx, vy = voice['coordinates']
|
||||||
|
|||||||
Binary file not shown.
@@ -472,105 +472,6 @@ namespace WordAddIn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 【智能扩写】按钮点击事件处理。
|
|
||||||
/// 功能描述:
|
|
||||||
/// 1. 获取用户选中的文本(或剪贴板内容)。
|
|
||||||
/// 2. 弹出选项窗体,允许用户输入自定义扩写提示词。
|
|
||||||
/// 3. 调用 AI 扩写接口,传入原文、用户提示和全文上下文。
|
|
||||||
/// 4. 将 AI 生成的扩写内容替换原有选区,或插入到光标位置。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="control">触发事件的 Ribbon 控件</param>
|
|
||||||
public async void OnExpandClick(Office.IRibbonControl control)
|
|
||||||
{
|
|
||||||
if (!EnsureLoggedIn()) return;
|
|
||||||
|
|
||||||
LoadingForm loading = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var selection = Globals.ThisAddIn.Application.Selection;
|
|
||||||
|
|
||||||
// 1. 判断是否有选中文本
|
|
||||||
// wdSelectionNormal 表示有选区,否则检查 Text 属性
|
|
||||||
bool hasSelection = selection.Type == Word.WdSelectionType.wdSelectionNormal ||
|
|
||||||
(!string.IsNullOrEmpty(selection.Text) && selection.Text.Length > 1);
|
|
||||||
|
|
||||||
if (!hasSelection)
|
|
||||||
{
|
|
||||||
// 2. 尝试从剪贴板读取
|
|
||||||
IDataObject data = Clipboard.GetDataObject();
|
|
||||||
if (data != null && data.GetDataPresent(DataFormats.Text))
|
|
||||||
{
|
|
||||||
string clipboardText = (string)data.GetData(DataFormats.Text);
|
|
||||||
if (string.IsNullOrWhiteSpace(clipboardText))
|
|
||||||
{
|
|
||||||
MessageBox.Show("剪贴板中内容为空,请先选择一段需要扩写的文字,或者复制文字到剪贴板。");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("请先选择一段需要扩写的文字,或者复制文字到剪贴板。");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string originalText;
|
|
||||||
if (hasSelection)
|
|
||||||
{
|
|
||||||
originalText = selection.Text.Trim();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 使用剪贴板内容
|
|
||||||
IDataObject data = Clipboard.GetDataObject();
|
|
||||||
originalText = (string)data.GetData(DataFormats.Text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(originalText))
|
|
||||||
{
|
|
||||||
MessageBox.Show("获取文字失败,请重试。");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 弹出选项设置窗体,让用户输入自定义扩写提示词
|
|
||||||
string customPrompt = null;
|
|
||||||
using (var optionsForm = new ExpandOptionsForm())
|
|
||||||
{
|
|
||||||
if (optionsForm.ShowDialog() != DialogResult.OK)
|
|
||||||
{
|
|
||||||
return; // 用户取消
|
|
||||||
}
|
|
||||||
customPrompt = optionsForm.SelectedPrompt;
|
|
||||||
}
|
|
||||||
|
|
||||||
loading = new LoadingForm("AI 正在扩写中,请稍候...");
|
|
||||||
loading.Show();
|
|
||||||
loading.Refresh();
|
|
||||||
|
|
||||||
// 4. 在后台线程运行 AI 请求,防止阻塞 UI
|
|
||||||
// 传入 GetCombinedContext() 以利用文档背景和参考资料
|
|
||||||
string expandedText = await Task.Run(() => _aiService.ExpandText(originalText, customPrompt, GetCombinedContext()));
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(expandedText))
|
|
||||||
{
|
|
||||||
// 5. 智能插入:尝试保持格式
|
|
||||||
SmartInsert(selection, expandedText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show("扩写失败: " + ex.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (loading != null)
|
|
||||||
{
|
|
||||||
loading.CloseSafe();
|
|
||||||
loading.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 【素材写作】按钮点击事件处理。
|
/// 【素材写作】按钮点击事件处理。
|
||||||
@@ -674,8 +575,7 @@ namespace WordAddIn
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 智能插入辅助方法。
|
/// 智能插入辅助方法。
|
||||||
/// 使用 TypeText 方法插入文本,以保持当前光标处的格式。
|
/// 插入文本并强制应用“正文”样式,确保格式统一。
|
||||||
/// 如果 TypeText 失败,则回退到直接赋值 Text 属性。
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="selection">Word 选区对象</param>
|
/// <param name="selection">Word 选区对象</param>
|
||||||
/// <param name="text">要插入的文本</param>
|
/// <param name="text">要插入的文本</param>
|
||||||
@@ -683,8 +583,19 @@ namespace WordAddIn
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 使用 TypeText 插入,让 Word 自动应用当前光标位置的格式
|
// 获取当前 Range
|
||||||
selection.TypeText(text);
|
Word.Range range = selection.Range;
|
||||||
|
|
||||||
|
// 插入文本
|
||||||
|
range.Text = text;
|
||||||
|
|
||||||
|
// 强制应用“正文”样式 (wdStyleNormal)
|
||||||
|
// 这样可以避免插入的内容受到当前光标位置样式(如标题样式)的影响
|
||||||
|
range.set_Style(Word.WdBuiltinStyle.wdStyleNormal);
|
||||||
|
|
||||||
|
// 将光标移动到插入内容之后,方便用户继续操作
|
||||||
|
range.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
|
||||||
|
range.Select();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1060,6 +971,9 @@ namespace WordAddIn
|
|||||||
var selection = Globals.ThisAddIn.Application.Selection;
|
var selection = Globals.ThisAddIn.Application.Selection;
|
||||||
var inlineShape = selection.InlineShapes.AddPicture(FileName: tempPath, LinkToFile: false, SaveWithDocument: true);
|
var inlineShape = selection.InlineShapes.AddPicture(FileName: tempPath, LinkToFile: false, SaveWithDocument: true);
|
||||||
|
|
||||||
|
// 强制将图片所在的段落设为“正文”样式
|
||||||
|
inlineShape.Range.Paragraphs[1].set_Style(Word.WdBuiltinStyle.wdStyleNormal);
|
||||||
|
|
||||||
// 简单的图片调整
|
// 简单的图片调整
|
||||||
inlineShape.LockAspectRatio = Microsoft.Office.Core.MsoTriState.msoTrue;
|
inlineShape.LockAspectRatio = Microsoft.Office.Core.MsoTriState.msoTrue;
|
||||||
if (inlineShape.Width > 400)
|
if (inlineShape.Width > 400)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
<button id="btnReferenceGenerate" label="素材写作" size="large" onAction="OnReferenceGenerateClick" imageMso="ReviewCompareTwoVersions" />
|
<button id="btnReferenceGenerate" label="素材写作" size="large" onAction="OnReferenceGenerateClick" imageMso="ReviewCompareTwoVersions" />
|
||||||
<button id="btnPolish" label="润色加工" size="large" onAction="OnPolishClick" imageMso="Spelling" />
|
<button id="btnPolish" label="润色加工" size="large" onAction="OnPolishClick" imageMso="Spelling" />
|
||||||
<button id="btnElevate" label="深度升华" size="large" onAction="OnElevateClick" imageMso="SmartArtInsert" />
|
<button id="btnElevate" label="深度升华" size="large" onAction="OnElevateClick" imageMso="SmartArtInsert" />
|
||||||
<button id="btnExpand" label="智能扩写" size="large" onAction="OnExpandClick" imageMso="ReviewNewComment" />
|
|
||||||
<button id="btnFormat" label="格式美化" imageMso="FontColorCycle" size="large" onAction="OnFormatClick" />
|
<button id="btnFormat" label="格式美化" imageMso="FontColorCycle" size="large" onAction="OnFormatClick" />
|
||||||
<button id="btnImage" label="生成配图" size="large" onAction="OnImageClick" imageMso="PictureInsertFromFile" />
|
<button id="btnImage" label="生成配图" size="large" onAction="OnImageClick" imageMso="PictureInsertFromFile" />
|
||||||
</group>
|
</group>
|
||||||
|
|||||||
@@ -41,38 +41,6 @@ namespace WordAddIn
|
|||||||
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {ApiKey}");
|
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {ApiKey}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 智能扩写:将简短的文本扩充为细节丰富、逻辑通顺的段落。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="originalText">需要扩写的原文</param>
|
|
||||||
/// <param name="customInstruction">用户自定义的扩写要求(如“更幽默一点”、“强调数据支持”等),可选</param>
|
|
||||||
/// <param name="documentContext">文档全文上下文(摘要、风格等),用于保持文风一致,可选</param>
|
|
||||||
/// <returns>扩写后的纯文本内容</returns>
|
|
||||||
public async Task<string> ExpandText(string originalText, string customInstruction = null, string documentContext = null)
|
|
||||||
{
|
|
||||||
// 构造 User 指令
|
|
||||||
string instruction = string.IsNullOrWhiteSpace(customInstruction)
|
|
||||||
? "请将以下内容扩写成一段正式、通顺的段落,保持原意但增加细节"
|
|
||||||
: customInstruction;
|
|
||||||
|
|
||||||
// 构造 System Prompt
|
|
||||||
// 强制要求不使用 Markdown,方便直接插入 Word
|
|
||||||
string systemPrompt = "你是一个专业的文档编辑助手。请直接输出扩写后的纯文本内容,不要使用任何Markdown标记(如#、**、- 等)。直接使用自然段落。";
|
|
||||||
|
|
||||||
// 注入文档上下文(如果有)
|
|
||||||
if (!string.IsNullOrWhiteSpace(documentContext))
|
|
||||||
{
|
|
||||||
systemPrompt += $"\n\n【全文背景与排版规则】:你已通读全文,以下是文档的整体上下文信息和排版规则,请在扩写时保持与全文主题和风格的一致性,并参考排版规则生成对应的层级结构:\n{documentContext}";
|
|
||||||
}
|
|
||||||
|
|
||||||
var messages = new List<Message>
|
|
||||||
{
|
|
||||||
new Message { role = "system", content = systemPrompt },
|
|
||||||
new Message { role = "user", content = $"{instruction}:\n\n{originalText}" }
|
|
||||||
};
|
|
||||||
|
|
||||||
return await GetChatCompletion(messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 润色加工:优化文本的语言表达,提升流畅度和专业性。
|
/// 润色加工:优化文本的语言表达,提升流畅度和专业性。
|
||||||
|
|||||||
@@ -1,182 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace WordAddIn
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 智能扩写设置窗体。
|
|
||||||
/// 功能描述:
|
|
||||||
/// 1. 提供多种预设的扩写模板(如"商务正式"、"细腻情感"等)。
|
|
||||||
/// 2. 允许用户修改预设模板或输入完全自定义的扩写要求。
|
|
||||||
/// 3. 返回用户的最终选择 (SelectedPrompt) 给调用方。
|
|
||||||
/// </summary>
|
|
||||||
public class ExpandOptionsForm : Form
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 用户最终确认的扩写要求。
|
|
||||||
/// </summary>
|
|
||||||
public string SelectedPrompt { get; private set; }
|
|
||||||
|
|
||||||
private ComboBox cmbTemplates;
|
|
||||||
private TextBox txtCustomPrompt;
|
|
||||||
private Button btnOk;
|
|
||||||
private Button btnCancel;
|
|
||||||
private Label lblTemplate;
|
|
||||||
private Label lblCustom;
|
|
||||||
|
|
||||||
private readonly Dictionary<string, string> _templates = new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ "默认扩写", "请将以下内容扩写成一段正式、通顺的段落,保持原意但增加细节。" },
|
|
||||||
{ "细腻情感", "请对选中文本进行扩写,重点从心理活动、情绪变化和感官体验三个维度进行细腻描写。" },
|
|
||||||
{ "商务正式", "请将选中文本改写为商务职场风格,使用专业术语,语气正式且客观。" },
|
|
||||||
{ "生动故事", "请将选中文本扩写为一个生动的小故事,增加对话和场景描写,使其引人入胜。" },
|
|
||||||
{ "学术严谨", "请将选中文本扩写为学术风格,逻辑严密,用词精准,适合用于论文或报告。" },
|
|
||||||
{ "诗意唯美", "请用优美、诗意的语言扩写选中文本,多用修辞手法,营造唯美的意境。" }
|
|
||||||
};
|
|
||||||
|
|
||||||
public ExpandOptionsForm()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
InitializeTemplates();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化窗体组件。
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent()
|
|
||||||
{
|
|
||||||
this.lblTemplate = new System.Windows.Forms.Label();
|
|
||||||
this.lblCustom = new System.Windows.Forms.Label();
|
|
||||||
this.cmbTemplates = new System.Windows.Forms.ComboBox();
|
|
||||||
this.txtCustomPrompt = new System.Windows.Forms.TextBox();
|
|
||||||
this.btnOk = new System.Windows.Forms.Button();
|
|
||||||
this.btnCancel = new System.Windows.Forms.Button();
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// lblTemplate
|
|
||||||
//
|
|
||||||
this.lblTemplate.AutoSize = true;
|
|
||||||
this.lblTemplate.Location = new System.Drawing.Point(20, 20);
|
|
||||||
this.lblTemplate.Name = "lblTemplate";
|
|
||||||
this.lblTemplate.Size = new System.Drawing.Size(83, 12);
|
|
||||||
this.lblTemplate.TabIndex = 0;
|
|
||||||
this.lblTemplate.Text = "选择预设模板:";
|
|
||||||
//
|
|
||||||
// lblCustom
|
|
||||||
//
|
|
||||||
this.lblCustom.AutoSize = true;
|
|
||||||
this.lblCustom.Location = new System.Drawing.Point(20, 80);
|
|
||||||
this.lblCustom.Name = "lblCustom";
|
|
||||||
this.lblCustom.Size = new System.Drawing.Size(107, 12);
|
|
||||||
this.lblCustom.TabIndex = 2;
|
|
||||||
this.lblCustom.Text = "扩写要求 (可修改):";
|
|
||||||
//
|
|
||||||
// cmbTemplates
|
|
||||||
//
|
|
||||||
this.cmbTemplates.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
|
||||||
this.cmbTemplates.FormattingEnabled = true;
|
|
||||||
this.cmbTemplates.Location = new System.Drawing.Point(20, 45);
|
|
||||||
this.cmbTemplates.Name = "cmbTemplates";
|
|
||||||
this.cmbTemplates.Size = new System.Drawing.Size(440, 20);
|
|
||||||
this.cmbTemplates.TabIndex = 1;
|
|
||||||
this.cmbTemplates.SelectedIndexChanged += new System.EventHandler(this.CmbTemplates_SelectedIndexChanged);
|
|
||||||
//
|
|
||||||
// txtCustomPrompt
|
|
||||||
//
|
|
||||||
this.txtCustomPrompt.Location = new System.Drawing.Point(20, 105);
|
|
||||||
this.txtCustomPrompt.Multiline = true;
|
|
||||||
this.txtCustomPrompt.Name = "txtCustomPrompt";
|
|
||||||
this.txtCustomPrompt.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
|
||||||
this.txtCustomPrompt.Size = new System.Drawing.Size(440, 120);
|
|
||||||
this.txtCustomPrompt.TabIndex = 3;
|
|
||||||
//
|
|
||||||
// btnOk
|
|
||||||
//
|
|
||||||
this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK;
|
|
||||||
this.btnOk.Location = new System.Drawing.Point(260, 250);
|
|
||||||
this.btnOk.Name = "btnOk";
|
|
||||||
this.btnOk.Size = new System.Drawing.Size(90, 35);
|
|
||||||
this.btnOk.TabIndex = 4;
|
|
||||||
this.btnOk.Text = "开始扩写";
|
|
||||||
this.btnOk.UseVisualStyleBackColor = true;
|
|
||||||
this.btnOk.Click += new System.EventHandler(this.BtnOk_Click);
|
|
||||||
//
|
|
||||||
// btnCancel
|
|
||||||
//
|
|
||||||
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
|
||||||
this.btnCancel.Location = new System.Drawing.Point(370, 250);
|
|
||||||
this.btnCancel.Name = "btnCancel";
|
|
||||||
this.btnCancel.Size = new System.Drawing.Size(90, 35);
|
|
||||||
this.btnCancel.TabIndex = 5;
|
|
||||||
this.btnCancel.Text = "取消";
|
|
||||||
this.btnCancel.UseVisualStyleBackColor = true;
|
|
||||||
//
|
|
||||||
// ExpandOptionsForm
|
|
||||||
//
|
|
||||||
this.AcceptButton = this.btnOk;
|
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
|
||||||
this.CancelButton = this.btnCancel;
|
|
||||||
this.ClientSize = new System.Drawing.Size(500, 311);
|
|
||||||
this.Controls.Add(this.btnCancel);
|
|
||||||
this.Controls.Add(this.btnOk);
|
|
||||||
this.Controls.Add(this.txtCustomPrompt);
|
|
||||||
this.Controls.Add(this.lblCustom);
|
|
||||||
this.Controls.Add(this.cmbTemplates);
|
|
||||||
this.Controls.Add(this.lblTemplate);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
|
||||||
this.MaximizeBox = false;
|
|
||||||
this.MinimizeBox = false;
|
|
||||||
this.Name = "ExpandOptionsForm";
|
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
|
||||||
this.Text = "智能扩写设置";
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
this.PerformLayout();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化模板下拉列表。
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeTemplates()
|
|
||||||
{
|
|
||||||
foreach (var key in _templates.Keys)
|
|
||||||
{
|
|
||||||
cmbTemplates.Items.Add(key);
|
|
||||||
}
|
|
||||||
if (cmbTemplates.Items.Count > 0)
|
|
||||||
{
|
|
||||||
cmbTemplates.SelectedIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 模板选择改变事件。
|
|
||||||
/// 当用户选择不同模板时,自动填充对应的 Prompt 到文本框中。
|
|
||||||
/// </summary>
|
|
||||||
private void CmbTemplates_SelectedIndexChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (cmbTemplates.SelectedItem != null && _templates.ContainsKey(cmbTemplates.SelectedItem.ToString()))
|
|
||||||
{
|
|
||||||
txtCustomPrompt.Text = _templates[cmbTemplates.SelectedItem.ToString()];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 确定按钮点击事件。
|
|
||||||
/// 验证输入有效性,并保存结果。
|
|
||||||
/// </summary>
|
|
||||||
private void BtnOk_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
SelectedPrompt = txtCustomPrompt.Text.Trim();
|
|
||||||
if (string.IsNullOrEmpty(SelectedPrompt))
|
|
||||||
{
|
|
||||||
MessageBox.Show("扩写要求不能为空。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
||||||
this.DialogResult = DialogResult.None; // Prevent closing
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -245,9 +245,6 @@
|
|||||||
<Compile Include="Models.cs">
|
<Compile Include="Models.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="ExpandOptionsForm.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="ImageOptionsForm.cs">
|
<Compile Include="ImageOptionsForm.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
Reference in New Issue
Block a user