mcpField
U
ui-generation

ui-generation

github.com/happy-technologies-llc开发4142 次安装2 天前更新
代码仓库

关于 ui-generation

面向 ServiceNow 开发者和公民开发者的 UI 生成技能,可将自然语言需求转化为客户端脚本、Service Portal 组件和 UI Builder 页面等组件。流程还包括查询现有实现以参考,并验证生成结果。

主要功能

  1. 01从自然语言需求识别组件与行为
  2. 02生成表单客户端脚本
  3. 03创建 Service Portal 小组件
  4. 04构建 UI Builder 页面与事件映射
  5. 05查询现有组件并验证生成结果

适用场景

  1. 01根据业务描述生成表单字段行为
  2. 02快速制作 Service Portal 小组件原型
  3. 03构建带数据资源的工作区页面
  4. 04为 UI 交互生成事件处理逻辑

MCP 相关

该技能通过 MCP 工具查询现有 UI 组件、创建和更新脚本及页面配置,并发现表结构以支持数据绑定。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/happy-technologies-llc/happy-platform-skills --skill ui-generation

安装后在 Claude Code 中输入/ui-generation确认已加载。

详细介绍

使用自然语言生成 UI

概述

此技能介绍如何根据自然语言描述生成 ServiceNow UI 组件:

  • 为表单和列表创建客户端脚本(onChange、onLoad、onSubmit、onCellEdit)
  • 为 UI Builder 和 Service Portal 小组件构建数据绑定配置
  • 为用户交互生成事件处理逻辑
  • 使用 Jelly/HTML 模板和处理脚本创建 UI Pages
  • 使用 AngularJS 控制器和 HTML 模板构建 Service Portal 小组件
  • 使用数据资源和事件映射生成 UI Builder 体验页面
  • 为可重用的表单装饰和格式化程序生成 UI 宏

适用场景: 当开发者或公民开发者需要根据自然语言描述的业务需求创建 UI 组件,或需要快速制作表单行为、门户小组件或工作区页面的原型时。

先决条件

  • 角色: admin、personalize_form 或 sp_admin(用于 Service Portal 小组件)
  • 插件: com.glide.ui.ui_page(UI Pages)、com.glide.service-portal(Service Portal)、com.sn_ui_builder(UI Builder)
  • 访问权限: 对 sys_script_client、sys_ui_page、sp_widget、sys_ux_page_registry 表具有写入权限
  • 知识要求: JavaScript 基础知识、GlideForm API、AngularJS 基础知识(用于 Service Portal)、UI Builder 概念
  • 相关技能: 用于客户端脚本模式的 development/client-scripts,以及用于目录表单行为的 catalog/ui-policies

流程

第 1 步:解析自然语言描述

分析用户请求以确定:

  • 组件类型: 客户端脚本、UI 页面、Service Portal 小组件、UI Builder 页面、UI 宏
  • 目标表单/表: 组件适用的表或表单
  • 行为: 应执行的操作(显示/隐藏字段、验证数据、获取记录、渲染 UI)
  • 触发条件: 启动行为的事件(字段更改、表单加载、按钮点击、页面加载)
  • 数据依赖项: 组件需要读取或写入的数据
第 2 步:查询现有组件以获取模式

MCP 方式:

Tool: SN-Query-Table
Parameters:
  table_name: sys_script_client
  query: table=incident^active=true^typeLIKEonChange
  fields: sys_id,name,table,type,field_name,script,active,ui_type
  limit: 10

REST 方式:

GET /api/now/table/sys_script_client
  ?sysparm_query=table=incident^active=true^typeLIKEonChange
  &sysparm_fields=sys_id,name,table,type,field_name,script,active,ui_type
  &sysparm_limit=10
第 3 步:生成客户端脚本

将自然语言转换为 GlideForm API 调用。常见模式:

onChange——显示/隐藏字段:

MCP 方式:

Tool: SN-Create-Record
Parameters:
  table_name: sys_script_client
  data:
    name: "Show VPN fields when category is Network"
    table: incident
    type: onChange
    field_name: category
    ui_type: 0
    active: true
    script: |
      function onChange(control, oldValue, newValue, isLoading) {
        if (isLoading) return;
        var isNetwork = (newValue == 'network');
        g_form.setVisible('u_vpn_type', isNetwork);
        g_form.setVisible('u_network_segment', isNetwork);
        if (isNetwork) {
          g_form.setMandatory('u_vpn_type', true);
        } else {
          g_form.setMandatory('u_vpn_type', false);
        }
      }

REST 方式:

POST /api/now/table/sys_script_client
Body: {
  "name": "Show VPN fields when category is Network",
  "table": "incident",
  "type": "onChange",
  "field_name": "category",
  "ui_type": "0",
  "active": "true",
  "script": "function onChange(control, oldValue, newValue, isLoading) { ... }"
}
第 4 步:生成用于表单初始化的 onLoad 脚本

MCP 方式:

Tool: SN-Create-Record
Parameters:
  table_name: sys_script_client
  data:
    name: "Initialize priority banner on form load"
    table: incident
    type: onLoad
    ui_type: 0
    active: true
    script: |
      function onLoad() {
        var priority = g_form.getValue('priority');
        if (priority == '1') {
          g_form.showFieldMsg('priority', 'Critical incident - follow P1 procedures', 'error');
          g_form.setReadOnly('category', true);
          g_form.setReadOnly('subcategory', true);
        }
      }
第 5 步:生成 onSubmit 验证脚本

MCP 方式:

Tool: SN-Create-Record
Parameters:
  table_name: sys_script_client
  data:
    name: "Validate resolution notes before close"
    table: incident
    type: onSubmit
    ui_type: 0
    active: true
    script: |
      function onSubmit() {
        var state = g_form.getValue('state');
        if (state == '6') {
          var resolution = g_form.getValue('close_notes');
          if (!resolution || resolution.trim().length < 20) {
            g_form.showFieldMsg('close_notes', 'Resolution notes must be at least 20 characters', 'error');
            return false;
          }
        }
        return true;
      }
第 6 步:生成 Service Portal 小组件

MCP 方式:

Tool: SN-Create-Record
Parameters:
  table_name: sp_widget
  data:
    name: "Team Incident Dashboard"
    id: "team-incident-dashboard"
    template: |
      <div class="panel panel-default">
        <div class="panel-heading"><h3>{{c.data.title}}</h3></div>
        <div class="panel-body">
          <div ng-repeat="inc in c.data.incidents track by inc.sys_id">
            <div class="alert alert-{{inc.priorityClass}}">
              <strong>{{inc.number}}</strong> - {{inc.short_description}}
              <span class="pull-right badge">{{inc.state}}</span>
            </div>
          </div>
          <p ng-if="c.data.incidents.length === 0">No open incidents.</p>
        </div>
      </div>
    client_script: |
      api.controller = function($scope) {
        var c = this;
      };
    server_script: |
      (function() {
        data.title = "My Team's Open Incidents";
        var gr = new GlideRecord('incident');
        gr.addQuery('assignment_group', gs.getUser().getMyGroups());
        gr.addActiveQuery();
        gr.orderByDesc('priority');
        gr.setLimit(20);
        gr.query();
        data.incidents = [];
        while (gr.next()) {
          data.incidents.push({
            sys_id: gr.getUniqueValue(),
            number: gr.getValue('number'),
            short_description: gr.getValue('short_description'),
            state: gr.getDisplayValue('state'),
            priority: gr.getValue('priority'),
            priorityClass: {'1':'danger','2':'warning','3':'info','4':'success'}[gr.getValue('priority')] || 'default'
          });
        }
      })();

REST 方式:

POST /api/now/table/sp_widget
Body: {
  "name": "Team Incident Dashboard",
  "id": "team-incident-dashboard",
  "template": "<div class='panel panel-default'>...</div>",
  "client_script": "api.controller = function($scope) { var c = this; };",
  "server_script": "(function() { ... })();"
}
第 7 步:生成 UI Builder 体验页面

MCP 方式:

Tool: SN-Create-Record
Parameters:
  table_name: sys_ux_page_registry
  data:
    title: "Executive Incident Overview"
    path: /executive-incident-overview
    description: "Executive dashboard showing incident metrics and trends"
    category: workspace
    active: true

为页面配置数据资源:

Tool: SN-Create-Record
Parameters:
  table_name: sys_ux_data_broker_transform
  data:
    name: "Incident Metrics Data Resource"
    page: "<page_sys_id>"
    table: incident
    query: "active=true^priority<=2"
    fields: "number,short_description,priority,state,assigned_to,sys_created_on"
    max_rows: 50
第 8 步:生成事件处理程序

配置 UI Builder 的事件到操作映射:

MCP 方式:

Tool: SN-Create-Record
Parameters:
  table_name: sys_ux_event
  data:
    name: "Row Click Navigate to Record"
    page: "<page_sys_id>"
    component: "<component_sys_id>"
    event_name: "click"
    action_type: "navigate"
    action_config: {
      "route": "/record/incident/${sys_id}",
      "target": "_self"
    }
第 9 步:生成用于表单装饰的 UI 宏

MCP 方式:

Tool: SN-Create-Record
Parameters:
  table_name: sys_ui_macro
  data:
    name: "sla_countdown_banner"
    description: "Displays a countdown timer for SLA breach on incident form"
    xml: |
      <?xml version="1.0" encoding="utf-8"?>
      <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide">
        <g:evaluate var="jvar_sla_info" expression="
          var sla = new GlideRecord('task_sla');
          sla.addQuery('task', current.sys_id);
          sla.addQuery('has_breached', false);
          sla.addActiveQuery();
          sla.orderBy('planned_end_time');
          sla.setLimit(1);
          sla.query();
          sla.next() ? sla.getDisplayValue('planned_end_time') : 'N/A';
        "/>
        <div style="background:#fff3cd;padding:10px;border-radius:4px;margin-bottom:10px;">
          <strong>SLA Target:</strong> ${jvar_sla_info}
        </div>
      </j:jelly>
第 10 步:验证和测试生成的组件

MCP 方式:

Tool: SN-Query-Table
Parameters:
  table_name: sys_script_client
  query: sys_id=<created_sys_id>
  fields: sys_id,name,table,type,active,sys_updated_on
  limit: 1

通过检查 sys_update_xml 表中的最新更新记录,确认没有脚本语法错误:

Tool: SN-Query-Table
Parameters:
  table_name: sys_update_xml
  query: name=sys_script_client_<sys_id>^ORDERBYDESCsys_created_on
  fields: sys_id,name,action,sys_created_on
  limit: 1

工具用法

工具用途使用场景
SN-Query-Table查找现有 UI 组件以获取模式模式发现、验证
SN-Create-Record创建客户端脚本、小组件、UI 页面构建新的 UI 组件
SN-Update-Record修改脚本、模板、配置迭代生成的组件
SN-Get-Table-Schema查找用于数据绑定的字段名称了解表单字段和数据模型

最佳实践

  1. 始终正确设置 ui_type —— 桌面端使用 0,移动端/服务门户使用 1,两者都使用 2
  2. 使用 g_form API 方法,而不是直接操作 DOM,来编写客户端脚本
  3. 尽量减少客户端脚本中的服务器调用 —— 使用 GlideAjax 异步查询服务器
  4. 恰当限定客户端脚本的作用域 —— 使用 IIFE 避免污染全局作用域
  5. 在多种浏览器上进行测试 —— 避免使用特定于浏览器的 JavaScript 功能
  6. 在所有生成的 onChange 处理程序中加入空值检查,以处理字段值为空的情况
  7. 在 onChange 脚本中使用 isLoading 防护,避免表单加载时执行
  8. 在服务器调用期间将组件设为只读,避免重复提交
  9. 遵循无障碍标准 —— 在自定义组件中加入 ARIA 标签和键盘导航
  10. 版本控制 —— 创建 UI 组件前,始终将其关联到一个更新集

故障排除

问题原因解决方法
客户端脚本未触发type 或 field_name 值错误确认 type 与事件匹配,且 field_name 与列名匹配
g_form 未定义错误脚本在表单上下文之外运行确保脚本关联到正确的表和 ui_type
组件数据未加载服务器脚本中的 GlideRecord 查询错误检查服务器脚本中的表权限和查询语法
UI 页面空白XML 中的 Jelly 语法错误验证 XML 结构,并检查是否存在未转义字符
事件处理程序无响应组件 ID 不匹配确认事件配置中的组件 sys_id
表单字段未隐藏字段名与标签不匹配使用列名(例如 u_vpn_type),而不是标签

示例

示例 1:从自然语言生成客户端脚本

输入:“当有人在事件表单中选择‘硬件’作为类别时,将型号和序列号字段设为必填,并显示一条提示消息,要求填写这些字段。”

**生成内容:**一个针对 incident.category 的 onChange 客户端脚本;当 newValue == 'hardware' 时,调用 g_form.setMandatory() 和 g_form.showFieldMsg() 处理 u_model 和 u_serial_number。

示例 2:从自然语言生成 Service Portal 组件

输入:“创建一个组件,显示已登录用户尚未关闭的请求,并用状态栏展示完成百分比。”

**生成内容:**一个 Service Portal 组件,其中服务器脚本查询当前用户的 sc_req_item,客户端通过 AngularJS 和 Bootstrap 进度条进行渲染,并提供点击导航功能。

示例 3:从自然语言生成 UI Builder 页面

输入:“构建一个工作区页面,显示按优先级分类的事件图表,并在下方列出我团队尚未关闭的事件。”

**生成内容:**一个 UI Builder 页面注册,包含两个数据资源(用于图表的聚合数据和用于表格的列表数据)、一个绑定到优先级聚合数据的条形图组件,以及一个支持点击行导航的数据表组件。

相关技能

  • development/client-scripts - 客户端脚本开发模式详解
  • development/ui-actions - UI 操作按钮和链接
  • catalog/ui-policies - 目录专用 UI 策略
  • development/scripted-rest-apis - 用于组件数据的后端 API
  • genai/flow-generation - 用于 UI 触发流程的 Flow Designer 自动化

评论

支持 Markdown