1059 lines
37 KiB
C#
1059 lines
37 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Drawing;
|
||
using System.IO;
|
||
using System.Runtime.InteropServices;
|
||
using System.Threading;
|
||
using System.Windows.Forms;
|
||
using AIProofread.Controls;
|
||
using AIProofread.core;
|
||
using AIProofread.Util;
|
||
using log4net;
|
||
using Microsoft.Office.Interop.Word;
|
||
using Newtonsoft.Json;
|
||
using UtilLib;
|
||
using CustomTaskPane = Microsoft.Office.Tools.CustomTaskPane;
|
||
|
||
namespace AIProofread.Model
|
||
{
|
||
/// <summary>
|
||
/// 文档信息 包含文档相关数据、面板及对文档的相关操作
|
||
/// </summary>
|
||
public class DocumentInfo
|
||
{
|
||
public ILog Logger = LogHelper.GetLogger(typeof(DocumentInfo));
|
||
public static readonly int MIN_WIDTH = 420;
|
||
private static char[] ArticleSpecialChars = new char[4] { '\a', '\r', '\v', '\f' };
|
||
|
||
private static object missing = System.Reflection.Missing.Value;
|
||
/// <summary>
|
||
/// 是否已经校对
|
||
/// </summary>
|
||
public bool hasProofreaded = false;
|
||
/// <summary>
|
||
/// 是否已经处理了校对结果
|
||
/// </summary>
|
||
public bool hasProcessMark = false;
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public Dictionary<int, ProofreadItem> marks = new Dictionary<int, ProofreadItem>();
|
||
|
||
/// <summary>
|
||
/// 最小宽度
|
||
/// </summary>
|
||
public static int MinWidth = 0;
|
||
/// <summary>
|
||
/// 校对选区集合
|
||
/// </summary>
|
||
private List<Range> ranges = new List<Range>();
|
||
|
||
/// <summary>
|
||
/// 当前选中对现象编号
|
||
/// </summary>
|
||
private int selectProofreadId;
|
||
|
||
//private Document currentDocument;
|
||
/// <summary>
|
||
/// 当前对应文档
|
||
/// </summary>
|
||
public Document CurrentDocument { get; set; }
|
||
|
||
/// <summary>
|
||
/// 文件名称
|
||
/// </summary>
|
||
public string fileName;
|
||
|
||
private string uniqueId;
|
||
public string UniqueId { get { return uniqueId; } }
|
||
|
||
public string ProofreadCachePath
|
||
{
|
||
get
|
||
{
|
||
return CurrentDocument.FullName + "-proofread.json";
|
||
}
|
||
}
|
||
|
||
public bool IsActive { get; internal set; } = false;
|
||
public bool PaneVisible { get; set; } = false;
|
||
public int Id { get; set; }
|
||
|
||
public CustomTaskPane TaskPane { get; set; }
|
||
public WdProtectionType ProtectionType { get { return CurrentDocument.ProtectionType; } }
|
||
|
||
/// <summary>
|
||
/// 是否已校对
|
||
/// </summary>
|
||
public bool Proofread { get; set; }
|
||
/// <summary>
|
||
/// 是否校对中
|
||
/// </summary>
|
||
public bool Proofreading { get; set; }
|
||
|
||
// 初始化
|
||
public DocumentInfo(Document doc)
|
||
{
|
||
this.CurrentDocument = doc;
|
||
Initialize();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示面板
|
||
/// </summary>
|
||
public void ShowPane()
|
||
{
|
||
if(null == TaskPane)
|
||
{
|
||
CreateTaskPane();
|
||
}
|
||
Logger.Debug("TaskPane.Visible {"+TaskPane==null?"null":(TaskPane.Visible?"true":"false")+" => true");
|
||
TaskPane.Visible = PaneVisible = true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏面板
|
||
/// </summary>
|
||
public void HidePane()
|
||
{
|
||
if (!PaneVisible) return;
|
||
ShowDocumentStatus("HidePane");
|
||
Logger.Debug($"TaskPane.Visible {TaskPane.Visible} => false");
|
||
TaskPane.Visible = PaneVisible = false;
|
||
}
|
||
|
||
public void RunInMainThread(Action action)
|
||
{
|
||
Logger.Debug($"RunInMainThread {action}");
|
||
if (null == TaskPane)
|
||
{
|
||
CreateTaskPane();
|
||
}
|
||
TaskPane.Control.BeginInvoke(action);
|
||
}
|
||
|
||
public void ShowDialog(string message, string confirmText, string confirmAction)
|
||
{
|
||
TaskPane.Control.BeginInvoke(new Action(() =>
|
||
{
|
||
//MessageBox.Show(message, "提示");
|
||
FormMessage.ShowMessage(message, confirmText, confirmAction);
|
||
}));
|
||
}
|
||
public FormMessage ShowMessage(string message, int closeDelay, bool showCloseBtn = true)
|
||
{
|
||
var msgForm = FormMessage.ShowMessage(message, closeDelay);
|
||
if (closeDelay > 0)
|
||
{
|
||
|
||
if (!showCloseBtn)
|
||
{
|
||
msgForm.HideCloseBtn();
|
||
}
|
||
// n毫秒后自动关闭
|
||
System.Threading.Tasks.Task.Delay(closeDelay).ContinueWith(t =>
|
||
{
|
||
if (msgForm.IsDisposed) return;
|
||
TaskPane.Control.BeginInvoke(new Action(() =>
|
||
{
|
||
msgForm.Close();
|
||
}));
|
||
});
|
||
}
|
||
return msgForm;
|
||
}
|
||
|
||
public void ShowLogin(string action)
|
||
{
|
||
TaskPane.Control.BeginInvoke(new Action(() =>
|
||
{
|
||
FormLogin frm = new FormLogin(action);
|
||
Globals.ThisAddIn.LoginFormList.Add(frm);
|
||
frm.ShowDialog();
|
||
}));
|
||
}
|
||
|
||
private void ShowDocumentStatus(string tag)
|
||
{
|
||
// Logger.Log($"{fileName} {tag} PaneVisible is {PaneVisible} Poofread is {Proofread} Proofreading is {Proofreading}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 激活
|
||
/// </summary>
|
||
public void Active()
|
||
{
|
||
ShowDocumentStatus("Active");
|
||
IsActive = true;
|
||
if (Config.IS_WPS && null != TaskPane && PaneVisible)
|
||
{
|
||
TaskPane.Visible = true;
|
||
}
|
||
}
|
||
|
||
public void Deactive()
|
||
{
|
||
ShowDocumentStatus("Deactive");
|
||
IsActive = false;
|
||
if (Config.IS_WPS)
|
||
{
|
||
if (PaneVisible)
|
||
{
|
||
// 异步等待一段时间 重新设置为true,防止面板关闭时,触发事件
|
||
ThreadPool.QueueUserWorkItem(state =>
|
||
{
|
||
Thread.Sleep(500);
|
||
PaneVisible = true;
|
||
});
|
||
}
|
||
if (null != TaskPane && PaneVisible)
|
||
{
|
||
TaskPane.Visible = false;
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
try
|
||
{
|
||
// 释放com
|
||
try
|
||
{
|
||
Marshal.ReleaseComObject(CurrentDocument);
|
||
}
|
||
catch (Exception) { }
|
||
if(TaskPane.Control.IsDisposed) return;
|
||
ProofreadMainControl control = (ProofreadMainControl)TaskPane.Control;
|
||
control.ResetWeb();
|
||
|
||
HidePane();
|
||
TaskPane?.Dispose();
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
LogHelper.Log("Error", e);
|
||
}
|
||
}
|
||
|
||
// 计算uniqueId
|
||
private void ComputeUniqueId()
|
||
{
|
||
string filename = CurrentDocument.FullName;
|
||
if (!string.IsNullOrEmpty(uniqueId) || string.IsNullOrEmpty(filename))
|
||
{
|
||
return;
|
||
}
|
||
// 通过文档路径生成唯一id
|
||
uniqueId = filename.GetHashCode().ToString();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加变量控制重复调用
|
||
/// </summary>
|
||
private bool isResizing = false;
|
||
private void Control_SizeChanged(object sender, EventArgs e)
|
||
{
|
||
if (isResizing) return;
|
||
if (TaskPane != null && TaskPane.Visible && TaskPane.Width < MinWidth)
|
||
{
|
||
isResizing = true;
|
||
SendKeys.Send("{ESC}");
|
||
TaskPane.Width = MinWidth;
|
||
isResizing = false;
|
||
}
|
||
}
|
||
|
||
// 创建pane 并初始化
|
||
public void CreateTaskPane()
|
||
{
|
||
Logger.Debug("CreateTaskPane");
|
||
var control = new ProofreadMainControl();
|
||
if (MinWidth < 10)
|
||
{
|
||
MinWidth = MIN_WIDTH * control.LabelWidth() / 42;
|
||
}
|
||
// 创建pane
|
||
TaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(control, " ");
|
||
// 默认隐藏
|
||
TaskPane.Visible = false;
|
||
// 设置宽度
|
||
control.Width = MinWidth;
|
||
TaskPane.Width = MinWidth;
|
||
|
||
// 监听尺寸变化 防止最小尺寸小于设置值
|
||
control.SizeChanged += Control_SizeChanged;
|
||
TaskPane.VisibleChanged += TaskPane_VisibleChanged;
|
||
}
|
||
|
||
|
||
public void CheckBtnStatus()
|
||
{
|
||
//
|
||
if (Globals.ThisAddIn.ribbon != null)
|
||
{
|
||
Globals.ThisAddIn.ribbon.BtnShowPanel.Enabled = !PaneVisible && Proofread;
|
||
Globals.ThisAddIn.ribbon.SetCommonBtnStatus(!Proofreading);
|
||
}
|
||
}
|
||
|
||
private void TaskPane_VisibleChanged(object sender, EventArgs e)
|
||
{
|
||
// 如果已经隐藏 则记录隐藏用于(WPS)多面板的切换的处理
|
||
PaneVisible = TaskPane.Visible;
|
||
CheckBtnStatus();
|
||
//Globals.ThisAddIn.ribbon.BtnShowPanel.Enabled = !TaskPane.Visible && Proofread;
|
||
}
|
||
|
||
public void Initialize()
|
||
{
|
||
this.fileName = CurrentDocument.FullName;
|
||
ranges.Clear();
|
||
ComputeUniqueId();
|
||
if (TaskPane == null)
|
||
{
|
||
Logger.Debug("init document Initialize(318) and CreateTaskPane");
|
||
CreateTaskPane();
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//处理文档选区时 判断当前选区是否有校对项 有则选择该范围
|
||
public void ProcessSelectionChange(Selection s)
|
||
{
|
||
// 判断选区内是否有书签
|
||
if (s.Bookmarks != null && s.Bookmarks.Count > 0)
|
||
{
|
||
// 判断是否时点击 点击的起始和结束位置相同
|
||
if (s.Range.Start == s.Range.End)
|
||
{
|
||
//
|
||
var count = s.Bookmarks.Count;
|
||
// 原则只有一个书签
|
||
//foreach (Microsoft.Office.Interop.Word.Bookmark item in s.Bookmarks)
|
||
//{
|
||
// int proofreadId = Config.GetBookmarkIdByName(item.Name);
|
||
// if (proofreadId > 0)
|
||
// {
|
||
// //Bridge.bridge.SelectMarkById(proofreadId, 0);
|
||
// return;
|
||
// }
|
||
//}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取当前文档文本
|
||
public string GetAllText()
|
||
{
|
||
return CurrentDocument.Range().Text;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前选中文本
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public string GetSelectedText()
|
||
{
|
||
// 获取当前文档的选区
|
||
var selection = Globals.ThisAddIn.Application.Selection;
|
||
return selection.Text;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取指定选区的文本
|
||
/// </summary>
|
||
/// <param name="range"></param>
|
||
/// <returns></returns>
|
||
public string GetRangeText(Range range)
|
||
{
|
||
string text = range?.Text;
|
||
return string.IsNullOrEmpty(text) ? "" : text;
|
||
}
|
||
/// <summary>
|
||
/// 获取指定选区的文本
|
||
/// </summary>
|
||
/// <param name="start"></param>
|
||
/// <param name="end"></param>
|
||
/// <returns></returns>
|
||
public string GetRangeText(int start, int end)
|
||
{
|
||
if (start >= end) return null;
|
||
return GetRangeText(CurrentDocument.Range(start, end));
|
||
}
|
||
|
||
public Range Range(int start, int end)
|
||
{
|
||
if (start >= end) return null;
|
||
return CurrentDocument.Range(start, end);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存校对缓存结果
|
||
/// </summary>
|
||
private void SaveProofreadCache(string cacheData)
|
||
{
|
||
// 判断文档是否已经保存
|
||
|
||
if (!CurrentDocument.Saved)
|
||
{
|
||
// 保存文档
|
||
if (!CurrentDocument.Saved)
|
||
{
|
||
// 提示保存文档
|
||
var result = MessageBox.Show("当前文档尚未保存,是否保存?", "提示", MessageBoxButtons.YesNo);
|
||
if (result == DialogResult.Yes)
|
||
{
|
||
CurrentDocument.Save();
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// 定位所有的校对项
|
||
public void LocateAllProofreadItems(List<CorrectContext> list)
|
||
{
|
||
// 获取所有的校对项
|
||
//List<Range> proofreadItems = GetProofreadItems();
|
||
var prevOffset = 0;
|
||
foreach (var item in list)
|
||
{
|
||
if (item.CorrectItems != null && item.CorrectItems.Count > 0)
|
||
{
|
||
foreach (var correct in item.CorrectItems)
|
||
{
|
||
var range = LocateProofreadItem(correct, item, ref prevOffset);
|
||
if (range == null) continue;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查找偏移量
|
||
/// </summary>
|
||
private static readonly int INSERT_FIND_OFFSET = 5;
|
||
/// <summary>
|
||
/// 定位校对项
|
||
/// </summary>
|
||
/// <param name="correct">校对项</param>
|
||
/// <param name="ctx">校对上下文</param>
|
||
/// <param name="prevOffset">上一步的</param>
|
||
/// <returns></returns>
|
||
private Range LocateProofreadItem(CorrectItem correct, CorrectContext ctx, ref int prevOffset)
|
||
{
|
||
var document = CurrentDocument;
|
||
// 校对项的段落号超过文档的段落数,直接返回
|
||
if (ctx.ParagraphNumber > document.Paragraphs.Count) return null;
|
||
// 获取当前段落
|
||
var paragraph = document.Paragraphs[ctx.ParagraphNumber];
|
||
if (paragraph == null) return null;
|
||
|
||
|
||
var paraRange = paragraph.Range;
|
||
var paraText = paraRange.Text;
|
||
var paraStart = paraRange.Start;
|
||
|
||
//var offset = paraStart + ctx.SentenceOffset;
|
||
//var cutLength = Math.Min(c.InsertLen, paraText.Length - offset);
|
||
var sentence = paraRange.Sentences[ctx.SentenceNumber]; //paraText.Substring(ctx.SentenceOffset, ctx.InsertLength);
|
||
ctx.SentenceOffset = sentence.Start;
|
||
var offset = paraStart + ctx.SentenceOffset;
|
||
if (sentence.Text == ctx.Insert)
|
||
{ // 比对原始内容与校对原文是否一致
|
||
var range = document.Range(offset + correct.Start, offset + correct.End);
|
||
//
|
||
if (range.Text == correct.Origin) return range;
|
||
}
|
||
|
||
var originText = ctx.Insert;
|
||
// 如果是新增 则查找定位
|
||
if (correct.Tag == "i")
|
||
{
|
||
// 找前缀
|
||
var prefix1 = correct.Start > 2 ? (
|
||
correct.Start > INSERT_FIND_OFFSET
|
||
? originText.Substring(correct.Start - INSERT_FIND_OFFSET, INSERT_FIND_OFFSET)
|
||
: originText.Substring(0, correct.Start)
|
||
) : null;
|
||
// 找后缀
|
||
var suffix1 = prefix1 == null ? (
|
||
correct.End + INSERT_FIND_OFFSET < originText.Length
|
||
? originText.Substring(correct.Start, INSERT_FIND_OFFSET)
|
||
: originText.Substring(correct.Start, originText.Length - correct.Start)
|
||
) : null;
|
||
// 偏移量
|
||
var start1 = prefix1 != null || suffix1 != null
|
||
? paraText.IndexOf(prefix1 ?? suffix1, prevOffset)
|
||
: -1;
|
||
if (start1 != -1)
|
||
{
|
||
var findOffset = paraStart + start1 + (prefix1 != null ? prefix1.Length : 0);
|
||
return document.Range(findOffset, findOffset);
|
||
}
|
||
}
|
||
|
||
// 执行查找
|
||
int wordStart = correct.Start;
|
||
int wordEnd = correct.End;
|
||
|
||
// 找前缀
|
||
var prefix = wordStart > 2 ? (
|
||
wordStart > INSERT_FIND_OFFSET
|
||
? originText.Substring(wordStart - INSERT_FIND_OFFSET, INSERT_FIND_OFFSET)
|
||
: originText.Substring(0, wordStart)
|
||
) : null;
|
||
|
||
// 找后缀
|
||
var suffix = prefix == null ? (
|
||
wordEnd + INSERT_FIND_OFFSET < originText.Length
|
||
? originText.Substring(wordStart, INSERT_FIND_OFFSET)
|
||
: originText.Substring(wordStart, originText.Length - wordStart)
|
||
) : null;
|
||
var start = prefix != null || suffix != null
|
||
? paraText.IndexOf(prefix ?? suffix, prevOffset) // item.start +
|
||
: -1;
|
||
if (start != -1)
|
||
{
|
||
var findOffset = paraRange.Start + start + (prefix != null ? prefix.Length : 0);
|
||
var range = document.Range(findOffset, findOffset + wordEnd - wordStart);
|
||
if (range.Text == correct.Origin) { return range; }
|
||
}
|
||
// 直接定位查找
|
||
start = paraText.IndexOf(correct.Origin, prevOffset);
|
||
if (start == -1) return null;
|
||
// 定位整体开始位置
|
||
start = paraStart + start;
|
||
return document.Range(start, start + correct.Origin.Length);
|
||
|
||
}
|
||
|
||
public void GlobalCallback(string callbackId, string result)
|
||
{
|
||
ProofreadMainControl control = (ProofreadMainControl)TaskPane.Control;
|
||
try
|
||
{
|
||
if (control.web.CoreWebView2 == null)
|
||
{
|
||
Thread.Sleep(1000);
|
||
}
|
||
control.web.CoreWebView2.ExecuteScriptAsync($"window.__global_callback_function('{callbackId}','{result}');");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Log("GlobalCallback", "call web global function error \n" + ex.Message + "\n" + callbackId + result);
|
||
}
|
||
}
|
||
public void SendMessageToWeb(string msg, object data)
|
||
{
|
||
var json = JsonConvert.SerializeObject(new WebMessage(msg, data));
|
||
ProofreadMainControl control = (ProofreadMainControl)TaskPane.Control;
|
||
try
|
||
{
|
||
if (control.web.CoreWebView2 == null)
|
||
{
|
||
Thread.Sleep(1000);
|
||
}
|
||
control.web.CoreWebView2.PostWebMessageAsJson(json);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Log("SendMessage", "send message to web error \n" + ex.Message + "\n" + msg + data.ToString());
|
||
}
|
||
}
|
||
|
||
public void ClearAllProofreadMark()
|
||
{
|
||
try
|
||
{
|
||
selectProofreadId = -1;
|
||
foreach (var item in marks.Values)
|
||
{
|
||
if (item.mark != null)
|
||
{
|
||
if (item.content.Tag == "i" && item.content.IsAccept == AcceptStatus.Default)
|
||
{
|
||
item.mark.Text = "";
|
||
}
|
||
item.ResetMarkStyle();
|
||
}
|
||
}
|
||
DocumentUtil.ClearProofreadMarks();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Log("ClearAllProofreadMark", ex);
|
||
}
|
||
// 清空marks
|
||
marks.Clear();
|
||
}
|
||
|
||
|
||
public void SelectMarkById(int proofreadId)
|
||
{
|
||
SelectMarkById(proofreadId, true);
|
||
}
|
||
/// <summary>
|
||
/// 选中标签
|
||
/// </summary>
|
||
/// <param name="proofreadId"></param>
|
||
public void SelectMarkById(int proofreadId, bool noticeToWeb)
|
||
{
|
||
if (proofreadId == selectProofreadId) return;
|
||
// 取消上一个标签移除
|
||
if (selectProofreadId != -1 && marks.ContainsKey(selectProofreadId))
|
||
{
|
||
var m = marks[selectProofreadId];
|
||
if (m != null && CurrentDocument.Bookmarks.Exists(m.Name))
|
||
{
|
||
marks[selectProofreadId].UnSelect();
|
||
}
|
||
else
|
||
{
|
||
marks.Remove(selectProofreadId);
|
||
}
|
||
}
|
||
selectProofreadId = proofreadId;
|
||
|
||
if (proofreadId != -1 && marks.ContainsKey(proofreadId))
|
||
{
|
||
var mark = marks[proofreadId].mark;
|
||
if (mark == null) return;
|
||
// 已经不存在该标签了
|
||
if (mark != null && !CurrentDocument.Bookmarks.Exists(mark.Name))
|
||
{
|
||
marks.Remove(proofreadId);
|
||
return;
|
||
}
|
||
//object lineNum = (int)mark.Range.Information[WdInformation.wdFirstCharacterLineNumber] - 1;
|
||
//object goToLine = WdGoToItem.wdGoToLine;
|
||
//object goNext = WdGoToDirection.wdGoToNext;
|
||
//Globals.ThisAddIn.Application.ActiveWindow.Selection.GoTo(ref goToLine, ref goNext, ref lineNum);
|
||
//
|
||
//object bookmark = WdGoToItem.wdGoToBookmark;
|
||
//object bookmarkName = mark.Name;
|
||
var targetRange = mark.Range;
|
||
// 选中
|
||
targetRange.Select();
|
||
Globals.ThisAddIn.Application.ActiveWindow.ScrollIntoView(targetRange);//.Selection.GoTo(ref bookmark, ref missing, ref missing, ref bookmarkName);
|
||
|
||
//
|
||
//mark.DisableCharacterSpaceGrid = false;
|
||
// 先滚动到可视区域
|
||
//doc.ActiveWindow.ScrollIntoView(mark.Range);
|
||
marks[proofreadId].Select();
|
||
//Globals.ThisAddIn.SendMessageToWeb("select", proofreadId);
|
||
}
|
||
if (noticeToWeb)
|
||
{
|
||
Globals.ThisAddIn.SendMessageToWeb("select-proofread", proofreadId);
|
||
}
|
||
}
|
||
|
||
|
||
public void InitProofread(List<CorrectContext> list)
|
||
{
|
||
hasProofreaded = true;
|
||
int prevOffset = 0;
|
||
|
||
List<int> disabledList = new List<int>();
|
||
List<InsertMarkData> insertMarks = new List<InsertMarkData>();
|
||
foreach (var correct in list)
|
||
{
|
||
if(LogHelper.LoggerForm != null)
|
||
{
|
||
LogHelper.Log(string.Format("correct content:{0}", correct.Insert));
|
||
}
|
||
int currentOffset = correct.SentenceOffset;
|
||
if (correct.CorrectItems != null && correct.CorrectItems.Count > 0)
|
||
{
|
||
prevOffset = 0;
|
||
int index = 0;
|
||
foreach (var item in correct.CorrectItems)
|
||
{
|
||
if (marks.ContainsKey(item.Id)) continue;
|
||
// Logger.Log(string.Format("mark type {0} data {1}->{2}", item.Tag, item.Origin, item.Text));
|
||
int _prev = prevOffset;
|
||
bool isDisabled = false;
|
||
// 判断查找内容是否在原始数据中,否则直跳过
|
||
if(item.Tag != "i" && item.Origin.Trim().Length > 0)
|
||
{
|
||
isDisabled = correct.Insert.IndexOf(item.Origin) == -1;
|
||
}
|
||
// 查找对应区域并再该区域添加书签
|
||
var mark = isDisabled ? null : DocumentUtil.FindRangeAndCreateBookmark(item, correct, CurrentDocument, ref prevOffset);
|
||
// 防止调用方法中没有更新
|
||
if (_prev >= prevOffset)
|
||
{
|
||
prevOffset = currentOffset + item.Start;
|
||
}
|
||
|
||
if (item.Tag != "i") index++;
|
||
if (mark != null)
|
||
{
|
||
marks.Add(item.Id, new ProofreadItem(item, correct.Insert, mark, Id));
|
||
try
|
||
{
|
||
if (item.Tag == "i")
|
||
{
|
||
insertMarks.Add(new InsertMarkData()
|
||
{
|
||
Mark = mark,
|
||
InsertLength = item.Text.Length
|
||
});
|
||
}
|
||
else
|
||
{
|
||
SetMarkStyle(mark);
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
LogHelper.Log(string.Format("mark color error {0}", e.Message));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
disabledList.Add(item.Id);
|
||
var msg = new Dictionary<string, object>{
|
||
{"message","没有找到标记对象" },
|
||
{ "origin",item },
|
||
{ "origin_correct",correct },
|
||
{ "new_text",correct.NewText },
|
||
{ "paragraph_num",correct.ParagraphNumber },
|
||
};
|
||
LogHelper.Log(JsonConvert.SerializeObject(msg));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 为了避免影响其他文本定位,操作完成后才使用空格填充
|
||
try
|
||
{
|
||
foreach (var item in insertMarks)
|
||
{
|
||
item.Mark.Text = ToolUtil.GetBlankText(item.InsertLength);
|
||
SetMarkStyle(item.Mark);
|
||
}
|
||
}
|
||
catch (Exception) { }
|
||
insertMarks.Clear();
|
||
//foreach (var item in marks)
|
||
//{
|
||
// if (item.Value.mark != null)
|
||
// {
|
||
// if (item.Value.content.Tag == "i")
|
||
// {
|
||
// item.Value.mark.Text = ToolUtil.GetBlankText(item.Value.content.Text.Length);
|
||
// }
|
||
// if (item.Value.content.Color != null)
|
||
// {
|
||
// try
|
||
// {
|
||
// var color = (WdColor)ColorTranslator.ToOle(Colors.FromHex(item.Value.content.Color));
|
||
// // 给选区添加背景颜色
|
||
// item.Value.mark.Shading.BackgroundPatternColor = color;
|
||
// }
|
||
// catch (Exception)
|
||
// {
|
||
// //item.Value.mark.Shading.BackgroundPatternColor = WdColor.wdColorLightOrange;
|
||
// }
|
||
// }
|
||
// }
|
||
//}
|
||
|
||
// 隐藏面板对应校对项
|
||
MainPanelWebMessage.DisabledProofreadItem(disabledList);
|
||
}
|
||
|
||
private void SetMarkStyle(Microsoft.Office.Tools.Word.Bookmark mark)
|
||
{
|
||
// 颜色转码
|
||
var color = (WdColor)ColorTranslator.ToOle(Colors.FromHex(Config.TextBackgroundColor));
|
||
// 给选区添加背景颜色
|
||
mark.Shading.BackgroundPatternColor = color;
|
||
}
|
||
|
||
|
||
public void InitProofreadCache(List<CorrectContext> list,Dictionary<int, ProofreadRangeInfo> itemInfoDic)
|
||
{
|
||
marks.Clear();
|
||
|
||
foreach (var correct in list)
|
||
{
|
||
correct.CorrectItems.ForEach(item =>
|
||
{
|
||
var mark = DocumentUtil.FindBookMarkByCorrect(item);
|
||
if (mark != null)
|
||
{
|
||
var pi = new ProofreadItem(item, correct.Insert, mark, Id);
|
||
// 是否存在样式信息
|
||
if (itemInfoDic!= null && itemInfoDic.ContainsKey(item.Id))
|
||
{
|
||
// 获取样式信息并还原
|
||
var info = itemInfoDic[item.Id];
|
||
try
|
||
{
|
||
pi.originColor = info.Color;
|
||
pi.originBackgroundColor = info.Background;
|
||
pi.originSize = info.Size;
|
||
}
|
||
catch (Exception ex) { LogHelper.Log(ex); }
|
||
}
|
||
marks.Add(item.Id, pi);
|
||
}
|
||
});
|
||
//marks.Add(item.Id, new ProofreadItem(item.CorrectItems[0], null, Id));
|
||
}
|
||
}
|
||
|
||
private void FindMarkByCorrectItem()
|
||
{
|
||
|
||
}
|
||
|
||
public DocumentContent GetAllParagraphs()
|
||
{
|
||
string rangeText = CurrentDocument.Content.Text;
|
||
string trimText = HostHelper.ReplaceSpecialChars(rangeText, isReplaceMultSpaceLine: true);
|
||
|
||
string[] separator = new string[5] { "\r\a", "\a", "\r", "\v", "\f" };
|
||
string[] array4 = rangeText.Split(separator, StringSplitOptions.None);
|
||
string[] array5 = trimText.Split('\n');
|
||
|
||
List<string> list = new List<string>();
|
||
var paragraphs = CurrentDocument.Paragraphs;
|
||
int total = paragraphs.Count;
|
||
for (int i = 1; i <= total; i++)
|
||
{
|
||
list.Add(GetParagraphText(paragraphs[i]));
|
||
}
|
||
|
||
return new DocumentContent()
|
||
{
|
||
OriginCut = array4,
|
||
TrimCut = array5,
|
||
Paragraphs = list.ToArray(),
|
||
};
|
||
}
|
||
|
||
private string GetParagraphText(Paragraph paragraph)
|
||
{
|
||
// 需要
|
||
return GetRangeText(paragraph.Range);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取文档段落总数
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public int GetTotalParagraphNumber()
|
||
{
|
||
return CurrentDocument.Paragraphs.Count;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 读取文档原始文件并转换成base64
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public string GetOriginFileData()
|
||
{
|
||
FileStream fs = new FileStream(CurrentDocument.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||
byte[] bytes = new byte[fs.Length];
|
||
fs.Read(bytes, 0, bytes.Length);
|
||
return Convert.ToBase64String(bytes);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 采纳校对项
|
||
/// </summary>
|
||
/// <param name="proofreadId"></param>
|
||
/// <param name="status"></param>
|
||
internal void ProcessMark(int proofreadId, int status)
|
||
{
|
||
// 是否存在书签
|
||
if (proofreadId > 0 && marks.ContainsKey(proofreadId))
|
||
{
|
||
hasProcessMark = true;
|
||
// 采纳
|
||
marks[proofreadId].Process(status);
|
||
}
|
||
}
|
||
|
||
internal bool Saved()
|
||
{
|
||
if (CurrentDocument.Saved)
|
||
{
|
||
return true;
|
||
}
|
||
if (!hasProofreaded && !CurrentDocument.Saved) // 没有校对前需要提示保存
|
||
{
|
||
return false;
|
||
}
|
||
if (hasProofreaded && hasProcessMark && !CurrentDocument.Saved)
|
||
{
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
public void Save()
|
||
{
|
||
try
|
||
{
|
||
CurrentDocument.Save();
|
||
}catch (Exception ex)
|
||
{
|
||
LogHelper.Log(ex);
|
||
}
|
||
}
|
||
public void FocusToPanel()
|
||
{
|
||
TaskPane.Visible = true;
|
||
TaskPane.Control.Focus();
|
||
}
|
||
|
||
public void Close()
|
||
{
|
||
try
|
||
{
|
||
// 清除标记内存数据
|
||
marks.Clear();
|
||
// 清除区域相关数据
|
||
ranges.Clear();
|
||
// TaskPane.Dispose();
|
||
this.Dispose();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Log(ex);
|
||
}
|
||
}
|
||
|
||
public void ExportResult(string modelType)
|
||
{
|
||
TaskPane.Control.BeginInvoke(new Action(() =>
|
||
{
|
||
DocumentUtil.ExportProofreadResult(modelType);
|
||
}));
|
||
}
|
||
|
||
public void ShowUpgrade(string data, bool force)
|
||
{
|
||
TaskPane.Control.BeginInvoke(new Action(() =>
|
||
{
|
||
var upgradeData = JsonConvert.DeserializeObject<UpgradeData>(data);
|
||
var needUpgrade = upgradeData.NeedUpgrade(Config.APP_VERSION);
|
||
//force = force && !Config.UpgradeForcedNotice;
|
||
|
||
if (force)
|
||
{
|
||
// 已经强制更新但被忽略过则不再提示
|
||
if (Config.UpgradeForcedNotice) return;
|
||
|
||
var result = MessageBox.Show(upgradeData.Message, "是否确认更新", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
|
||
if (result == DialogResult.No)
|
||
{
|
||
Config.UpgradeForcedNotice = true;
|
||
Globals.ThisAddIn.ribbon.SetBtnStatus("disable-by-upgrade", false);
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (upgradeData.Ext == 1)
|
||
{
|
||
if (!needUpgrade)
|
||
{
|
||
ShowDialog("当前版本为最新版本,无需升级", "", "");
|
||
}
|
||
else
|
||
{
|
||
if (!force)
|
||
{
|
||
// 非强制则再问一次
|
||
var ret = MessageBox.Show(upgradeData.Message, "是否确认更新", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
|
||
if (ret == DialogResult.No)
|
||
{
|
||
Globals.ThisAddIn.ribbon.SetBtnStatus("disable-by-upgrade", false);
|
||
return;
|
||
}
|
||
}
|
||
|
||
Bridge.bridge.OpenUrlWithOsBrowser(upgradeData.DownloadUrl);
|
||
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Bridge.StartUpgradeProcess();
|
||
}
|
||
}));
|
||
}
|
||
|
||
public void ShowSetting()
|
||
{
|
||
|
||
TaskPane.Control.BeginInvoke(new Action(() =>
|
||
{
|
||
FormSetting frm = new FormSetting();
|
||
frm.Show();
|
||
}));
|
||
}
|
||
public void ShowWebView(string url, int width, int height, bool dialog)
|
||
{
|
||
TaskPane.Control.BeginInvoke(new Action(() =>
|
||
{
|
||
FormWebView view = new FormWebView(url, width, height);
|
||
if (dialog)
|
||
{
|
||
view.StartPosition = FormStartPosition.CenterScreen;
|
||
view.ShowDialog();
|
||
}
|
||
else
|
||
{
|
||
view.StartPosition = FormStartPosition.CenterParent;
|
||
view.Show();
|
||
}
|
||
}));
|
||
}
|
||
|
||
public Dictionary<int, ProofreadRangeInfo> GetProofreadOriginData()
|
||
{
|
||
Dictionary<int,ProofreadRangeInfo> dic = new Dictionary<int, ProofreadRangeInfo>();
|
||
// 变量文档所有marks 记录mark对应range的背景、大小、颜色
|
||
foreach (var item in marks)
|
||
{
|
||
if (item.Value.mark != null)
|
||
{
|
||
// 添加到数据
|
||
dic.Add(item.Key, new ProofreadRangeInfo()
|
||
{
|
||
Background = item.Value.originBackgroundColor,
|
||
Color = item.Value.originColor,
|
||
Size = item.Value.originSize
|
||
});
|
||
}
|
||
}
|
||
return dic;
|
||
}
|
||
|
||
public void CheckPanel()
|
||
{
|
||
LogHelper.Log(CurrentDocument.FullName + $" TaskPane visible {PaneVisible} has " + (TaskPane == null ? "null" : "exists"));
|
||
if (TaskPane == null) CreateTaskPane();
|
||
}
|
||
}
|
||
}
|