基于WebOffice JSSDK开发Hook分装

WebOffice 即在线文档预览编辑服务,可为接入方提供专业的文档处理能力。支持文字、表格、演示和 PDF 四大主流文档类型。支持多人协作编辑,内容实时同步。
官方链接 webOffice

export interface IWaterMarksOptions {
  index?: number
  text?: string
  fontName?: string
  fontSize?: number
  fontColor?: string
  transparency?: number
  gradient?: boolean
  applyTo?: number
}

export interface IAddContentOptions {
  start?: number
  end?: number
  textArray: string[]
}

export interface IAddPicOptions {
  start: number
  end: number
  fileName: string
  linkToFile?: boolean
  saveWithDocument?: boolean
}

export interface IInitWebOfficeSDK {
  officeType?: string
  appId?: string
  fileId: string
  token?: string
  mount?: string | HTMLElement
  commonOptions?: any
  wordOptions?: any
}

export interface ICommandBarItem {
  cmbId: string
  visible?: boolean
  enable?: boolean
}

let g_instance: any

export const initWebOfficeSDK = async (
  options?: IInitWebOfficeSDK,
  commandBarIds?: ICommandBarItem[]
) => {
  const { officeType, mount, appId } = options ?? {}

  const initOptions = {
    appId: appId ?? import.meta.env.VITE_APP_ID,
    officeType: officeType ?? 'w',
    token: 'token',
    mount: mount ?? document.body,
    ...options,
  }

  const instance = window.$WebOfficeSDK.init(initOptions)
  g_instance = instance

  await instance.ready()

  // 显示隐藏历史记录、协作记录等
  commandBarIds?.forEach((item: ICommandBarItem) => {
    instance.setCommandBars([
      // 可以配置多个组件
      {
        cmbId: item.cmbId,
        attributes: {
          visible: item.visible ?? true, // 显示隐藏组件
          enable: item.enable ?? true, // 禁用组件, 组件显示但不响应点击事件
        },
      },
    ])
  })

  // 设置
  const app = instance.Application as any

  return { app, instance }
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const useWebOffice = (app: any, instance?: any) => {
  // 销毁wps实例
  const destroyWpsOffice = () => {
    instance?.destroy()
  }

  // 设置为只读
  const setReadOnly = async (ReadOnly?: boolean) => {
    await app.ActiveDocument?.SetReadOnly({
      Value: ReadOnly ?? false,
    })
  }

  // 获取光标位置
  const getCursorPosition = async () => {
    const range = await app.ActiveDocument.ActiveWindow.Selection.Range
    return {
      start: await range.Start,
      end: await range.End,
    }
  }

  // 控制目录显示与否
  const setShoeDocumentMap = (showDocumentMap: boolean) => {
    app.ActiveDocument.ActiveWindow.DocumentMap = showDocumentMap || false
  }

  // 定位到文档末尾
  const positionDocEnd = async () => {
    // 获取选中区域
    const DocumentRange = await app.ActiveDocument.GetDocumentRange()

    // 获取末尾
    const End = await DocumentRange.End

    // 定位到末尾
    const range = await app.ActiveDocument.Range.SetRange(End - 9, End - 9)

    return {
      range,
    }
  }

  // 插入文字水印
  const setWaterMarks = async (options?: IWaterMarksOptions) => {
    const { index, text, fontName, fontSize, fontColor, transparency, gradient, applyTo } =
      options ?? {}
    // 水印对象
    const waterMarks = await app.ActiveDocument.Sections.Item(index ?? 1).WaterMarks
    // 插入文字水印
    await waterMarks.AddTextWaterMark({
      Text: text ?? '水印文案', // Text:水印文本
      FontName: fontName ?? '宋体', // FontName:水印字体类型
      FontSize: fontSize ?? 40, // FontSize:水印字体大小
      FontColor: fontColor ?? '#171717', // FontColor:水印字体颜色
      Transparency: transparency ?? 0.3, // Transparency:透明度
      Gradient: gradient ?? true, // Gradient:倾斜度
      ApplyTo: applyTo ?? 1, // ApplyTo:插入位置
    })
  }

  // 删除内容
  const delContent = async (num: number) => {
    const text = await geWpsWContent()
    await app.ActiveDocument.Range.SetRange(0, text.length)
    // num 见:https://solution.wps.cn/docs/client/api/Enum/Word.html#wdunits
    app.ActiveDocument.ActiveWindow.Selection.Delete(num)
  }

  // 添加html内容
  const addContent = async (options: IAddContentOptions) => {
    const { textArray, start, end } = options || {}
    const HTML = generateTextString(textArray)
    await app.ActiveDocument.Range(start, end).PasteHtml({
      HTML,
    })
  }

  // 添加纯文本
  const addTextContent = async (options: { start: number; end: number; text: string }) => {
    const { text, start, end } = options || {}
    const range = await app.ActiveDocument.Range(start, end)
    // 设置文本
    range.Text = text
  }
  /**
   * 生成文本HTML字符串
   * @param data 文本数据(字符串数组)
   *
   * @return 文本HTML字符串
   */
  const generateTextString = (data: any[]) => {
    if (!Array.isArray(data)) throw TypeError('文本数据不合法')

    return data.map(item => `${item}`).join('')
  }

  // 插入非嵌入式图片
  const addInlineShapesPic = async (options: IAddPicOptions) => {
    // 获取图形对象
    const shapes = await app.ActiveDocument.InlineShapes
    const { fileName, start, end, linkToFile, saveWithDocument } = options || {}
    await shapes.AddPicture({
      FileName: fileName,
      LinkToFile: linkToFile ?? true, // 为 true 表示要将图片链接到创建它的文件,false 使图片文件的独立副本。默认值为 false
      SaveWithDocument: saveWithDocument ?? true, // 为 true 要随文档一起保存的链接的图片。默认值为 false
      Range: {
        start,
        end,
      },
    })
  }

  // 删除图片
  const delPicture = async () => {
    // 获取图形对象
    const shapes = await app.ActiveDocument.InlineShapes
    const count = await shapes.Count

    for (let i = 1; i < count + 1; i++) {
      const shape = await shapes.Item(i)
      // 删除嵌入式图形对象
      await shape.Delete(i)
    }
  }

  // 替换文本
  const replaceText = async (obj: { key: string; value: string }) => {
    const isSuccess = await app.ActiveDocument.ReplaceText([
      {
        key: obj.key,
        value: obj.value,
      },
    ])

    return {
      isSuccess,
    }
  }

  // 保存文件的改动
  const saveFile = async () => {
    await app.ActiveDocument.Save()
  }

  // 轻文档:获取全文内容
  const getWpsOContent = async () => {
    const editor = await app.ActiveOutline?.Editor
    const doc = await editor?.Document
    // 获取文档内容
    const content = await doc?.GetContent()
    return content
  }

  // 获取全文内容
  const geWpsWContent = async () => {
    // 返回一个 Range 对象
    const range = await app.ActiveDocument.Content

    // 获取 range 内文本内容信息
    const content = await range.Text

    return content
  }

  // 保存文档
  const saveDoc = async () => {
    const result = await g_instance.save()
    console.log(result)
  }

  // 设置固定行间距
  const setFixedLineSpacing = async (data: { value: number; unit: number }) => {
    const text = await geWpsWContent()
    // 段落格式对象
    const paragraphFormat = await app.ActiveDocument.Range(0, text.length).ParagraphFormat

    // 设置行间距为18磅固定行间距
    await paragraphFormat.SetFixedLineSpacing(data.value, data.unit)
  }

  // 行间距
  const lineSpacingRule = async (value: number) => {
    const text = await geWpsWContent()
    // 段落格式对象
    const paragraphFormat = await app.ActiveDocument.Range(0, text.length).ParagraphFormat

    // 1.5 倍间距
    paragraphFormat.LineSpacingRule = value ?? 1.5
  }

  // 获取指定区域的带格式 HTML 数据
  const getHtmlData = async (options: { start: number; end: number }) => {
    const { start, end } = options || {}
    // 获取选中区域
    const range = await app.ActiveDocument.Range(start, end)
    // 获取指定区域的带格式 HTML 数据
    const htmlInfo = await range.GetHtmlData()

    return {
      htmlInfo,
    }
  }

  // 插入目录
  const addTablesOfContents = async (options: { start: number; end: number }) => {
    // 区域对象
    const range = await app.ActiveDocument.Range(options.start, options.end)

    // 插入目录
    await app.ActiveDocument.TablesOfContents.Add(range)
  }

  // 插入分隔符
  const insertBreak = async (type: number) => {
    // 选区位置插入分隔符(由于是默认值,所以可以不传)
    await app.ActiveDocument.ActiveWindow.Selection.InsertBreak(type)
  }

  // 删除目录
  const delTablesOfContents = async () => {
    // 获取文档中目录的数量
    const count = await app.ActiveDocument.TablesOfContents.Count
    count && (await app.ActiveDocument.TablesOfContents.Item(1).Delete())
  }

  return {
    app,
    getCursorPosition,
    setReadOnly,
    setShoeDocumentMap,
    setWaterMarks,
    addContent,
    delContent,
    addInlineShapesPic,
    saveFile,
    getWpsOContent,
    geWpsWContent,
    saveDoc,
    addTextContent,
    positionDocEnd,
    replaceText,
    setFixedLineSpacing,
    lineSpacingRule,
    getHtmlData,
    addTablesOfContents,
    insertBreak,
    delTablesOfContents,
    delPicture,
    destroyWpsOffice,
  }
}

你可能感兴趣的:(前端小屋,前端)