葡京国际平台依据Metronic的Bootstrap开发框架经验总结(17)– 使用 summernote插件实现HTML文档的编写和图表插入操作

于重重场子,我们得在线编HTML内容,然后以页面上或者其他终端上(如小序、APP应用等)显示,编辑HTML内容之插件有为数不少,本篇介绍因Bootstrap的 summernote插件实现HTML文档的编制和图片插入操作,这个控件的利用大便于,并且用户群也特别充分。

升級到 Delphi 10.2 Tokyo 笔记:

Summernote
是一个概括利落,所展现即所得(WYSIWYG)的编辑器,Summernote是一个轻量级、灵活基于Bootstrap和jQuery的HTML文本编辑器,拥有强大的API配置功能,多国语言支持支持Bootstrap2.x和3.0,支持视频以及图表上传以及代码的高亮显示,多种
后台语言版示例以及多主体支持,在浏览器兼容方面,支持IE9+以及现代之浏览器Chrome,Firefox,Safari等,在倒端应该来科学的呈现,还是特别对的,值得以。

  • 更新 Xcode 8.3 & iOS 10.3 测试:
    • macOS 没问题(可 Debug)
    • iOS Simulator 没问题(可 Debug)
    • iOS Device 64
      有题目,无法发布暨真机
      :(相同环境,换回 Delphi 10.1.2
      可以健康发布暨真机,可是非能够充分成
      IPA,在法定非供 HotFix 前,不要更新 Xcode
      8.3
      )注:因为 Xcode 8.3 已取消 xcrun PackageApplication
      改用 xcodebuild
      葡京国际平台 1
    • 暂缓解方式:http://stackoverflow.com/questions/43094380/whats-the-replacement-for-xcodes-packageapplication/43550906#43550906
  • 类型 TULargeInteger 需改用 ULARGE_INTEGER
  • MapView 载图已支持(iOS & Android):
    • 不用改:FMX.Maps.Android.pas
    • 不用改:FMX.Maps.iOS.pas
  • Android 无法载入 GIF
    问题就更正:https://quality.embarcadero.com/browse/RSP-11327

    • 不用改:FMX.Graphics.Android.pas
  • THTTPClient.BeginGet 回传类型改变:

    • // Delphi 10.1.2 Berlin

      var HTTPResponse: IHTTPResponse;
      HTTPResponse:= HTTPClient1.BeginGet(...);
      
      // Delphi 10.2 Tokyo
      var AsyncResult: IAsyncResult;
      AsyncResult := HTTPClient1.BeginGet(...);
      

       

  • 已修正:https://quality.embarcadero.com/browse/RSP-12693 左:Delphi 10.1.2
    Berlin
    右:Delphi 10.2 Tokyo
    葡京国际平台 2

  • Android
    平台,启动已经无黑屏,之前使用的黑屏处理办法,可以不再需要以了。
  • 线程绘图测试:Test Multi Thread Bitmap
    http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Multi-Threading_for_TBitmap,_TCanvas,_and_TContext3D

    葡京国际平台 3

  • 问题:FMX 使用 TPopup :

    • 拓宽一个 TEdit,运行时点吻合这个 Edit 没有游标?
    • 放一个 TMemo.ReadOnly = True 会弹有键盘?
  • (ID:
    30781
    已修正)

    题材:TMessageManager.DefaultManager.SubscribeToMessage
    没作用了?(实测只有 Android 平台发出问题,其它平台没有问题)

    • 遵照 button1 ,并无会见交 test
      葡京国际平台 4
    • 感谢 swish 提示,因为:Android 下 OnIdle
      事件非会见让正常点造成的,可以自己调用下 WakeMainThread
      就可知接触发一样赖 OnIdle
      葡京国际平台 5
  • (ID:
    30781 已修正)

    题目:使用 AddObject 造成重影问题(移动平台 Android & iOS
    才发生问题,Windows & macOS 测试没问题)

    • 第一步: 使用 Rectangle1.AddObject(SubRectangle);
    • 第二步: 使用 Rectangle2.AddObject(SubRectangle);
    • 还反覆第一步,第二步,造成重影及卡顿?
    • 官方QC:https://quality.embarcadero.com/browse/RSP-17663
    • 葡京国际平台 6
    • 测试工程:[测试]10.2_重影问题.zip
    • 修正方法:
      以 FMX.Controls.pas 复制到好之工目录下,再修改如下:

      procedure TStyledControl.SetNewScene(AScene: IScene);
      var
        OldScene: IScene;
      begin
        OldScene := FScene;
        inherited SetNewScene(AScene);
        if not (csDestroying in ComponentState) and (OldScene <> AScene) and (not IsUpdating)  then
      {---> KillResourceLink; // 删除代码
      {+++>}NeedStyleLookup; // 加入代码:移动平台重影问题,改回 Delphi 10.1.2 Berlin 代码,暂时修正 by Aone
      end;
      
    • 葡京国际平台 7

  • 问题:如果改动官方源码 FMX.Types.pas 会造成无法编译 macOS
    平台(其它平台正常),错误如下:
    葡京国际平台 8
  • (ID:
    30781 已修正)

    题材:TTabControl 加二页,第一页放 TText,第二页放
    TColorPanel,真机运行后,点次页,无法即时亮第二页内容,需要再次沾转,才见面显示。(Android 有问题 iOS 测试没问题)
    测试APK:[BUG]TabControl切页无法就经常显示.apk
    测试工程:[BUG]TabControl切页无法就经常显示.zip 官方QC:https://quality.embarcadero.com/browse/RSP-17738
  • 问题:(Delphi 10.1.2 正常)
    容平:在 TRectangle 里放一个 TButton(需要设置
    ModalResult=mrOk),点 Button 后用 Rectangle 由主窗 RemoveObject
    后失误
    现象二:如果一个 Frame 里生一个关门按钮,按下后关(使用
    Frame.Parent := nil; 或 RemoveObject )就会见错
    葡京国际平台 9
    测试工程:[BUG]TestRemoveObjectScene.zip 修正方法:关键问题是在 ModalResult
    = mrOk,只要非设置 Button.ModalResult 就无见面发错了(另外呢可参考
    10.1.2 的 FMX.Controls.pas 内 TControl.SetNewScene(AScene: IScene)
    函数)
    官方QC:https://quality.embarcadero.com/browse/RSP-17741
  • (ID:
    30781 已修正)

    问题:Android 开启相簿(使用官方例子),闪退?
    官方例子:http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Taking_Pictures_Using_FireMonkey_Interfaces
  • 问题:在 Linux 平台,uses System.Zip 会出错?
    葡京国际平台 10官方QC:https://quality.embarcadero.com/browse/RSP-17811 缓解方案:安装
    sudo apt-get install joe wget
    p7zip-full curl build-essential zlib1g-dev
    libcurl4-gnutls-dev
  • (ID:
    30781 已修正)

    题材:Android 平台运用 TControl.MakeScreenshot
    若发生文,截图继,文字会变成黑块。

拖欠插件是开源的,官网地址:http://summernote.org/,GitHub地址:https://github.com/summernote/summernote/、安装调整都颇便利。

 

1、Summernote的简易利用

利用办法:

1)、加载JS和CSS

<!-- include libraries(jQuery, bootstrap) -->
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script> 
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.js"></script> 

<!-- include summernote css/js-->
<link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.7/summernote.css" rel="stylesheet">
<script src="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.7/summernote.js"></script>

据悉MVC的Asp.net应用程序中,我们一般在BundleConfig.cs里面初始化我们的引入JS文件,如下所示。

            //添加对bootstrap-summernote的支持
            css_metronic.Include("~/Content/metronic/assets/global/plugins/bootstrap-summernote/summernote.css");
            js_metronic.Include("~/Content/metronic/assets/global/plugins/bootstrap-summernote/summernote.min.js");
            js_metronic.Include("~/Content/metronic/assets/global/plugins/bootstrap-summernote/lang/summernote-zh-CN.min.js");

            bundles.Add(css_metronic);
            bundles.Add(js_metronic);

 

2)、编写HTML内容

于HTML页面代码增加下面的符。

<div id="summernote">Hello Summernote</div>

 

3)、初始化调用

简简单单的初始化代码如下所示。

$(document).ready(function() {
  $('#summernote').summernote();
});

若是增加控件高度的定义,则如下所示。

$('#summernote').summernote({
  height: 300,   
  focus: true    
});

比方详细的初始化界面,一般还连语言国际化、图片上传等拍卖代码,如下所示

function initEditor() {
    $('#Note').summernote({
        lang: 'zh-CN',       // default: 'en-US'
        height: 600,         // set editor height                
        minHeight: null,    // set minimum height of editor
        maxHeight: null,    // set maximum height of editor
        focus: true,         // set focus to editable area after initializing summe
        callbacks: {
            onImageUpload: function (files) { //the onImageUpload API  
                img = sendFile(files[0]);
            }
        }
    });
}

4)、获取内容

var markupStr = $('#summernote').summernote('code');

 

5)、设置情节

装情节跟博内容接近,在code后面增加内需写入的HTML内容即可。

var markupStr = 'hello world';
$('#summernote').summernote('code', markupStr);

 

参考:

2、 summernote插件在骨子里项目面临的行使

面介绍了例行 summernote插件的使过程,一般情况下,我们使用它们除了编辑HTML内容他,还需对图纸上传进行处理,以管教我们好直接把文件及流传后台文件系统里面去,而不是把它转换为Base64的编码在页面内。

一般的初始化代码如下所示。

        function initEditor() {
            $('#Note').summernote({
                lang: 'zh-CN',       // default: 'en-US'
                height: 600,         // set editor height                
                minHeight: null,    // set minimum height of editor
                maxHeight: null,    // set maximum height of editor
                focus: true,         // set focus to editable area after initializing summe
                callbacks: {
                    onImageUpload: function (files) { //the onImageUpload API  
                        img = sendFile(files[0]);
                    }
                }
            });
        }

里面的sendFile的函数如下所示,主要是调整用附件管理模块进行文件的积存。

        //提交文件到服务器处理
        function sendFile(file) {
            data = new FormData();
            data.append("file", file);
            //增加额外的参数
            data.append("folder", '商品信息');
            data.append("guid", $("#ID").val());

            $.ajax({
                data: data,
                type: "POST",
                url: "/FileUpload/Upload",
                cache: false,
                contentType: false,
                processData: false,
                success: function (json) {
                    var data = $.parseJSON(json);
                    var url = data.urls[0];
                    $("#Note").summernote('insertImage', url, 'image name'); // the insertImage API  
                }
            });
        }

相似的话,我们的文书为以差不多只下中共享处理,一般建议为FTP方式开展处理,这上面可参考随笔《以附件管理模块中增对FTP
上传和预览的支持》,FTP上污染文书可以使用FluentFTP这个组件(GitHub地址:https://github.com/hgupta9/FluentFTP ),这个是一个用很常见,功能很强大的FTP组件。

上传附件到服务器上的后台控制器代码如下所示,主要是构建文件信息,上传后返回对应的URL,然后就是可以于 summernote插件上显示图片了。

        /// <summary>
        /// 上传附件到服务器上
        /// </summary>
        /// <param name="fileData">附件信息</param>
        /// <param name="guid">附件组GUID</param>
        /// <param name="folder">指定的上传目录</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Upload(string guid, string folder)
        {
            //如果需要修改字段显示,则参考下面代码处理
            dynamic obj = new ExpandoObject();
            List<string> urls = new List<string>();
            var result = new CommonResult();

            HttpFileCollectionBase files = HttpContext.Request.Files;
            if (files != null)
            {
                foreach (string key in files.Keys)
                {
                    try
                    {
                        #region MyRegion
                        HttpPostedFileBase fileData = files[key];
                        if (fileData != null)
                        {
                            HttpContext.Request.ContentEncoding = Encoding.GetEncoding("UTF-8");
                            HttpContext.Response.ContentEncoding = Encoding.GetEncoding("UTF-8");
                            HttpContext.Response.Charset = "UTF-8";

                            string fileName = Path.GetFileName(fileData.FileName);      //原始文件名称
                            string fileExtension = Path.GetExtension(fileName);         //文件扩展名

                            FileUploadInfo info = new FileUploadInfo();
                            info.FileData = ReadFileBytes(fileData);
                            if (info.FileData != null)
                            {
                                info.FileSize = info.FileData.Length;
                            }
                            info.Category = folder;
                            info.FileName = fileName;
                            info.FileExtend = fileExtension;
                            info.AttachmentGUID = guid;

                            info.AddTime = DateTime.Now;
                            info.Editor = CurrentUser.Name;//登录人
                            //info.Owner_ID = OwerId;//所属主表记录ID

                            result = BLLFactory<FileUpload>.Instance.Upload(info);
                            if (!result.Success)
                            {
                                LogTextHelper.Error("上传文件失败:" + result.ErrorMessage);
                            }
                            else
                            {
                                //返回具体路径地址
                                string serverRealPath = info.BasePath.UriCombine(info.SavePath);
                                if (!Path.IsPathRooted(info.BasePath) &&
                                    !info.BasePath.StartsWith("http://") &&
                                    !info.BasePath.StartsWith("https://"))
                                {
                                    //如果是相对目录,加上当前程序的目录才能定位文件地址
                                    var url = HttpContext.Request.Url;
                                    var baseurl = url.AbsoluteUri.Replace(url.PathAndQuery, "");
                                    serverRealPath = baseurl.UriCombine(serverRealPath).Replace('\\', '/');
                                }
                                urls.Add(serverRealPath);
                            }
                        }
                        #endregion
                    }
                    catch (Exception ex)
                    {
                        result.ErrorMessage = ex.Message;
                        LogTextHelper.Error(ex);
                    }
                }
                obj.urls = urls;
            }
            else
            {
                result.ErrorMessage = "fileData对象为空";
            }

            var newResult = new { Success = result.Success, ErrorMessage = result.ErrorMessage, urls = urls };
            return ToJsonContent(newResult);
        }

界面效果使己以随笔介绍的同样《微信小序成后台数据管理落实货物数量的动态展示、维护》。

案例对货物的详细信息的富文本进行编制,来展开图纸文字的编处理,如下界面所示。

葡京国际平台 11

当我们插入图片的下,弹出一个会话框界面,选择文件及传后返回URL显示在SummerNote插件上。

 葡京国际平台 12

上传文件成功后,通过下的代码插入一个图纸,如下代码。

    $.ajax({
        data: data,
        type: "POST",
        url: "/FileUpload/Upload",
        cache: false,
        contentType: false,
        processData: false,
        success: function (json) {
            var data = $.parseJSON(json);
            var url = data.urls[0];
            $("#Note").summernote('insertImage', url, 'image name'); // the insertImage API  
        }
    });

 以上就是自我当其实的Bootstrap框架项目受到以
summernote插件实现HTML文档的编写和图插入操作,整体性还是于轻上手的,经验供大家借鉴。

 其他有关随笔可以参考阅读下:

《组成bootstrap
fileinput插件和Bootstrap-table表格插件,实现公文上传、预览、提交的导入Excel数据操作流程》

《冲Metronic的Bootstrap开发框架经验总结(16)–
使用插件bootstrap-table实现表格记录之查询、分页、排序等拍卖》

依据Metronic的Bootstrap开发框架经验总结(15)– 更新使用Metronic
4.75版本

打开发框架提高支付效率说由 

据悉Metronic的Bootstrap开发框架经验总结(14)–条码和二维码的别和打印处理

基于Metronic的Bootstrap开发框架经验总结(13)–页面链接收藏夹功能的落实2

冲Metronic的Bootstrap开发框架经验总结(12)–页面链接收藏夹功能的贯彻

依据Metronic的Bootstrap开发框架经验总结(11)–页面菜单的几乎栽表现方式 

因Metronic的Bootstrap开发框架经验总结(10)–优化Bootstrap图标管理 

在MVC控制器里面用dynamic和ExpandoObject,实现数量转义的出口

基于Metronic的Bootstrap开发框架经验总结(9)–实现Web页面内容之打印预览和封存操作

据悉Metronic的Bootstrap开发框架经验总结(8)–框架功能完全界面介绍

依据Metronic的Bootstrap开发框架经验总结(7)–数据的导入、导出及附件的查处理 

据悉Metronic的Bootstrap开发框架经验总结(6)–对话框及提示框的处理以及优化

基于Metronic的Bootstrap开发框架经验总结(5)–Bootstrap文件及传插件File
Input的使

据悉Metronic的Bootstrap开发框架经验总结(4)–Bootstrap图标的取和运

依据Metronic的Bootstrap开发框架经验总结(3)–下拉列表Select2插件的应用 

冲Metronic的Bootstrap开发框架经验总结(2)–列表分页处理以及插件JSTree的采用

根据Metronic的Bootstrap开发框架经验总结(1)-框架总览及菜单模块的处理 

  • QDAC: Delphi 10.2 非官方补丁合集 http://blog.qdac.cc/?p=4485