跳转至

UI Tools


UI Tools程序版说明、本地安装和配置

UI Tools程序版是依赖网页版,支持用户在浏览器中使用网页版的功能并实现浏览器和本地文件系统双向同步的程序。程序版定期发布压缩包,包含程序、程序配置文件和项目依赖文件夹。


压缩文件说明

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
node.zip
│
└───www                       # 项目依赖的样式和脚本文件
│   │
│   └───css
│   └───fonts
│   └───html
│   └───js
│
└───noide.bin.zip             # 程序文件和配置文件
    │   noide.config.json     # 配置文件,配置说明参见noide.config.md
    │   noide.config.md       # 配置说明文件
    │   noide.exe             # 程序文件
    │   RunHide.vbs           # 支持程序后台运行的脚本文件,可忽略
    │   shutdown.bat          # 关闭脚本
    │   startup.bat           # 启动脚本

本地安装和配置

双击noide.exe启动程序,程序前台运行,程序启动时右侧文件树列表是当前程序所在路径的文件树。程序支持多实例,启动时绑定不同的端口。双击startup.bat启动程序,程序后台运行。双击shutup.bat关闭所有运行的程序实例。如果需要同时启动多个实例,同时支持单独关闭,请双击noide.exe启动程序,并通过右上角关闭想要关闭的程序。

Noide Screenshot

功能介绍

页面分为左右两部分,左侧为文件树列表,右侧是工作区域。工作区域可以分别以编辑器模式和UI Tools模式显示。

Noide Context Menu

快捷菜单支持新增、删除和重命名文件和文件夹操作,并根据文件类型显示不同的菜单。

后缀名为html的页面右键点击时,支持以Builder模式打开,打开后右侧工作区展示与网页版相同的内容。用户可以在右侧工作区域进行与网页版相同的操作,所有的修改变化会同步到本地的文件。左键单击文件时,文件以编辑器模式打开,可以查看文件变化,同时可以进行编辑操作,所有的编辑操作会同步到本地的文件中。

Add blank customAdd blank general两个快捷菜单分别创建空白的定制和通用模板文件,用户可以通过Builder模式打开对应的文件,进行编辑操作。

压缩包www/js/shared.js文件中包含压缩包打包时最新的公共脚本文件。程序公共脚本因为需要支持新功能和修复问题,可能需要不定期更新。为了确保shared.js保证最新,右击后缀名为js的文件,显示Update shared JavaScript菜单。单击后,程序会使用最新的公共脚本覆盖原有文件。

警告

更新脚本文件时,请确保更新的是公共脚本文件。请不要将定制的逻辑代码写入公共的脚本文件,更新操作会覆盖原有的文件。

Builder模式

工作区域以Builder模式打开后,界面和操作方式与网页版类似,将在Components组件介绍中详细介绍具体使用方式。

编辑器模式

编辑器模式快捷键支持
PC (Windows/Linux) Mac action
Ctrl+S Cmd+S Save the current file
Ctrl+Shift+S, Cmd+Option+S, Save all files
Ctrl+B Cmd+B Beautify (js, css, html files only)
Ctrl Cmd Show the settings menu
Ctrl+Alt+Up Ctrl+Option+Up add multi+cursor above
Ctrl+Alt+Down Ctrl+Option+Down add multi+cursor below
Ctrl+Alt+Right Ctrl+Option+Right add next occurrence to multi+selection
Ctrl+Alt+Left Ctrl+Option+Left add previous occurrence to multi+selection
Ctrl+L center selection
Ctrl+Shift+U Ctrl+Shift+U change to lower case
Ctrl+U Ctrl+U change to upper case
Alt+Shift+Down Cmd+Option+Down copy lines down
Alt+Shift+Up Cmd+Option+Up copy lines up
Del delete
Ctrl+Shift+D Cmd+Shift duplicate selection
Ctrl+F Cmd find
Ctrl+K Cmd+G find next
Ctrl+Shift+K Cmd+Shift+G find previous
Alt+0 Cmd+Option+0 fold all
Alt+L, Ctrl+F1 Cmd+Option+L, Cmd+F1 fold selection
Down Down, Ctrl+N go line down
Up Up, Ctrl+P go line up
Ctrl+End Cmd+End, Cmd+Down go to end
Left Left, Ctrl+B go to left
Ctrl+L Cmd+L go to line
Alt+Right, End Cmd+Right, End, Ctrl+E go to line end
Alt+Left, Home Cmd+Left, Home, Ctrl+A go to line start
Ctrl+P go to matching bracket
Page Down Option+Page Down, Ctrl+V go to page down
Page Up Option+Page Up go to page up
Right Right, Ctrl+F go to right
Ctrl+Home Cmd+Home, Cmd+Up go to start
Ctrl+Left Option+Left go to word left
Ctrl+Right Option+Right go to word right
Tab Tab indent
Ctrl+Alt+E macros recording
Ctrl+Shift+E Cmd+Shift+E macros replay
Alt+Down Option+Down move lines down
Alt+Up Option+Up move lines up
Ctrl+Alt+Shift+Up Ctrl+Option+Shift+Up move multicursor from current line to the line above
Ctrl+Alt+Shift+Down Ctrl+Option+Shift+Down move multicursor from current line to the line below
Shift+Tab Shift+Tab outdent
Ins Ins overwrite
Ctrl+Shift+Z, Ctrl+Y Cmd+Shift+Z, Cmd+Y redo
Ctrl+Alt+Shift+Right Ctrl+Option+Shift+Right remove current occurrence from multi+selection and move to next
Ctrl+Alt+Shift+Left Ctrl+Option+Shift+Left remove current occurrence from multi+selection and move to previous
Ctrl+D Cmd+D remove line
Alt+Del Ctrl+K remove to line end
Alt+Backspace Cmd+Backspace remove to linestart
Ctrl+Backspace Option+Backspace, Ctrl+Option+Backspace remove word left
Ctrl+Del Option+Del remove word right
Ctrl+R Cmd+Option+F replace
Ctrl+Shift+R Cmd+Shift+Option+F replace all
Ctrl+Down Cmd+Down scroll line down
Ctrl+Up scroll line up
Option+Page Down scroll page down
Option+Page Up scroll page up
Ctrl+A Cmd+A select all
Ctrl+Shift+L Ctrl+Shift+L select all from multi+selection
Shift+Down Shift+Down select down
Shift+Left Shift+Left select left
Shift+End Shift+End select line end
Shift+Home Shift+Home select line start
Shift+Page Down Shift+Page Down select page down
Shift+Page Up Shift+Page Up select page up
Shift+Right Shift+Right select right
Ctrl+Shift+End Cmd+Shift+Down select to end
Alt+Shift+Right Cmd+Shift+Right select to line end
Alt+Shift+Left Cmd+Shift+Left select to line start
Ctrl+Shift+P select to matching bracket
Ctrl+Shift+Home Cmd+Shift+Up select to start
Shift+Up Shift+Up select up
Ctrl+Shift+Left Option+Shift+Left select word left
Ctrl+Shift+Right Option+Shift+Right select word right
Ctrl+O split line
Ctrl+/ Cmd+/ toggle comment
Ctrl+T Ctrl+T transpose letters
Ctrl+Z Cmd+Z undo
Alt+Shift+L, Ctrl+Shift+F1 Cmd+Option+Shift+L, Cmd+Shift+F1 unfold
Alt+Shift+0 Cmd+Option+Shift+0 unfold all
Ctrl+Enter Cmd+Enter enter full screen

UI Tools网页版说明和使用


UI Tools网页版说明

UI Tools网页版是程序版依赖的服务,界面和功能和程序版使用Builder模式打开工作空间类似。

由于浏览器不支持直接的文件访问,UI Tools需要用户显式地进行文件的导入和导出操作。UI Tools网页版在组件列表上方会显式页面文件树。页面文件树中,显示的页面包含通用和定制的模板文件、用户基于模板文件创建的新页面和导入的页面。用户创建的页面通过localStorage保存到浏览器本地,支持在文件树列表删除已创建的页面。

UI Tools网页版快捷菜单

菜单 功能说明 快捷键
Undo 撤销上一步操作 Ctrl+Z
Redo 重做上一步操作 Ctrl+Y
Fullscreen 全屏显示,进入全屏模式后,按F1推出全屏
Preview 隐藏右侧功能区,全屏预览效果,此时左侧工作空间处于不可操作状态
Check generated file 模态框预览导出文件内容
Upload 上传页面到UI Tools中打开
Download 下载当前工作空间的页面到本地
Mobile View 预览当前页面在手机视图中的效果
Tablet View 预览当前页面在平板视图中的效果
Desktop View 预览当前页面在桌面视图中的效果

UI Tools网页版模板

定制模板

定制模板

定制模板是具有固定页面布局的预置模板。左侧是表单,右侧是表格或图表。

通用模板

Gridster

通用模板以布局块为基本单位,允许用户新增、删除布局块、调整布局块的大小、拖拽改变布局块在页面的位置并拖拽组件到布局块中定位。

UI Tools网页版设置

设置

定制设置

定制设置是对应不同组件的设置。

通用设置

通用设置是所有元素通用属性的设置。按其功能分成了GeneralBorderPaddingDisplayTypographySizeMargin等设置。方便用户对元素idclassstyle属性进行可视化的修改。

UI Tools网页版导出文件说明

UI Tools网页版支持导出不同类型的文件

Noide Screenshot

导出文件 文件说明
bundled.html 包含公共脚本文件的html
index.html 移除公共脚本文件的html,只包含必要的表格初始化文件,如需后期引入,可加入shared.js
shared.js 公共脚本文件
index.zip 包含index.html和shared.js的压缩文件

Components

组件是布局的最小单位。用户可以拖拽组件到对应的区域、调整它们的属性并预览效果。


定制组件

定制组件是为pds模板设计的一套具有固定宽度和高度的输入组件。

定制组件 组件说明
Custom Text Input Field 定制文本输入
Custom Datetime Input Field 定制日期时间输入
Custom File Input field 定制文件输入
Custom Auto Select Field 定制自动填充下拉框选项输入
Custom Manual Select Field 定制手动输入下拉框选项输入
Custom Multi-value Select Field 定制多选下拉
Custom Textarea Field 定制文本域输入
Custom Radio Field 定制radio输入
Custom Checkbox Field 定制checkbox输入
Custom Popup Text Input 定制弹出框文本输入
Custom Popup Manual Select 定制弹出框手动输入下拉框选项输入

Custom Text Input Field

Custom Datetime Input Field

Custom File Input Field

定制文件输入。

提示

文件输入在用户选择上传文件后,自动执行文件上传,成功后弹窗提示。查看如何覆盖通用代码一节了解如何实现自定义文件上传逻辑。

Custom Auto Select Field

定制自动填充下拉框选项输入,可以通过指定url地址,设置value和text映射,在页面加载后自动填充下拉框选项。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function generateOptions(el, response) {
    var value = $(el).attr('data-value-mapping') || 'value';
    var text = $(el).attr('data-text-mapping') || 'text';
    response.forEach(function (option) {
        $('<option></option>')
            .val(option[value])
            .text(option[text])
            .appendTo($(el));
    });
}

[].slice.call($('body').find('[data-auto-select-id]'))
    .filter(function (el) {
        return $(el).attr('data-url');
    }).forEach(function (el) {
        $.ajax({
            url: config.fundodooApiDomainUrl + $(el).attr('data-url'),
            dataType: 'json',
            method: 'POST',
            async: true,
            success: function (response) {
                generateOptions(el, response.data);
            }
        });
    });

Custom Manual Select Field

定制手动输入下拉框选项输入,允许用户在设置菜单手动添加或删除下拉框选项。

Custom Multi-value Select Field

Custom Textarea Field

Custom Radio Field

定制radio输入。

提示

通过选中radio元素后弹出的快捷菜单,点击复制按钮实现快速复制radio元素。

Custom Checkbox Field

定制checkbox输入。

提示

通过选中checkbox元素后弹出的快捷菜单,点击复制按钮实现快速复制checkbox元素。

Custom Popup Text Input

定制弹出框文本输入适用于定制模板弹出框。

Custom Popup Manual Select

定制弹出框手动输入下拉框选项输入适用于定制模板弹出框。

提示

设置输入组件title属性,当鼠标在输入组件悬浮时,在组件右侧显示title的内容。

通用组件

定制组件 组件说明
Container container
Form 表单
Grid Row 栅格
Tabs 标签页
Common ag-Grid 集成表格组件ag-Grid
Button 按钮
Rounded Button 圆形按钮
Button Group 按钮组
Text Input Field 文本输入
Datetime Input Field 日期时间输入
File Input Field 文件输入
Auto Select Field 自动填充下拉框选项输入
Manual Select Field 手动输入下拉框选项输入
Textarea Field 文本域输入
Radio Field radio输入
Checkbox Field checkbox输入
Static Table 静态表格
Chart 图表占位符
Heading Heading元素
Alert 告警框
Horizontal Rule 水平分割线
Image 图片组件
Progress Bar 进度条

Container

Container是基于Bootstrap中的Container实现的组件。该组件主要是为了HTML的语义化,帮助用户将其他组件统一放在Container组件中,提供了几种不同的主题背景颜色。

Form

Form是基于Bootstrap中的Form实现的表单组件。表单组件中可以放入不同的输入控件并设置它们的样式。参考定制组件中类型相同的输入控件的属性设置。

示例Form表单HTML代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<form>
  <div class="form-group">
    <label for="exampleFormControlInput1">Email address</label>
    <input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
  </div>
  <div class="form-group">
    <label for="exampleFormControlSelect1">Example select</label>
    <select class="form-control" id="exampleFormControlSelect1">
      <option>1</option>
      <option>2</option>
      <option>3</option>
      <option>4</option>
      <option>5</option>
    </select>
  </div>
  <div class="form-group">
    <label for="exampleFormControlSelect2">Example multiple select</label>
    <select multiple class="form-control" id="exampleFormControlSelect2">
      <option>1</option>
      <option>2</option>
      <option>3</option>
      <option>4</option>
      <option>5</option>
    </select>
  </div>
  <div class="form-group">
    <label for="exampleFormControlTextarea1">Example textarea</label>
    <textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
  </div>
</form>

警告

UI Tools没有限制输入组件一定要拖入form元素内。实际上,用户可以选择将输入组件放入页面内的任何可拖拽区域,并能正确呈现样式。但为了HTML的语义化,将输入组件放入form元素内是更合理的做法。

Text Input Field
Datetime Input Field
File Input Field
Auto Select Field
Manual Select Field
Textarea Field
Radio Field
Checkbox Field

设置输入组件的Required属性有什么作用?

设置输入组件的Required属性,当表单提交时,如果表单中存在设置了Required的输入组件且该组件值为空,将弹窗提示用户输入不能为空。

Grid Row

Grid Row

栅格是基于Bootstrap中的Grid实现的可视化、可配置的布局组件。支持栅格的新增和删除操作,支持改变栅格中列在不同分辨率下的大小。支持拖拽其他组件到栅格中的对应位置。

Tabs

Tabs

Tabs组件基于jQuery UI Tabs实现。允许用户新增、删除标签页和修改标签页的标题,支持拖拽其他组件到标签页中,支持标签页的嵌套。

Common ag-Grid

ag-Grid

表格组件基于ag-Grid实现。用户可以通过元素快捷菜单,新增、删除、修改表头,属性设置菜单修改表格颜色主题。支持ag-Grid常用属性设置。

常用属性设置说明1

属性 说明 示例
Header 表头名称、字段映射、宽度、是否隐藏、禁用改变大小、删除表头
Checkbox Selection 第一列数据是否显示checkbox
Header Checkbox Selection 第一列表头是否显示checkbox,可以快速进行全选
Enable Resize 是否启用使用鼠标改变表头宽度
Auto Size Columns 表格是否根据数据列自适应改变宽度
Populate Headers 是否根据返回数据自动填充表头,启用后现有的Header设置失效
Pagination 是否分页显示数据
Page Size 分页后每页显示的数据数目
Theme 集成全部官方颜色主题 ag-Grid-themes
Related Table 关联的其他表格,用于表格联动逻辑
Transpose Key 表格行列翻转的基准
Table Key 表格唯一标识,只读
Enable Row Click 是否响应行点击事件,默认行为是弹框,可覆盖默认行为。查看如何覆盖默认行为
Row Click Url 行点击弹框中有新的表格时,数据请求的地址
Enable Cell Click 是否响应单元格点击事件,默认行为是弹框,可覆盖默认行为。查看如何覆盖默认行为
Cell Click Url 单元格点击弹框中有新的表格时,数据请求的地址
Data Key 查询返回多个表格数据时,数据和表格的映射关系

Button

Button

Button是基于Bootstrap中的Button实现的按钮组件。支持常用样式属性的设置。支持点击弹出框操作,用户可以拖拽其他组件到弹出框。

Rounded Button

Rounded Button

Rounded Button是基于Bootstrap中的Button实现的圆形按钮组件。图标基于Font Awesome。用户如果需要设置其他图标,可以点击Rounded Button中的i元素,在属性设置中的Text -> Icon下拉框中选择常用的图标。如果需要设置其他图标,可以在General -> Class中修改为Font Awesome支持的图标。

Button Group

Button Group是基于Bootstrap中的Button Group实现的按钮组件。支持常用样式属性的设置。

Static Table

Static Table

静态表格是基于Bootstrap中的Table实现的静态表格。设置菜单里可以设置表格的多种不同样式。用户可以利用元素复制和删除功能,新增或删除表头和数据列。表格的表头和数据是静态数据。

Chart

Chart组件是图表占位组件。由于图表图例和数据一般是后台数据经代码渲染生成,UI Tools暂时不提供统一可视化设置功能。

Heading

Heading组件支持heading元素。

Alert

静态表格是基于Bootstrap中的Alert实现的告警组件。支持改变告警样式。

Horizontal Rule

Horizontal Rule组件支持hr元素。

Image

Image

信息

图片组件是img元素的占位组件。用户可以利用设置中的上传功能预览图片效果,图片以base64编码在页面中呈现。图片不会保存到导出页面或上传到服务器。

Progress Bar

Progress Bar是基于Bootstrap中的Progress实现的进度条组件。支持改变进度条样式。

Label Field

JavaScript代码生成


UI Tools生成页面时,支持生成通用的和适用于单独页面的脚本。

通用代码

UI Tools为简化用户的开发流程,会为一些通用的业务逻辑自动生成代码。如果用户使用网页版导出功能时,选择bundled.html导出,通用代码会包含在导出文件中。由于通用代码内容相同,为便于统一更新,不建议以bundled.html导出。网页版中,用户可以选择shared.js导出最新的通用代码。程序版www/js/shared.js已包含shared.js文件,用户可以右键更新到最新的通用代码。

通用代码功能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function onFileInputChange() {
    var formData = new FormData();
    formData.append(this.name, this.files[0]);
    $.ajax({
        url: config.fundodooApiDomainUrl + $(this).attr('data-url'),
        dataType: 'json',
        contentType: false,
        method : 'POST',
        async: true,
        processData: false,
        traditional: true,
        data: formData,
        fundodooAjax: true, //true:开启计时功能,false(或去掉此属性):不开启计时功能
        success: function (response, status, xhr) {
            layer.alert('文件上传成功', {
                icon: 1,
                shadeClose: true,
                title: '提示'
            });
        }
    });
}

$('form.form-box').find('input[type=file][data-url]').on('change', onFileInputChange);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function generateOptions(el, response) {
    var value = $(el).attr('data-value-mapping') || 'value';
    var text = $(el).attr('data-text-mapping') || 'text';
    response.forEach(function (option) {
        $('<option></option>')
            .val(option[value])
            .text(option[text])
            .appendTo($(el));
    });
}
[].slice.call($('body').find('[data-auto-select-id]'))
    .filter(function (el) {
        return $(el).attr('data-url');
    }).forEach(function (el) {
        var data = {
            owner: 'Common',
            queryId: 'findIdType',
            version: '10001',
            paramSource: null
        };
        $.ajax({
            url: config.fundodooApiDomainUrl + $(el).attr('data-url'),
            dataType: 'json',
            method: 'POST',
            data: data,
            async: true,
            success: function (response) {
                generateOptions(el, response.data);
            }
        });
    });
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function submitForm(form, url, successCb, errorCb) {
    var valid = true;
    form.find('input[required], select[required], textarea[required]')
        .each(function () {
            if (!this.value) {
                valid = false;
                layer.alert(this.name + '输入不能为空', {
                    icon: 2,
                    shadeClose: true,
                    title: '提示'
                });
                return false;
            }
        });
    if (valid) {
        var formData = new FormData();
        var data = form.serializeJSON();
        data.tok = sessionStorage.getItem('FUNDODOO_TOKEN');
        $.each($('input[type=file]'), function (i, element) {
            formData.append(element.name, element.files[0]);
        });
        Object.keys(data).forEach(function (value) {
            formData.append(value, data[value]);
        });
        var containsFileInput = form.find('input[type=file]').length > 0;
        $.ajax({
            url: config.fundodooApiDomainUrl + url,
            dataType: 'json',
            contentType: containsFileInput ? false : 'application/x-www-form-urlencoded',
            method : 'POST',
            async: true,
            processData: !containsFileInput,
            traditional: true,
            data: containsFileInput ? formData : data,
            fundodooAjax: true, //true:开启计时功能,false(或去掉此属性):不开启计时功能
            success: successCb,
            error: errorCb
        });
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// 新增弹出框只适用于定制模板
function popupAdd() {
    layer.open({
        type: 1,
        title: '新增',
        area: ['600px', '350px'],
        skin: 'layui-layer-rim', //加上边框
        content: $('div.popup-window#add'),
        end: function end() {
            $('div.popup-window#add form').trigger('reset');
        }
    });
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 编辑弹出框只适用于定制模板
function popupEdit() {
    var openPopup = function openPopup() {
        layer.open({
            type: 1,
            title: '修改',
            area: ['600px', '350px'],
            skin: 'layui-layer-rim', //加上边框
            content: $('div.popup-window#edit'),
            end: function end() {
                $('div.popup-window#edit form').trigger('reset');
            }
        });
    };
    var setFormValues = function setFormValues(selectedRow) {
        $('div.popup-window#edit form').find('input:not([type=submit]), select, textarea').each(function () {
            var field = $(this).attr('data-row-field') || $(this).attr('name');
            $(this).val(selectedRow[field]);
        });
    };
    if (grids.length) {
        var selectedRows = grids[0].gridOptions.api.getSelectedRows();
        if (selectedRows.length == 0) {
            layer.msg('请选择需要修改的数据', { icon: 5 });
        } else if (selectedRows.length > 1) {
            layer.msg('只允许同时修改一条数据', { icon: 5 });
        } else {
            setFormValues(selectedRows[0]);
            openPopup();
        }
    } else {
        layer.msg('请选择需要修改的数据', { icon: 5 });
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 删除弹出框只适用于定制模板
function popupDelete() {
    var openPopup = function openPopup() {
        layer.confirm('您确定需要删除吗?', {
            btn: ['确定', '取消']
        }, function () {
            $.ajax({
                url: config.fundodooApiDomainUrl + $('button#delete').attr('data-url'),
                dataType: 'json',
                contentType: 'application/x-www-form-urlencoded',
                method: 'POST',
                async: true,
                traditional: true,
                data: grids[0].gridOptions.api.getSelectedRows(),
                fundodooAjax: true, //true:开启计时功能,false(或去掉此属性):不开启计时功能
                success: function success() {
                    layer.closeAll();
                    $('form button#dataSearch').click();
                },
                error: function error() {}
            });
        }, function () {});
    };
    if (grids.length) {
        var selectedRows = grids[0].gridOptions.api.getSelectedRows();
        if (selectedRows.length == 0) {
            layer.msg('请选择需要删除的数据', { icon: 5 });
        } else {
            openPopup();
        }
    } else {
        layer.msg('请选择需要删除的数据', { icon: 5 });
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 详情弹出框目前适用于固定的业务逻辑,实际开发中可能需要根据业务需求做改动
function popupDetail(url, data, popup) {
    // Compatible with previous only one detail popup window
    var content = popup && popup.length ? popup : $('div.popup-window#detail');
    var openPopup = function openPopup() {
        layer.open({
            type: 1,
            title: '信息',
            area: ['660px', '330px'],
            skin: 'layui-layer-rim', //加上边框
            content: content,
            end: function end() {}
        });
    };
    if (content.length) {
        if (url && data) {
            $.ajax({
                url: config.fundodooApiDomainUrl + url,
                dataType: 'json',
                contentType: 'application/x-www-form-urlencoded',
                method: 'POST',
                async: true,
                traditional: true,
                data: data,
                fundodooAjax: true, //true:开启计时功能,false(或去掉此属性):不开启计时功能
                success: function success(response) {
                    content.find('[data-component-id="html/labelfield@common"]').each(function (_, element) {
                        var key = $(element).children('span:last-child').attr('data-key-mapping');
                        $(element).children('span:last-child').text(key ? response.data[key] || '' : '');
                    });
                    content.find('img').each(function (_, image) {
                        var $image = $(image);
                        var data = response.data[$image.attr('data-key-mapping')];
                        if (data) {
                            $image.attr('src', 'data:image/' + $image.attr('data-image-format') + ';base64,' + data);
                        } else {
                            $image.attr('src', $image.attr('data-image-placeholder'));
                        }
                    });
                    openPopup();
                },
                error: function error() {}
            });
        } else {
            openPopup();
        }
    }
}
1
2
3
4
5
function exportData() {
    if (grids.length) {
        grids[0].gridOptions.api.exportDataAsCsv();
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 弹出框中表单提交后,回调函数中关闭弹出框,重新查询数据渲染表格
function popupFormSubmitCallback() {
    submitForm($(this).parents('form'),
        $('button#' + $(this).parents('form').attr('data-related-button')).attr('data-url'),
        function (response) {
            layer.closeAll();
            $('form button#dataSearch').click();
        },
        function () {
        });
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// 函数中根据用户对表格设置的不同属性,实现不同的数据填充
// 支持数据填充表头、支持行列翻转、支持表头宽度根据内容自适应
function setAgGridData(grid, data) {
    var gridOptions = grid.gridOptions;
    var transposeKey = grid.transposeKey;
    var populateHeaders = grid.populateHeaders;
    var autoSizeColumns = grid.autoSizeColumns;
    if (populateHeaders) {
        if (data.length) {
            var colDefs = Object.keys(data[0]).map(function (key) {
                return {
                    headerName: key,
                    field: key
                };
            });
            gridOptions.api.setColumnDefs(colDefs);
            gridOptions.api.setRowData(data);
        }
    } else {
        if (transposeKey) {
            var transposedData = gridOptions.columnDefs
                .filter(function (colDef) {
                    return colDef.field !== transposeKey;
                })
                .map(function (colDef) {
                    var key = colDef.field;
                    var transposed = {};
                    transposed[transposeKey] = colDef.headerName;
                    data.forEach(function (item) {
                        transposed[item[transposeKey]] = item[key];
                    });
                    return transposed;
                });
            var newColDefs = [
                {
                    headerName: '',
                    field: transposeKey,
                    cellStyle: {
                        'font-size': 'large'
                    },
                    pinned: 'left'
                }
            ].concat(data.map(function (item) {
                return {
                    headerName: item[transposeKey],
                    field: $.isNumeric(item[transposeKey])
                        ? item[transposeKey].toString()
                        : item[transposeKey]
                };
            }));
            gridOptions.api.setColumnDefs(newColDefs);
            gridOptions.api.setRowData(transposedData);
        } else {
            gridOptions.api.setRowData(data);
        }
    }
    if (autoSizeColumns) {
        var allColumnIds = [];
        gridOptions.columnApi.getAllColumns().forEach(function(column) {
            allColumnIds.push(column.colId);
        });
        gridOptions.columnApi.autoSizeColumns(allColumnIds);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function query() {
    var queryForm = $(this).parents('form');
    var queryUrl = $(this).attr('data-url');
    submitForm(queryForm, queryUrl,
        function (response) {
            if (Array.isArray(response.data)) {
                if (grids.length) {
                    setAgGridData(grids[0], response.data);
                }
            } else {
                $.each(response.data, function (key, value) {
                    $.each(grids, function (i, grid) {
                        if (grid.key == key) {
                            setAgGridData(grid, value);
                            return false;
                        }
                    });
                });
            }
        },
        function () {
        });
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 注册弹出框表单提交回调函数,只适用于定制模板
$('form.popup-form input[type=submit]').on('click', popupFormSubmitCallback);

// 注册定制模板左侧表单提交回调函数,只适用于定制模板
$('form button#dataSearch').on('click', query);

// 注册文件输入框选择本地文件回调函数,文件自动上传到通过`data-url`指定的路径
$('form.form-box').find('input[type=file][data-url]').on('change', onFileInputChange);

// 注册通用模板表单中按钮元素点击回调函数
$('div.gridster div form button[data-enable-button-click-popup!=true]').on('click', query);

// 注册启用弹出框的按钮元素点击回调函数
function buttonClickedPopupCallback() {
    if ($(this).attr('data-enable-button-click-popup') === 'true') {
        popupDetail(null, null, $('#' + 'button_clicked_popup' + $(this).attr('data-button-key')));
    }
}
$('body').on('click', 'button', buttonClickedPopupCallback);
1
2
3
4
5
6
7
// 输入组件悬浮提示框初始化
$(function () {
    $('input, select, textarea').tooltip({"position":{"my":"left top","at":"right+5 top-5","collision":"none"}});
});

// Tabs组件初始化
$('[data-component-id="html/tabs@common"]').tabs();

如何覆盖通用代码

通用代码一般只适用于一些通用、简单的逻辑。如果要实现自定义逻辑,用户可以覆盖原有的实现。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 移除原有绑定的事件回调
$('form.popup-form input[type=submit]').off('click', popupFormSubmitCallback);
// 注册自定义事件回调
$('form.popup-form input[type=submit]').on('click', function () {});

// 移除原有绑定的事件回调
$('form.form-box').find('input[type=file][data-url]').off('change', onFileInputChange);
// 注册自定义事件回调
$('form.form-box').find('input[type=file][data-url]').on('change', function () {});

// 移除原有绑定的事件回调
$('form button#dataSearch').off('click', query);
// 注册自定义事件回调
$('form button#dataSearch').on('click', function () {});

// 移除原有绑定的事件回调
$('div.gridster div form button[data-enable-button-click-popup!=true]').off('click', query);
// 注册自定义事件回调
$('div.gridster div form button[data-enable-button-click-popup!=true]').on('click', function () {});

// 移除原有绑定的事件回调
$('body').off('click', 'button', buttonClickedPopupCallback);
// 注册自定义事件回调
$('body').on('click', 'button', function () {});

提示

通用代码中大部分代码需要通过用户操作触发,这部分代码可以实现覆盖原有实现。但下拉框数据初始化会在页面加载完成后执行,这部分代码如果用户需要重写,请不要引入shared.js文件。

定制代码

ag-Grid Code

UI Tools功能中,只有使用ag-Grid组件初始化的表格是必须包含在生成的页面里的。

备注

如果使用了ag-Grid组件,请不要修改导出的表格初始化代码。UI Tools在实现页面导入功能时,需要依赖这部分代码实现表格的初始化工作。同时,UI Tools为表格增加新功能时,需要覆盖这部分代码。与此同时,UI Tools没有限制用户覆盖原有代码逻辑的能力。下面会通过例子说明如何重写表格代码,实现自定义逻辑。

1
2
3
4
5
6
7
<div data-component-id="html/commontable@common"
    data-enable-row-click="true"
    style="width: 100%; height: 100%; z-index: 15; left: 0px; top: 0px;"
    class="resize-drag draggable ag-theme-blue ui-sortable-handle"
    data-table-id="_fl"
    id="table_fl">
</div>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var gridOptions_fl = {
            columnDefs: [{
                "headerName": "Athelete",
                "field": "athelete",
                "width": "",
                "checkboxSelection": true,
                "headerCheckboxSelection": false,
                "suppressMovable": true
            }],
            enableSorting: true,
            enableFilter: false,
            rowSelection: 'multiple',
            suppressRowClickSelection: true,
            suppressFieldDotNotation: true,
            pagination: undefined,
            paginationAutoPageSize: undefined,
            paginationPageSize: undefined,
            onCellClicked: function (event) {
                if (eGridDiv_fl.attr('data-enable-cell-click') == 'true') {
                    if (typeof popupCommon !== 'undefined' && typeof popupCommon == 'function') {
                        var popup = $('#' + 'cell_clicked_popup' + '_fl');
                        popupCommon(event, popup, eGridDiv_fl);
                    }
                }
            },
            onRowClicked: function (event) {
                if (eGridDiv_fl.attr('data-enable-row-click') == 'true') {
                    popupDetail(eGridDiv_fl.attr('data-row-click-url'), event.data, $('#' + 'row_clicked_popup' + '_fl'));
                }
            },
            onRowSelected: function (event) {
                if (event.node.isSelected() && eGridDiv_fl.attr('data-related-table')) {
                    if (window['gridOptions' + eGridDiv_fl.attr('data-related-table')]) {
                        window['gridOptions' + eGridDiv_fl.attr('data-related-table')].api.setRowData([event.data]);
                    }
                }
            }
        };
        new agGrid.Grid(eGridDiv_fl.get(0), gridOptions_fl);
        gridOptions_fl.api.setRowData([]);

上面的HTML片段和JavaScript代码用于初始化页面中的一个ag-Grid表格组件。默认的行点击和单元格点击事件是弹出对话框(需要在表格属性设置中开启弹出框)。

1
2
3
4
5
6
7
gridOptions_fl.onCellClicked = function () {
// 自定义逻辑
};

gridOptions_fl.onRowSelected = function () {
// 自定义逻辑
}

用户可以重新设置onCellClicked和onRowSelected属性,实现用户自定义逻辑。

参考ag-Grid文档了解更多使用方式。

样式主题制作器

样式主题制作器是一款通过可视化界面制作Bootstrap主题的网页应用,允许用户在线制作、导出和上传样式主题。该应用与UI Tools集成,允许用户在UI Tools中使用已上传到服务器的主题。


界面说明

基本操作

UI Tools集成


  1. 更多属性设置ag-Grid文档。