明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 4916|回复: 6

[其它] ONLYOFFICE多人协作在线编辑文档的部署与开发细节——值得拥有

  [复制链接]
发表于 2018-2-20 11:08 | 显示全部楼层 |阅读模式
本帖最后由 3xxx 于 2018-4-15 20:29 编辑





用golang语言开发的文档管理界面:永久开源,免费使用。

中文界面的ONLYOFFICE进行word在线协作效果:

powerpoint在线协作的效果:

excel表格的在线协作效果:

大家按照附件中的步骤部署一个在局域网,就可以所有人享受协作文档的乐趣了。

5、二次开发EngineerCMS

(1)运行前要替换EngineerCMS\views\onlyoffice\onlyoffice.tpl中的3处IP,如果engineercms和docker安装在同一个电脑上,那么三个IP相同,见5.1节。

(2)访问前要按照第6节中的方法设置宿主机(安装docker的电脑)的端口转发。

下文的开发仅供兴趣参考。

5.1 协作编辑页面——汉化界面

EngineerCMS\views\onlyoffice\onlyoffice.tpl

  1. <!DOCTYPE html>
  2. <html style="height: 100%;">
  3. <head>
  4.     <title>fei-OnlyOffice</title>
  5. </head>
  6. <body style="height: 100%; margin: 0;">

  7.     <div id="placeholder" style="height: 100%"></div>
  8.     <script type="text/javascript" src="http://192.168.99.100:9000/web-apps/apps/api/documents/api.js"></script>
  9.     <script type="text/javascript">
  10.         // alert({{.Doc.FileName}});
  11.         window.docEditor = new DocsAPI.DocEditor("placeholder",
  12.             {
  13.                 "document": {
  14.                     "fileType": "{{.fileType}}",
  15.                     "key": "{{.Key}}",//"Khirz6zTPdfd7"
  16.                     "title": "{{.Doc.FileName}}",
  17.                     "url": "http://192.168.99.1/attachment/onlyoffice/{{.Doc.FileName}}"
  18.                 },
  19.                 "documentType": "{{.documentType}}",
  20.                 "editorConfig": {
  21.                     "callbackUrl": "http://192.168.99.1/url-to-callback?id={{.Doc.Id}}",
  22.                     "user": {
  23.                         "id": "{{.Uid}}",
  24.                         "name": "{{.Uname}}"
  25.                     },
  26.                     "lang": "zh-CN",//"en-US",
  27.                 },
  28.                 "height": "100%",
  29.                 "width": "100%"
  30.             });
  31.     </script>
  32. </body>
  33. </html>
复制代码

5.2 协作页面的保存和回调

  1. package controllers

  2. import (
  3.   "encoding/json"
  4.   "engineercms/models"
  5.   "github.com/astaxie/beego"
  6.   "io/ioutil"
  7.   "net/http"
  8.   "net/url"
  9.   "os"
  10.   "path"
  11.   "regexp"
  12.   "strconv"
  13.   "strings"
  14.   "time"
  15. )

  16. type OnlyController struct {
  17.   beego.Controller
  18. }

  19. type Callback struct {
  20.   Key         string   `json:"key"`
  21.   Status      int      `json:"status"`
  22.   Url         string   `json:"url"`
  23.   Changesurl  string   `json:"changesurl"`
  24.   History     history  `json:"history"`
  25.   Users       []string `json:"users"`
  26.   Actions     []action `json:"actions"`
  27.   Lastsave    string   `json:"lastsave"`
  28.   Notmodified bool     `json:"notmodified"`
  29. }

  30. type action struct {
  31.   Type   int
  32.   userid string
  33. }

  34. type history struct {
  35.   changes       []change
  36.   serverVersion string
  37. }

  38. type change struct {
  39.   created string
  40.   User    User1
  41. }

  42. type User1 struct {
  43.   id   string
  44.   name string
  45. }

  46. //协作页面的显示
  47. func (c *OnlyController) OnlyOffice() {
  48.   id := c.Ctx.Input.Param(":id")
  49.   //pid转成64为
  50.   idNum, err := strconv.ParseInt(id, 10, 64)
  51.   if err != nil {
  52.     beego.Error(err)
  53.   }
  54.   //根据附件id取得附件的prodid,路径
  55.   onlyattachment, err := models.GetOnlyAttachbyId(idNum)
  56.   if err != nil {
  57.     beego.Error(err)
  58.   }
  59.   c.Data["Doc"] = onlyattachment

  60.   c.Data["Key"] = strconv.FormatInt(onlyattachment.Updated.UnixNano(), 10)

  61.   var uname string
  62.   v := c.GetSession("uname")
  63.   if v != nil {
  64.     uname = v.(string)
  65.     c.Data["Uname"] = v.(string)

  66.     user, err := models.GetUserByUsername(uname)
  67.     if err != nil {
  68.       beego.Error(err)
  69.     }
  70.     c.Data["Uid"] = user.Id
  71.     // useridstring = strconv.FormatInt(user.Id, 10)
  72.   } else {
  73.     c.Data["Uname"] = c.Ctx.Input.IP()
  74.     c.Data["Uid"] = c.Ctx.Input.IP()
  75.   }

  76.   if path.Ext(onlyattachment.FileName) == ".docx" || path.Ext(onlyattachment.FileName) == ".DOCX" {
  77.     c.Data["fileType"] = "docx"
  78.     c.Data["documentType"] = "text"
  79.   } else if path.Ext(onlyattachment.FileName) == ".XLSX" || path.Ext(onlyattachment.FileName) == ".xlsx" {
  80.     c.Data["fileType"] = "xlsx"
  81.     c.Data["documentType"] = "spreadsheet"
  82.   } else if path.Ext(onlyattachment.FileName) == ".pptx" || path.Ext(onlyattachment.FileName) == ".PPTX" {
  83.     c.Data["fileType"] = "pptx"
  84.     c.Data["documentType"] = "presentation"
  85.   } else if path.Ext(onlyattachment.FileName) == ".doc" || path.Ext(onlyattachment.FileName) == ".DOC" {
  86.     c.Data["fileType"] = "doc"
  87.     c.Data["documentType"] = "text"
  88.   } else if path.Ext(onlyattachment.FileName) == ".txt" || path.Ext(onlyattachment.FileName) == ".TXT" {
  89.     c.Data["fileType"] = "txt"
  90.     c.Data["documentType"] = "text"
  91.   } else if path.Ext(onlyattachment.FileName) == ".XLS" || path.Ext(onlyattachment.FileName) == ".xls" {
  92.     c.Data["fileType"] = "xls"
  93.     c.Data["documentType"] = "spreadsheet"
  94.   } else if path.Ext(onlyattachment.FileName) == ".csv" || path.Ext(onlyattachment.FileName) == ".CSV" {
  95.     c.Data["fileType"] = "csv"
  96.     c.Data["documentType"] = "spreadsheet"
  97.   } else if path.Ext(onlyattachment.FileName) == ".ppt" || path.Ext(onlyattachment.FileName) == ".PPT" {
  98.     c.Data["fileType"] = "ppt"
  99.     c.Data["documentType"] = "presentation"
  100.   }

  101.   u := c.Ctx.Input.UserAgent()
  102.   matched, err := regexp.MatchString("AppleWebKit.*Mobile.*", u)
  103.   if err != nil {
  104.     beego.Error(err)
  105.   }
  106.   if matched == true {
  107.     // beego.Info("移动端~")
  108.     c.TplName = "onlyoffice/onlyoffice.tpl"
  109.   } else {
  110.     // beego.Info("电脑端!")
  111.     c.TplName = "onlyoffice/onlyoffice.tpl"
  112.   }
  113. }

  114. //协作页面的保存和回调
  115. //关闭浏览器标签后获取最新文档保存到文件夹
  116. func (c *OnlyController) UrltoCallback() {
  117.   // pk1 := c.Ctx.Input.RequestBody
  118.   id := c.Input().Get("id")
  119.   //pid转成64为
  120.   idNum, err := strconv.ParseInt(id, 10, 64)
  121.   if err != nil {
  122.     beego.Error(err)
  123.   }
  124.   //根据附件id取得附件的prodid,路径
  125.   onlyattachment, err := models.GetOnlyAttachbyId(idNum)
  126.   if err != nil {
  127.     beego.Error(err)
  128.   }

  129.   var callback Callback
  130.   json.Unmarshal(c.Ctx.Input.RequestBody, &callback)

  131.   if callback.Status == 1 || callback.Status == 4 {
  132.     c.Data["json"] = map[string]interface{}{"error": 0}
  133.     c.ServeJSON()
  134.   } else if callback.Status == 2 {
  135.     resp, err := http.Get(callback.Url)
  136.     if err != nil {
  137.       beego.Error(err)
  138.     }
  139.     body, err := ioutil.ReadAll(resp.Body)
  140.     if err != nil {
  141.       beego.Error(err)
  142.     }
  143.     defer resp.Body.Close()
  144.     if err != nil {
  145.       beego.Error(err)
  146.     }

  147.     f, err := os.OpenFile(".\\attachment\\onlyoffice\"+onlyattachment.FileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm)
  148.     if err != nil {
  149.       beego.Error(err)
  150.     }
  151.     defer f.Close()
  152.     _, err = f.Write(body)
  153.     // _, err = f.WriteString(str)
  154.     // _, err = io.Copy(body, f)
  155.     if err != nil {
  156.       beego.Error(err)
  157.     } else {
  158.       err = models.UpdateOnlyAttachment(idNum)
  159.       if err != nil {
  160.         beego.Error(err)
  161.       }
  162.     }
  163.     c.Data["json"] = map[string]interface{}{"error": 0}
  164.     c.ServeJSON()
  165.   }
  166. }
复制代码



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2018-2-21 18:12 | 显示全部楼层
学习中,不错的资料
 楼主| 发表于 2018-2-26 20:47 | 显示全部楼层
自己部署过程中遇到什么问题,请从附件中联系到我,互相沟通
 楼主| 发表于 2018-3-3 11:29 | 显示全部楼层
很长时间,我都想给自己企业部署一个免费开源的文档协作系统,不是那种project wise的协同概念,是协作,大家打开同一个文件,同时进行编辑。这种技术已经发展了十多年了,我们大部分人都没用上。好可惜。

大家有无注意到目前文档协作已经发展了好多年,国内的比如石墨文档,一起写等基于云存储。微软的office365,office online,google doc,quip等。

但是想自己企业部署一个给众人用的免费开源的不多。所以我推荐这款,你只要在局域网或云主机上装一下,就能实现文档协作啦~~~

好处是毋庸置疑的,大家可以同时在一个文档上进行编辑,实时的,效果很震撼。

号称颠覆了传统的office办公软件工作习惯了,

比如,彻底免去了汇总负责人的工作,传统的多专业协作一个文档,都是要指派一个人进行负责汇总,现在不用了,你传个文档上去,把链接发给大家,大家随时打开就可以编辑,互不影响,互相又能看见彼此的编辑效果。

会议纪要写好了,要发给大家看看有无修改意见,以前改一个字也要用邮件发回来,很多人修改的情况下,汇总的工作量蛮大,而且没啥意义,现在不用了,发个链接给大家,有意见直接改。

工作进度表,多人的工作进度表要汇总,而且领导要求这样的表格不断更新,要么用专门的软件,要么用这个实时文档协作,随时都可以在总表上修改自己的部分,领导随时可以看到最终的结果,而不必被领导催着更新表格了。
 楼主| 发表于 2018-3-25 21:23 | 显示全部楼层
改进了界面,支持pdf阅览,txt文件、doc、docx、excel和ppt文件的实时协作。
支持历史版本管理:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
 楼主| 发表于 2018-4-15 19:33 | 显示全部楼层
我们设计过程中大量采用excel计算书,因为很多经典的计算都可以用excel解决,最最基本的就是工程量计算啦。稍微复杂的比如钢管计算,埋地钢管结构计算,顶管计算,水力学计算,波浪爬高计算,堤防高程计算,挡土墙稳定计算,溢洪道计算,水闸消能计算等,统统可以用excel编写公式解决。

而且随着工作的积累,这些计算书越来越多了,有同事们一起编写的,经过校核和审查的,有的根据需要不断去扩展,去完善的,达到参数化要求的。

比如一些参数化的工程量计算书,一些钢筋图甚至都可以用excel来做,比如输入结构尺寸,得出每种钢筋的长度和重量,钢筋表采用参数化,对于那些标准图,都可以这样来做。

问题来了,这么多excel计算书可以网络化吗?

2个思路,一个是web上设计一个输入表单,后台采用代码重新写这些excel里面的公式,注意,必须用代码写公式,我认为这个工作量太大了,excel里面简单的加加减减乘乘除除,到了代码里,首先要定义变量,然后写公式,然后得到结果,然后输出到前段web页面列表显示,工作量不是一般的大哦,而且维护麻烦,修改也麻烦,想改一个公式,那也是要了老命了吧。

自从有了文档协作,这个似乎看到了光明。

把这个excel计算书传上去,设置权限,任何人打开它就是一个原本的计算书,在里面计算,得到结果,下载下来。校核的人打开,查阅,检查。审查的人,甚至可以同步查看计算书。

不用来回邮件传递计算书,校核审查的人可以在上面直接修改,添加批注。

确实不错的选择。值得推荐。

附件:

人类每次有新工具出现都会伴随应用发展,比如有了遥感图,大家就可以往上面叠加东西。文档协作对于我,解决了之前很多困挠,比如任务工作量统计或加班登记,不用协作就要发邮件,或开发网页表单,每个人填好提交,后端写入数据库,统计,再展示出来,可以设查看权限,大家彼此之间看不到,只有领导看到全局。用文档协作,直接在Excel中填,它去汇总,少了大量开发。

还有标准化应用,每次大家写工程量,项目、单位不尽统一,先固定好这些项目和单位,协作填上数量就好。

一些Excel的计算书,放协作上,大家随时拿来算,这放以前,共享计算书,下载,每次改进,日积月累,都不知到底用哪个。解决了Excel计算书网络发布,在线计算的难题。

最近和同事协作会务,事项有30多,专家随时变动,订票,退票,会议通知,专家意见初稿,等等,以往要发上百次邮件。

珠三角月报第一次协作,两三天几十个专业基本都填完了。

还有好多,呼应前文,有新工具,人才会不断朝那方面靠,去利用。就像会编程和不会编程的人,思路完全不一样啊。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-4-26 20:39 , Processed in 0.409209 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表