ocr-chat.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /**
  2. * Func 标签:ocr-chat
  3. *
  4. * 约定:src/pages/processing/func/ 目录下每个文件名就是一个"可用标签/能力"。
  5. * 本文件用于声明该标签存在(供文档/提示词/后续动态加载使用)。
  6. *
  7. * 运行时真实执行逻辑由 ActionParser + electronAPI.extractChatHistory + main-js/func/ocr-chat.js 实现。
  8. */
  9. export const tagName = 'ocr-chat';
  10. export const schema = {
  11. description: '根据图片识别对话内容,区分好友和自己的对话,输出JSON字符串格式的消息记录。',
  12. inputs: {
  13. // 按用户要求:抽象为 avatar1/avatar2,不绑定 friend/me 语义
  14. avatar1: '参与者1的头像/标识图片路径(相对于工作流目录)',
  15. avatar2: '参与者2的头像/标识图片路径(相对于工作流目录)',
  16. variable: '输出变量名(保存JSON字符串格式的消息记录)',
  17. },
  18. outputs: {
  19. variable: 'JSON字符串格式的消息记录(数组,每个元素包含 sender 和 text 字段)',
  20. },
  21. };
  22. /**
  23. * 执行 ocr-chat 功能
  24. * 这个函数会被 ActionParser 调用
  25. *
  26. * @param {Object} params - 参数对象
  27. * @param {string} params.device - 设备 ID/IP:Port
  28. * @param {string} params.avatar1 - 参与者1的头像路径
  29. * @param {string} params.avatar2 - 参与者2的头像路径
  30. * @param {string} params.folderPath - 工作流文件夹路径
  31. * @param {Object} params.region - 识别区域(可选,包含四个顶点坐标的 corners 对象)
  32. * @param {string} params.friendRgb - 好友对话框RGB颜色(格式:"(r,g,b)")
  33. * @param {string} params.myRgb - 我的对话框RGB颜色(格式:"(r,g,b)")
  34. * @returns {Promise<{success: boolean, messagesJson?: string, messages?: Array, error?: string}>}
  35. */
  36. export async function executeOcrChat({ device, avatar1, avatar2, folderPath, region = null, friendRgb = null, myRgb = null }) {
  37. try {
  38. if (!window.electronAPI || !window.electronAPI.extractChatHistory) {
  39. return {
  40. success: false,
  41. error: 'extractChatHistory API 不可用'
  42. };
  43. }
  44. // 调用主进程的 extractChatHistory 函数
  45. const result = await window.electronAPI.extractChatHistory(
  46. device,
  47. avatar1,
  48. avatar2,
  49. folderPath,
  50. region, // 传递区域参数
  51. friendRgb, // 传递好友RGB
  52. myRgb // 传递我的RGB
  53. );
  54. if (!result.success) {
  55. return { success: false, error: result.error };
  56. }
  57. // 获取消息数组
  58. let messages = [];
  59. if (result.messages && Array.isArray(result.messages)) {
  60. messages = result.messages;
  61. } else if (result.messagesText) {
  62. // 如果只有文本,尝试解析(向后兼容)
  63. const lines = result.messagesText.split('\n').filter(line => line.trim());
  64. for (const line of lines) {
  65. const match = line.match(/^(对方|好友|我):\s*(.+)$/);
  66. if (match) {
  67. const senderLabel = match[1];
  68. const sender = (senderLabel === '对方' || senderLabel === '好友') ? 'friend' : 'me';
  69. const text = match[2].trim();
  70. messages.push({ sender, text });
  71. }
  72. }
  73. }
  74. // 将消息数组转换为 chat-history.txt 格式的字符串
  75. // 格式:{"data":"时间戳","friend":"消息","me":"消息"}
  76. // 每个消息前都有一个时间戳(同一时间识别的消息使用相同时间戳)
  77. const formattedLines = [];
  78. formattedLines.push('{');
  79. // 获取当前时间戳(格式:昨天 HH:MM 或 今天 HH:MM)
  80. const now = new Date();
  81. const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  82. const yesterday = new Date(today);
  83. yesterday.setDate(yesterday.getDate() - 1);
  84. let timeLabel = '';
  85. const hour = now.getHours();
  86. const minute = now.getMinutes();
  87. if (now >= today) {
  88. timeLabel = `今天 ${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
  89. } else if (now >= yesterday) {
  90. timeLabel = `昨天 ${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
  91. } else {
  92. timeLabel = `${now.getFullYear()}/${now.getMonth() + 1}/${now.getDate()} ${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
  93. }
  94. // 添加消息(按顺序),每个消息前添加时间戳
  95. let entryIndex = 0;
  96. for (let i = 0; i < messages.length; i++) {
  97. const msg = messages[i];
  98. const sender = msg.sender || msg.role || '';
  99. const text = (msg.text || msg.message || '').trim();
  100. if (text && (sender === 'friend' || sender === 'me')) {
  101. // 每个消息前添加时间戳
  102. formattedLines.push(`\t"data":${JSON.stringify(timeLabel)},`);
  103. formattedLines.push(`\t"${sender}":${JSON.stringify(text)}`);
  104. // 如果不是最后一条消息,添加逗号
  105. const hasMoreMessages = messages.slice(i + 1).some(m => {
  106. const s = m.sender || m.role || '';
  107. const t = (m.text || m.message || '').trim();
  108. return t && (s === 'friend' || s === 'me');
  109. });
  110. if (hasMoreMessages) {
  111. formattedLines[formattedLines.length - 1] += ',';
  112. }
  113. }
  114. }
  115. formattedLines.push('}');
  116. const chatHistoryFormat = formattedLines.join('\n');
  117. return {
  118. success: true,
  119. messagesJson: chatHistoryFormat, // 返回 chat-history.txt 格式的字符串
  120. messages: messages // 保留原始消息数组(向后兼容)
  121. };
  122. } catch (error) {
  123. return {
  124. success: false,
  125. error: error.message || '提取聊天记录失败'
  126. };
  127. }
  128. }