← 返回
未分类

HISUI 前端框架开发指南(信创版 / Java 后端)

HISUI 前端框架开发指南(信创版 / Java 后端)。 HISUI 是基于 easyui 的二次开发版本,用于医疗信息系统开发。 本版本适用于 Java 后端(Spring Boot)接口,请求方式使用 $iget/$ipost。 当用户提到 HISUI、前端组件、jQuery UI、表格、表单、布局、Java 接口等关键词时使用此 skill。 支持组件查询、代码示例、API 参考和最佳实践指导。 特别注意:本 skill 基于实际项目代码习惯(DHCMA/EPD),使用 $HUI 语法和 $(function(){}) 入口模式。 后台请求使用 $iget(GET)/$ipost(POST)。
HISUI 前端框架开发指南(信创版 / Java 后端)。 HISUI 是基于 easyui 的二次开发版本,用于医疗信息系统开发。 本版本适用于 Java 后端(Spring Boot)接口,请求方式使用 $iget/$ipost。 当用户提到 HISUI、前端组件、jQuery UI、表格、表单、布局、Java 接口等关键词时使用此 skill。 支持组件查询、代码示例、API 参考和最佳实践指导。 特别注意:本 skill 基于实际项目代码习惯(DHCMA/EPD),使用 $HUI 语法和 $(function(){}) 入口模式。 后台请求使用 $iget(GET)/$ipost(POST)。
maypu
未分类 community v1.0.0 1 版本 100000 Key: 无需
★ 0
Stars
📥 3
下载
💾 0
安装
1
版本
#latest

概述

HISUI 前端框架开发指南(信创版 / Java 后端)

> 适用于 Java(Spring Boot)后端接口,请求方式为 $iget / $ipost


目录结构规范

项目静态资源位于 static/phm/ 下,每个功能模块对应 html/scripts/ 两个目录,每页两个文件(HTML + JS):

static/phm/
├── base/                          # 基础配置模块
│   ├── html/                     # HTML 页面文件
│   │   ├── dict.html            # 字典配置页面
│   │   ├── route.html           # 路由配置页面
│   │   └── auth.assign.html
│   └── scripts/                # 对应 JS 逻辑文件
│       ├── dict.js
│       ├── route.js
│       └── auth.assign.js
├── common/                      # 公共库(所有模块共用)
│   ├── scripts/
│   │   ├── com.hisui.phm.js    # HISUI 公共方法(必须引入)
│   │   ├── com.sys.js          # 系统公共方法(必须引入)
│   │   ├── com.fun.js          # 通用工具方法(必须引入)
│   │   ├── component.js        # 组件初始化
│   │   ├── phm.auth.js         # 权限控制(按钮显示/隐藏)
│   ├── scripts_lib/            # 第三方库(如 SheetJS)│
│   └── css/
│       └── base.css            # 公共样式

命名规则:

  • HTML 和 JS 文件同名(如 dict.htmldict.js
  • HTML 中通过相对路径引用 JS:
  • 公共库通过 ../../common/scripts/xxx.js 引用

一、HTML 编写规范

1.1 标准页面结构

<!-- FileName: static/phm/模块名/html/xxx.html -->
<!-- Author: 作者名 -->
<!-- Date: 创建日期 -->
<!-- Description: 页面描述 -->
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>页面标题</title>

<!-- 【必须】引入公共 hisui(顺序不可变) -->
<script type="text/javascript" src="../../common/scripts/com.hisui.phm.js"></script>
<script type="text/javascript" src="../../common/scripts/com.sys.js"></script>
<script type="text/javascript" src="../../common/scripts/com.fun.js"></script>

<!-- 引用公共 css、js -->
<link href="../../common/css/base.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../common/scripts/component.js"></script>

<!-- 引用业务 js(与 HTML 同名,放在 head 前) -->
<script src="../scripts/xxx.js" type="text/javascript"></script>

<!-- 控制组件显示隐藏(权限:根据后台配置自动禁用/启用按钮) -->
<script src="../../common/scripts/phm.auth.js" type="text/javascript"></script>

<!-- 如需 SheetJS 等第三方库,按需引入 -->
<!-- <script type="text/javascript" src="../../common/scripts_lib/SheetJS/xlsx.full.min.js"></script> -->

<head></head>
<body>
<!-- 主页面 - 使用 hisui-layout 五方布局 -->
<div class="hisui-layout" data-options="fit:true">
    <div data-options="region:'north',border:false" style="height:50px;padding:10px;">
        <!-- 顶部:查询条件 -->
        <table class="search-table">
            <tr>
                <td class="r-label"><label for="txtName" class="hisui-label">名称</label></td>
                <td><input class="hisui-textbox" id="txtName" style="width:150px"></td>
                <td class="search-btnlist">
                    <a id="btnQuery" class="hisui-linkbutton" data-options="iconCls:'icon-w-find'">查询</a>
                </td>
            </tr>
        </table>
    </div>
    
    <div data-options="region:'center',border:false" style="padding:10px;">
        <!-- 中央:主数据表格 -->
        <table id="gridMain" data-options="toolbar:'#ToolBar'"></table>
        <div id="ToolBar" style="padding:3px;">
            <a class="hisui-linkbutton" id="btnAdd" 
               data-options="iconCls:'icon-add',plain:true">新增</a>
            <a class="hisui-linkbutton" id="btnEdit" 
               data-options="iconCls:'icon-write-order',plain:true,disabled:true">修改</a>
            <a class="hisui-linkbutton" id="btnDelete" 
               data-options="iconCls:'icon-cancel',plain:true,disabled:true">删除</a>
        </div>
    </div>
</div>

<!-- 编辑对话框(内容直接写在 HTML 中,data-options="closed:true" 初始隐藏) -->
<div id="winEdit" class="hisui-dialog" data-options="closed:true" style="padding:10px 10px 0px 10px;">
    <table class="search-table">
        <tr>
            <td class="r-label"><label for="txtCode" class="hisui-label">代码</label></td>
            <td><input class="textbox" id="txtCode" style="width:260px" type="text"/></td>
        </tr>
        <tr>
            <td class="r-label"><label for="txtDesc" class="hisui-label">描述</label></td>
            <td><input class="textbox" id="txtDesc" style="width:260px" type="text"/></td>
        </tr>
        <tr>
            <td class="r-label"><label for="chkIsActive" class="hisui-label">是否有效</label></td>
            <td><input type='hisui-checkbox' type="checkbox" id="chkIsActive"/></td>
        </tr>
        <tr>
            <td colspan="2" class="search-btnlist">
                <a id="btnSave" class="hisui-linkbutton">保存</a>
                <a id="btnClose" class="hisui-linkbutton">关闭</a>
            </td>
        </tr>
    </table>
</div>
</body>
</html>

1.2 关键点说明

  • 脚本引入顺序不可变com.hisui.phm.jscom.sys.jscom.fun.jsbase.csscomponent.js → 业务 JS
  • 布局使用 class="hisui-layout" + data-options="fit:true"
  • 区域划分north(上)、south(下)、west(左)、center(中)、east(右)
  • 按钮权限:引入 phm.auth.js 后,按钮的 disabled:true 会根据后台配置自动控制,无需手动处理
  • 对话框内容直接写在 HTML 中:用
    ,不在 JS 中动态生成
  • 表格工具栏:通过 data-options="toolbar:'#ToolBar'" 关联
  • 表单用 class="search-table"标签用 class="r-label"按钮区用 class="search-btnlist"

二、JS 编写规范

2.1 标准结构

信创版每个页面一个 JS 文件,包含:全局变量、组件初始化、事件绑定、数据加载,全部写在一个 .js 文件里。

// File: static/phm/模块名/scripts/xxx.js

// ========== 1. 页面全局变量对象 ==========
var globalObj = {
    editId: "",          // 当前编辑记录 ID
    gridId: "",          // 当前选中行 ID
    // 其他页面状态...
};

// ========== 2. 页面入口(jQuery document ready) ==========
$(function () {
    // 初始化按钮状态(单选场景:有选中时才允许编辑/删除)
    $("#btnEdit").linkbutton("disable");
    $("#btnDelete").linkbutton("disable");

    // 初始化组件
    initMain();

    // 事件初始化
    InitEvent();

    // 初始化加载表格数据
    loadGridData();
});

// ========== 3. 组件初始化 ==========
function initMain() {
    // 初始化数据表格
    $HUI.datagrid("#gridMain", {
        fit: true,
        headerCls: "panel-header-gray",
        iconCls: "icon-paper",
        rownumbers: true,
        singleSelect: true,
        autoRowHeight: false,
        loadMsg: "数据加载中...",
        pagination: true,
        pageSize: 20,
        pageList: [20, 50, 100, 200],
        columns: [[
            { field: 'code', title: '代码', width: '150' },
            { field: 'displayname', title: '描述', width: '250' },
            { field: 'activity', title: '是否有效', width: '80',
                formatter: function (value) {
                    return value == true ? "是" : "否";
                }
            },
            { field: 'id', title: 'ID', hidden: true }
        ]],
        onSelect: function (rowIndex, rowData) {
            // 防止重复选中同一行时无法取消
            if (rowData.id == globalObj.gridId) {
                $("#gridMain").datagrid("clearSelections");
                $("#btnEdit").linkbutton("disable");
                $("#btnDelete").linkbutton("disable");
                globalObj.gridId = "";
            } else {
                globalObj.gridId = rowData.id;
                $("#btnEdit").linkbutton("enable");
                $("#btnDelete").linkbutton("enable");
            }
        },
        onDblClickRow: function (rowIndex, rowData) {
            editDialog(rowData);
        },
        onLoadSuccess: function (data) {
            globalObj.gridId = "";
            globalObj.editId = "";
            $("#btnEdit").linkbutton("disable");
            $("#btnDelete").linkbutton("disable");
        }
    });

    // 初始化下拉框(如有)
    $HUI.combobox("#cboProduct", {
        url: PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/selectList"),
        method: 'POST',
        onBeforeLoad: function (param) {
            param.obj = { activity: true };
            param.checkTime = true;
        },
        editable: true,
        valueField: 'code',
        textField: 'displayname'
    });

    // 初始化对话框(按钮在 JS 的 buttons 参数中定义)
    $HUI.dialog("#winEdit", {
        title: "编辑",
        iconCls: "icon-w-paper",
        closed: true,
        modal: true,
        isTopZindex: true,
        width: 500,
        height: 400,
        buttons: [{
                text: '保存',
                handler: function () { saveData(); }
            }, {
                text: '关闭',
                handler: function () { $HUI.dialog('#winEdit').close(); }
            }]
    });
}

// ========== 4. 事件绑定 ==========
function InitEvent() {
    // 新增按钮(单选场景:有选中行时禁止新增)
    $("#btnAdd").click(function () {
        var rowData = $("#gridMain").datagrid("getSelected");
        if (rowData) return false;
        editDialog("");
    });

    // 修改按钮
    $("#btnEdit").click(function () {
        var rowData = $("#gridMain").datagrid("getSelected");
        if (!rowData) {
            $.messager.alert("提示", "请先选择对象", "info");
            return false;
        }
        editDialog(rowData);
    });

    // 删除按钮
    $("#btnDelete").click(function () {
        var rowData = $("#gridMain").datagrid("getSelected");
        if (!rowData) {
            $.messager.alert("提示", "请先选择对象", "info");
            return false;
        }
        deleteData();
    });

    // 查询按钮
    $("#btnQuery").click(function () {
        loadGridData();
    });
}

// ========== 5. 数据加载 ==========
function loadGridData() {
    $("#gridMain").datagrid("loading");
    $ipost(PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/selectList"), {
        objXxx: {
            // 查询条件从页面获取
        }
    }, function (result) {
        if (result.success) {
            // 前端分页:使用 PHM_COM.pagerFilter
            $("#gridMain").datagrid({ loadFilter: PHM_COM.pagerFilter })
                             .datagrid("loadData", result.data || []);
        } else {
            $.messager.alert("提示", result.msg, "error");
        }
        $("#gridMain").datagrid("loaded");
    });
}

// ========== 6. 对话框操作 ==========
function editDialog(rowData) {
    if (rowData) {
        // 修改模式:回填表单
        globalObj.editId = rowData.id;
        $("#txtCode").val(rowData.code);
        $("#txtDesc").val(rowData.displayname);
        $("#chkIsActive").checkbox("setValue", rowData.activity);
    } else {
        // 新增模式:清空表单
        globalObj.editId = "";
        $("#txtCode").val("");
        $("#txtDesc").val("");
        $("#chkIsActive").checkbox("setValue", true);
    }
    $HUI.dialog('#winEdit').open();
}

// ========== 7. 保存数据 ==========
function saveData() {
    var code = $.trim($("#txtCode").val());
    var desc = $.trim($("#txtDesc").val());
    if (!code) { $.messager.alert("提示", "代码不能为空!"); return; }
    if (!desc) { $.messager.alert("提示", "描述不能为空!"); return; }

    var url = globalObj.editId
        ? "phm/sys/xxx/update"
        : "phm/sys/xxx/insert";

    $ipost(PHM_COM.joinUrl(PHM_WIN.appPath, url), {
        id: globalObj.editId,
        code: code,
        displayname: desc,
        activity: $("#chkIsActive").checkbox("getValue")
    }, function (result) {
        if (result.success) {
            $.messager.popover({ msg: "保存成功!", type: 'success', timeout: 1000 });
            $HUI.dialog('#winEdit').close();
            loadGridData();
            $("#gridMain").datagrid("clearSelections");
            $("#btnEdit").linkbutton("disable");
            $("#btnDelete").linkbutton("disable");
        } else {
            $.messager.alert("提示", result.msg, "error");
        }
    });
}

// ========== 8. 删除数据 ==========
function deleteData() {
    var rowData = $("#gridMain").datagrid("getSelected");
    $.messager.confirm('确认', '确定删除此记录?', function (r) {
        if (r) {
            $ipost(PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/deleteById"), {
                id: rowData.id
            }, function (result) {
                if (result.success) {
                    $.messager.popover({ msg: "删除成功!", type: 'success', timeout: 1000 });
                    loadGridData();
                } else {
                    $.messager.popover({ msg: result.msg, type: 'error', timeout: 1000 });
                }
            });
        }
    });
}

2.2 关键点说明

  • 全局变量用 globalObj:集中管理页面状态(editIdgridId 等),替代旧版分散的 obj.RecRowID
  • 入口用 $(function() { ... }):jQuery 标准就绪事件,不用 InitviewScreen() 模式
  • API 路径拼接用 PHM_COM.joinUrl(PHM_WIN.appPath, "phm/..."):自动拼接上下文路径,适配不同部署环境
  • 前端分页用 PHM_COM.pagerFilter$("#grid").datagrid({ loadFilter: PHM_COM.pagerFilter }) 然后 loadData(result.data)
  • 响应格式result.success(布尔)、result.code(状态码)、result.msg(消息)、result.data(数据)
  • 对话框按钮在 buttons 参数中定义:不用 HTML onclick,统一在 $HUI.dialog()buttons 中配置
  • 按钮初始状态:页面加载时先 disable,选中行后再 enable(单选场景)
  • 防止重复选中:在 onSelect 中判断 rowData.id == globalObj.gridId 时调用 clearSelections() 取消选中

三、后台交互(数据访问)

> 需先引入 jQuery,再引入 websys.jquery.js。

3.1 $ipost — 向后台发送 POST 请求

> 默认以 request body - JSON 方式发送,对应 Spring Boot @PostMapping + @RequestBody

语法

// 异步调用(推荐)
$ipost(allpath, param, successHandler, errorHandler);

// 同步调用(callback 传 false,返回后台结果)
var rtn = $ipost(allpath, param, false);

参数说明

参数说明
------------
allpath请求路径(如 /api/xxx/save
param请求参数对象
successHandler成功回调函数(异步),入参为后台返回的 JSON;传 false 时为同步调用
errorHandler错误回调函数(可选,仅异步有效)

示例代码

// 异步调用(常用)
$ipost('/api/sys/savemenu', { code: 'his', name: '菜单名' }, function(json) {
    console.log(json); // 后台返回的 JSON 数据
});

// 同步调用(callback 传 false)
var rtn = $ipost('/api/xxx/getInfo', { id: globalObj.gridId }, false);
if (rtn && rtn.code === 200) {
    var d = rtn.data;
    $('#txtCode').val(d.code);
}

// 保存数据(常用模式)
$ipost(PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/update"), {
    id: globalObj.editId,
    code: code,
    displayname: desc
}, function(rtn) {
    if (rtn && rtn.code === 200) {
        $.messager.popover({ msg: '保存成功!', type: 'success', timeout: 1000 });
        $("#gridMain").datagrid("reload");
    } else {
        $.messager.alert("错误提示", "保存失败! " + (rtn ? rtn.message : ''), 'info');
    }
});

// 删除数据
$ipost(PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/deleteById"), { id: globalObj.gridId }, function(rtn) {
    if (rtn && rtn.code === 200) {
        $.messager.popover({ msg: '删除成功!', type: 'success', timeout: 1000 });
        $("#gridMain").datagrid("reload");
    }
});

// 导出 Excel
$ipost('/api/xxx/list', { resultSetType: "excel", fileName: '数据列表' });

// 导出 PDF
$ipost('/api/xxx/list', { resultSetType: "pdf", fileName: '数据列表' });

// 导出并打印 PDF
$ipost('/api/xxx/list', { resultSetType: "excelPrint", printer: '' });

// 指定纸张大小(A3/A4)及方向(rotate: 0 或 90)
$ipost('/api/xxx/list', { resultSetType: "pdf", fileName: '文件名', pageSize: "A3", rotate: "90" });

// 导出时显示进度遮罩
$.messager.progress({ title: "提示", msg: 'Excel文件下载中', text: $g('下载中...') });
$ipost('/api/xxx/list', { p1: "参数", resultSetType: "excel", fileName: '文件名' }, function() {
    $.messager.progress("close");
});

// 文件上传(FormData 方式)
function uploadFile() {
    var fileObj = document.getElementById('upfile').files[0];
    var formData = new FormData();
    formData.append('file', fileObj);
    
    $.messager.progress({ title: "提示", msg: '文件上传中', text: $g('上传中...') });
    $ipost('/file/uploadReturnUrl', formData, function(rtn) {
        $.messager.progress("close");
        // rtn 包含后台返回的文件信息
    });
}

对应 Java 后端示例

@PostMapping("/save")
public BaseResponse<Void> save(@RequestBody XXXDto dto) {
    xxxService.save(dto);
    return BaseResponse.success();
}

3.2 $iget — 向后台发送 GET 请求

> 默认使用 formdata 方式发送,对应 Spring Boot @GetMapping

语法

// 异步调用(推荐)
$iget(allpath, param, successHandler, errorHandler);

// 同步调用(callback 传 false,返回后台结果)
var rtn = $iget(allpath, param, false);

参数说明

参数说明
------------
allpath请求路径(如 /api/xxx/detail
param请求参数对象
successHandler成功回调函数(异步),入参为后台返回的 JSON;传 false 时为同步调用
errorHandler错误回调函数(可选,仅异步有效)

示例代码

// 异步调用(推荐)
$iget('/api/xxx/detail', { id: globalObj.gridId }, function(json) {
    if (json && json.data) {
        var d = json.data;
        $('#txtCode').val(d.code);
        $('#txtDesc').val(d.description);
    }
});

// 同步调用(callback 传 false)
var rtn = $iget(PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/detail"), { id: globalObj.gridId }, false);
if (rtn && rtn.data) {
    $('#txtCode').val(rtn.data.code);
}

// 查询列表
$iget('/api/xxx/list', { keyword: $('#txtName').val(), page: 1, size: 20 }, function(json) {
    if (json && json.data) {
        $("#gridMain").datagrid("loadData", json.data);
    }
});

// 获取下拉数据
$iget('/api/xxx/combo', { type: 'DEPT', isActive: 1 }, function(json) {
    if (json && json.data) {
        $('#cboDept').combobox('loadData', json.data);
    }
});

对应 Java 后端示例

@GetMapping("/detail")
public BaseResponse<XXXVo> detail(String id) {
    XXXVo vo = xxxService.getById(id);
    return BaseResponse.success(vo);
}

3.3 $ipost_enc / $iget_enc — 全参数加密请求

> 发送请求前将所有参数加密,后台 Java 使用 @InterfaceDecrypt 解密。

$iget_enc 示例(GET 全参数加密)

$iget_enc('/api/user/login', {
    password: "123456",
    username: "doctor01",
    loc: '所有科室'
}, function(rtn) {
    console.log(rtn.data);
});

对应 Java:

@GetMapping("/login")
@InterfaceDecrypt
public BaseResponse<UserVo> login(String password, String username, String loc) {
    return BaseResponse.success(userVo);
}

$ipost_enc 示例(POST 全参数加密)

$ipost_enc('/api/user/login', {
    password: "123456",
    username: "doctor01",
    loc: '所有科室'
}, function(rtn) {
    console.log(rtn.data);
});

对应 Java:

@PostMapping("/login")
@InterfaceDecrypt
public BaseResponse<UserDto> login(@RequestBody UserDto dto) {
    return BaseResponse.success(dto);
}

3.4 websys_interfaceEncrypt — 部分参数加密

> 只对指定参数加密,其余参数明文传输,后台使用 @InterfaceDecrypt(keyParams/bodyParams) 解密指定参数。

// GET 部分参数加密
var passwordEnc = websys_interfaceEncrypt("123456");
var usernameEnc = websys_interfaceEncrypt("admin");
$iget('/api/user/login', {
    password: passwordEnc,
    username: usernameEnc,
    loc: '部分科室'
}, function(rtn) {
    console.log(rtn.data);
});

对应 Java:

@GetMapping("/login")
@InterfaceDecrypt(keyParams = {"password", "username"})
public BaseResponse<UserVo> login(String password, String username, String loc) {
    return BaseResponse.success(userVo);
}

四、前端公共方法

4.1 头菜单表单(全局参数读写)

> 头菜单表单用于存储全局参数,如:病人ID、就诊ID、就诊类型、手术ID、会诊ID、DoingSth 等。

常用表单属性

属性名说明
--------------
EpisodeID就诊ID(传此值时 admType 也需传入)
PatientID患者ID
DoingSth正在做某事说明,不为空时切换菜单会弹出提示
admType患者就诊类型(用于患者信息条和诊断录入界面)
PACSApplyNo医技申请单号
AppointmentID手术申请ID
PlannedOperationID拟施手术id

websys_resetMenuForm — 重设头菜单表单

// 重置所有表单(全初始化)
websys_resetMenuForm();

// 强制处理全局头菜单就诊信息
websys_resetMenuForm(true);

websys_getMenuForm — 从头菜单表单获取值

var frm = websys_getMenuForm();
var episodeId = frm.EpisodeID.value;
var patientId = frm.PatientID.value;
var admType   = frm.admType.value;

// 强制处理全局头菜单就诊信息
websys_getMenuForm(true);

websys_setMenuForm — 设置头菜单表单值

> ⚠️ 会先清空所有表单信息,再将参数写入全局表单。

> ⚠️ 除 DoingSth 外,禁止直接用 x.value=x 赋值,必须使用此方法。

websys_setMenuForm({ PatientID: 1, EpisodeID: 2, admType: 'I' });
websys_setMenuForm({ PatientID: 1, EpisodeID: 2, admType: 'I', canGiveBirth: 1 });
websys_setMenuForm({ PatientID: 1, EpisodeID: 2, admType: 'I', AppointmentID: 1 });

// 强制处理全局头菜单就诊信息
websys_setMenuForm({ EpisodeID: 2, PatientID: 1, admType: 'I' }, true);

// DoingSth 可直接赋值
var frm = websys_getMenuForm();
frm.DoingSth.value = "病历文书正在编辑中,是否保存";

4.2 websys_getSession — 获得当前会话信息

var session = websys_getSession();

4.3 websys_getMenuWin — 获得头菜单 Window 对象

var menuWin = websys_getMenuWin();

4.4 websys_showModal — 弹出 HISUI 窗口

在顶层窗口弹出

websys_showModal({
    title: '弹出窗口',
    width: 700,
    height: 400,
    url: '../base/runqian/html/test.html?open=2',
    myData: { startDate: '2024-12-09' }   // 附加参数对象
});

// 在弹出界面中获得附加参数
var myData = websys_showModal('options').myData;  // {startDate:'2024-12-09'}

// 关闭窗口
websys_showModal('close');

在指定 iframe 区域内弹出

websys_showModal({
    title: '弹出窗口',
    width: 700,
    height: 400,
    targetFrm: window,    // 也可用 targetName:"MyName" 指定 iframe 名称
    url: '../../../base/runqian/html/test.html?open=1',
    myData: { startDate: '2024-12-09' }
});

// 在 test.html 中获得附加参数
var myData = websys_showModal('options', { targetFrm: window.parent }).myData;

// 关闭窗口
websys_showModal('close', { targetFrm: window.parent });

4.5 链接路径相关方法

websys_rewriteUrl — 为 URL 增加请求参数

websys_rewriteUrl("my.html?id=1", { id: 2, name: 'whc' }); // 返回:my.html?id=2&name=whc
websys_rewriteUrl("my.html", { id: 2, name: 'whc' });       // 返回:my.html?id=2&name=whc
websys_rewriteUrl("", { id: 2, name: 'whc' });              // 返回:?id=2&name=whc

websys_frontPathCombine — 相对路径转绝对路径

// 相对于 static/base/ 的 html 路径,生成绝对路径
websys_frontPathCombine("../emr/ip/html/my.html");
// 返回:/his/base/../emr/ip/html/my.html

// 以 / 或 // 开头时不处理
websys_frontPathCombine("//emr/ip/html/my.html"); // 返回://emr/ip/html/my.html

websys_urlToParamObj — 获取 URL 中的参数对象

websys_urlToParamObj(location.href);              // 返回当前界面的请求参数对象
websys_urlToParamObj("my.html?id=1&name=whc");    // 返回:{id:1, name:"whc"}
websys_urlToParamObj("id=1&name=whc");            // 返回:{id:1, name:"whc"}

websys_objToParam — 在已有参数串中补充参数

// containEmpty 为 false 或不传时,忽略 obj 中的空值
websys_objToParam({ id: 1 }, "id=2&type=", true);           // 返回:'id=2&type='
websys_objToParam({ id: 1, sex: '' }, "id=2&type=", false); // 返回:'id=2&type='

4.6 websys_createWindow — 创建新窗口

websys_createWindow('my.html', '_blank');
websys_createWindow('my.html', 'TRAK_hidden', 'status,scrollbars,resizable,hisui=true,width=80%,height=80%');

4.7 Token 相关方法

// 获得登录的 token 值
websys_getHosAccessToken();
// 等价于:window.sessionStorage.getItem("hispro__access-token")

// 通用方法获取 sessionStorage 中的值
websys_getHosStorageItemValue('access-token'); // 获取 token
websys_getHosStorageItemValue('HostName');     // 获取 HostName 值

// 也可使用 HOS 基础平台封装的方法
window.hos_utils.ls.get('access-token');

4.8 websys_getTop — 获得同域最顶层 Window

var myTop = websys_getTop();
// 一直向上查找 parent,遇到跨域则返回当前 window

4.9 $g — 国际化翻译方法

// 基础用法
$g('notNull.code');                              // 返回:代码不能为空

// 数组占位符
$g('password.errorTimes', [3, 2]);              // 返回:你已错误登录3次,还有2机会

// 字符串内联占位符(索引方式)
$g('你已错误登录{0}次,还有{1}机会', [3, 2]);   // 返回:你已错误登录3次,还有2机会

// 字符串内联占位符(命名方式)
$g('你已错误登录{etimes}次,还有{rtimes}机会', { etimes: 3, rtimes: 2 });
// 返回:你已错误登录3次,还有2机会

HTML 内翻译:

<td class="hisui-label">姓名</td>
<span class="hisui-label">登记号</span>

4.10 websys_printByRunQian — 润乾打印方法

<!-- 引入公共打印 JS -->
<script src="../../scripts/websys.print.comm.js"></script>
websys_printByRunQian({
    reportName: "bsp/sys/test",           // 不带后缀,必填
    needSelectPrinter: 'yes',             // 是否需要用户选择打印机(yes/no,默认 no)
    printerName: '打印机名称',            // 打印机名
    reportParam: {                        // 会自动加上 session 中信息作为参数
        stDate: '2023-11-18',
        endDate: '2023-11-19'
    }
});

五、核心组件使用示例

5.1 数据表格(Datagrid)

// 初始化
$HUI.datagrid("#gridMain", {
    fit: true,
    title: "病人列表",
    headerCls: 'panel-header-gray',
    iconCls: 'icon-paper',
    pagination: true,
    rownumbers: true,
    singleSelect: true,
    autoRowHeight: false,
    pageSize: 20,
    pageList: [20, 50, 100, 200],
    url: PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/selectList"),
    method: 'post',
    columns: [[
        { field: 'code', title: '编码', width: 100 },
        { field: 'name', title: '姓名', width: 120 },
        { field: 'dept', title: '科室', width: 100 },
        { field: 'diag', title: '诊断', width: 150 },
        { field: 'id', title: 'ID', hidden: true }
    ]],
    onDblClickRow: function(rowIndex, rowData) {
        editDialog(rowData);
    },
    onSelect: function(rowIndex, rowData) {
        if (rowIndex > -1) {
            // 防止重复选中
            if (rowData.id == globalObj.gridId) {
                $("#gridMain").datagrid("clearSelections");
                globalObj.gridId = "";
            } else {
                globalObj.gridId = rowData.id;
            }
        }
    }
});

5.2 放大镜(Lookup)

// 初始化(远程搜索)
$HUI.lookup("#cbgLookup", {
    width: 260,
    panelWidth: 600,
    url: PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/dept/selectList"),
    method: 'post',
    editable: true,
    mode: 'remote',
    idField: 'id',
    textField: 'name',
    columns: [[
        { field: 'code', title: '代码', width: 100 },
        { field: 'name', title: '名称', width: 240 }
    ]],
    pagination: true,
    onBeforeLoad: function(param) {
        var q = param['q'];
        if (q == "") return false;
        param = $.extend(param, { keyword: q });
    },
    onSelect: function(rindex, rowData) {
        if (rindex > -1) {
            globalObj.gridId = rowData.id;
        }
    },
    loadMsg: '正在查询',
    isCombo: true,
    minQueryLen: 0
});

5.3 下拉框(Combobox)

// 初始化
$HUI.combobox("#cboDept", {
    url: PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/dict/selectList"),
    valueField: 'code',
    textField: 'displayname',
    editable: true,
    onBeforeLoad: function(param) {
        param.type = 'DEPT';
        param.isActive = 1;
    }
});

5.4 对话框(Dialog)

// 初始化(按钮在 buttons 参数中定义)
$HUI.dialog("#winEdit", {
    title: '编辑窗口',
    iconCls: 'icon-w-paper',
    closed: true,
    modal: true,
    isTopZindex: true,
    width: 500,
    height: 400,
    buttons: [{
        text: '保存',
        iconCls: 'icon-w-save',
        handler: function() { saveData(); }
    }, {
        text: '关闭',
        iconCls: 'icon-w-close',
        handler: function() { $HUI.dialog('#winEdit').close(); }
    }]
});

// 操作
$HUI.dialog('#winEdit').open();
$HUI.dialog('#winEdit').close();
$HUI.dialog('#winEdit').dialog('setTitle', '新标题');

六、前端方法速查汇总表

方法名类型说明
--------------------
$ipost(path, param, callback, error)HTTPPOST 请求(JSON body),callback 为 false 时同步
$iget(path, param, callback, error)HTTPGET 请求(formdata),callback 为 false 时同步
$ipost_enc(path, param, success)HTTPPOST 全参数加密请求
$iget_enc(path, param, success)HTTPGET 全参数加密请求
websys_interfaceEncrypt(value)加密对单个值加密(部分参数加密场景)
websys_getMenuWin()窗口获得头菜单 Window 对象
websys_getSession()会话获得当前会话信息
websys_resetMenuForm(forceGlobal?)表单重置头菜单表单
websys_getMenuForm(forceGlobal?)表单获取头菜单表单
websys_setMenuForm(options, forceGlobal?)表单设置头菜单表单
websys_showModal(options)窗口弹出 HISUI 窗口
websys_rewriteUrl(url, paramObj)URL为 URL 增加参数
websys_frontPathCombine(url)URL相对路径转绝对路径
websys_urlToParamObj(url)URL解析 URL 参数为对象
websys_objToParam(obj, origin, containEmpty)URL补充参数到参数串
websys_createWindow(url, name, features)窗口创建新窗口
websys_getHosAccessToken()Token获取登录 token
websys_getHosStorageItemValue(key)Token获取 sessionStorage 值
websys_getTop()窗口获得同域最顶层 window
$g(key, params?)国际化翻译文本
websys_printByRunQian(options)打印润乾报表打印

七、常用提示信息

7.1 Popover 提示(推荐)

// 成功提示
$.messager.popover({ msg: '保存成功!', type: 'success', timeout: 1000 });

// 错误提示
$.messager.popover({ msg: '保存失败!', type: 'error', timeout: 2000 });

// 警告提示
$.messager.popover({ msg: '请先选择数据!', type: 'warning', timeout: 1500 });

7.2 Alert 对话框

// 信息提示
$.messager.alert("提示", "操作成功!", 'info');

// 错误提示
$.messager.alert("错误提示", "保存失败!", 'error');

// 确认框
$.messager.confirm('确认', '确定要删除吗?', function(r) {
    if (r) {
        $ipost(PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/deleteById"), { id: globalObj.gridId }, function(rtn) {
            if (rtn && rtn.code === 200) {
                $.messager.popover({ msg: '删除成功!', type: 'success', timeout: 1000 });
                $("#gridMain").datagrid("reload");
            }
        });
    }
});

八、最佳实践

8.1 性能优化

  1. 表格设置 autoRowHeight: false - 提高渲染性能
  2. 使用分页 - pagination: true,每页不超过 200 条
  3. 缓存对象 - 将常用组件赋值给变量,避免重复查找 DOM
  4. 放大镜使用 mode:'remote' - 远程搜索,避免一次性加载大量数据

8.2 代码组织

  1. 每页两个文件 - html/xxx.html + scripts/xxx.js
  2. JS 入口用 $(function(){}) - 不用 InitviewScreen() 旧模式
  3. 全局状态用 globalObj - 集中管理,替代分散变量
  4. 函数命名清晰 - initMain()InitEvent()loadGridData()editDialog()saveData()deleteData()
  5. $ipost 优先 - 统一使用 POST 方式,避免参数暴露在 URL

8.3 错误处理

// 统一错误处理
function showError(msg) {
    $.messager.alert("错误提示", msg, 'info');
}

// 带错误回调的请求
$ipost(PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/save"), param, function(rtn) {
    if (rtn && rtn.code === 200) {
        $.messager.popover({ msg: '操作成功!', type: 'success', timeout: 1000 });
    } else {
        showError("操作失败: " + (rtn ? rtn.message : '网络异常'));
    }
}, function(err) {
    showError("请求失败,请检查网络连接");
});

// 数据校验
function validateForm() {
    var errinfo = "";
    if (!$.trim($('#txtCode').val())) errinfo += "代码不能为空!<br>";
    if (!$.trim($('#txtDesc').val())) errinfo += "描述不能为空!<br>";
    if (errinfo) {
        showError(errinfo);
        return false;
    }
    return true;
}

九、常见问题

Q1: $ipost 和 $iget 有什么区别?

A: $ipost 以 JSON body 方式发送 POST 请求,适合新增/修改/删除;$iget 以 formdata 方式发送 GET 请求,适合查询详情。一般来说优先使用 $ipost,安全性更好。

Q1b: 如何使用同步调用?

A:callback 参数传 false,方法会直接返回结果(阻塞当前线程,仅在必要时使用):

// $ipost 同步
var rtn = $ipost(PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/getInfo"), { id: globalObj.gridId }, false);
if (rtn && rtn.code === 200) { ... }

// $iget 同步
var rtn = $iget(PHM_COM.joinUrl(PHM_WIN.appPath, "phm/sys/xxx/detail"), { id: globalObj.gridId }, false);
if (rtn && rtn.data) { ... }

Q2: 如何在 $ipost/$iget 中处理错误?

A: 在第四个参数传入 errorHandler 函数:

$ipost('/api/xxx', param, function(rtn) {
    // 成功
}, function(err) {
    $.messager.alert("提示", "请求失败", 'error');
});

Q3: 怎么确认后台返回的数据结构?

A: 通常 Java 后端统一返回 BaseResponse 结构:

{
    "code": 200,
    "message": "success",
    "data": { ... }
}

前端通过 rtn.code === 200 判断成功,通过 rtn.data 获取数据,通过 rtn.message 获取提示信息。

Q4: 表格分页参数如何传递?

A: 表格会自动传入 page(页码)和 rows(每页条数)参数,后端可用分页对象处理(如 PageRequest.of(page - 1, rows))。前端使用 PHM_COM.pagerFilter 实现前端分页。

Q5: 对话框无法置顶?

A: 设置 isTopZindex: true

Q6: 按钮禁用后仍然触发事件?

A: 使用 stopAllEventOnDisabled: true 配置项


十、图标参考

  • icon-w-find - 查找
  • icon-w-ok - 确定
  • icon-w-cancel - 取消
  • icon-w-edit - 编辑
  • icon-w-delete - 删除
  • icon-w-save - 保存
  • icon-w-paper - 文档
  • icon-write-order - 修改
  • icon-add - 新增
  • icon-resort - 排序

使用示例:

<a class="hisui-linkbutton" data-options="iconCls:'icon-w-save'">保存</a>

十一、参考资料

  • 前端公共方法文档:http://hisui.cn/bsp/dev/front/
  • HISUI 组件文档:http://hisui.cn/api/
  • EasyUI 文档:http://www.jeasyui.com/documentation/

版本: v20260611(信创版)

适用场景: 医疗信息系统(HIS、EMR、LIS 等)Java 后端

技术栈: HISUI(EasyUI 二次开发)+ Spring Boot

版本历史

共 1 个版本

  • v1.0.0 Initial release 当前
    2026-06-11 13:37 安全 安全

安全检测

腾讯云安全 (Keen)

安全,无风险
查看报告

腾讯云安全 (Sanbu)

安全,无风险
查看报告

🔗 相关推荐

dev-programming

Mcporter

steipete
使用 mcporter CLI 直接列出、配置、认证及调用 MCP 服务器/工具(支持 HTTP 或 stdio),涵盖临时服务器、配置编辑及 CLI/类型生成功能。
★ 195 📥 67,725
dev-programming

Github

steipete
使用 `gh` CLI 与 GitHub 交互,通过 `gh issue`、`gh pr`、`gh run` 和 `gh api` 管理议题、PR、CI 运行及高级查询。
★ 679 📥 327,940
dev-programming

CodeConductor.ai

larsonreever
AI驱动平台,提供快速全栈开发、智能体、工作流自动化及低代码AI集成的可扩展产品创建。
★ 72 📥 182,008