关于 catalog-items
面向 ServiceNow 开发人员的服务目录技能,介绍目录项目、变量、客户端脚本、审批与履行流程的设计,并包含记录生产器和订购指南示例。
主要功能
- 01设计目录、类别和可申请项目
- 02配置变量与可复用变量集
- 03编写客户端脚本和表单验证
- 04设置定价、审批与履行流程
- 05创建记录生产器和订购指南
适用场景
- 01构建自助服务申请表单
- 02复用多个目录项目的字段组
- 03按条件验证申请并计算价格
- 04为多项目入职申请设置向导
MCP 相关
文档提及用于创建目录变量的 MCP 工具,包括 snow_create_variable 和 snow_create_catalog_variable。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ serac-labs/ serac --skill catalog-items安装后在 Claude Code 中输入/catalog-items确认已加载。
详细介绍
ServiceNow 服务目录开发
服务目录允许用户通过自助服务门户申请服务和项目。
目录组件
| 组件 | 用途 | 示例 |
|---|---|---|
| Catalog | 类别的容器 | IT 服务目录 |
| Category | 项目分组 | 硬件、软件 |
| Item | 可申请的服务 | 申请新笔记本电脑 |
| Variable | 项目上的表单字段 | 笔记本电脑型号下拉框 |
| Variable Set | 可重复使用的变量组 | 用户详细信息 |
| Producer | 直接创建记录 | 报告事件 |
| Order Guide | 多项目向导 | 新员工入职配置 |
目录项目结构
Catalog Item: Request New Laptop
├── Variables
│ ├── laptop_model (Reference: cmdb_model)
│ ├── reason (Multi-line text)
│ └── urgency (Choice: Low, Medium, High)
├── Variable Sets
│ └── Delivery Information (Address, Contact)
├── Catalog Client Scripts
│ ├── onLoad: Set defaults
│ └── onChange: Update price
├── Workflows/Flows
│ └── Laptop Approval Flow
└── Fulfillment
└── Creates Task for IT
变量类型
| 类型 | 使用场景 | 示例 |
|---|---|---|
| 单行文本 | 简短输入 | 员工 ID |
| 多行文本 | 较长输入 | 业务理由 |
| 选择框 | 单选 | 优先级 |
| 复选框 | 是/否 | 加急配送 |
| 引用 | 链接到表 | 申请对象 |
| 日期 | 日期选择器 | 需要日期 |
| 查找选择框 | 筛选后的引用 | 按类别选择型号 |
| 列表收集器 | 多项选择 | 抄送收件人 |
| 容器开始/结束 | 视觉分组 | 硬件选项 |
| 宏 | 自定义小组件 | 费用计算器 |
创建目录变量
基本变量
// Via MCP (snow_create_variable supports reference, checkbox, etc.;
// snow_create_catalog_variable covers text/choice types only)
snow_create_variable({
cat_item: "<catalog item sys_id>",
name: "laptop_model",
question_text: "Laptop Model",
type: "reference",
mandatory: true,
order: 100,
})
// Set the reference table and qualifier on the created variable
snow_record_manage({
action: "update",
table: "item_option_new",
sys_id: "<variable sys_id>",
data: { reference: "cmdb_model", reference_qual: "category=computer" },
})
带动态默认值的变量
// Variable: requested_for
// Type: Reference (sys_user)
// Default value (script):
javascript: gs.getUserID()
带引用限定条件的变量
// Variable: assignment_group
// Type: Reference (sys_user_group)
// Reference Qualifier:
// Simple:
active=true^type=it
// Dynamic (Script):
javascript: 'active=true^manager=' + gs.getUserID()
// Advanced (using current variables):
javascript: 'u_department=' + current.variables.department
目录客户端脚本
在 onLoad 时设置默认值
function onLoad() {
// Set default values
g_form.setValue("urgency", "low")
// Hide admin-only fields
if (!g_user.hasRole("catalog_admin")) {
g_form.setDisplay("cost_center", false)
}
// Set default date to tomorrow
var tomorrow = new GlideDateTime()
tomorrow.addDays(1)
g_form.setValue("needed_by", tomorrow.getDate().getValue())
}
在 onChange 时动态定价
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading) return
// Get price from selected model
var ga = new GlideAjax("CatalogUtils")
ga.addParam("sysparm_name", "getModelPrice")
ga.addParam("sysparm_model", newValue)
ga.getXMLAnswer(function (price) {
g_form.setValue("item_price", price)
updateTotal()
})
}
function updateTotal() {
var price = parseFloat(g_form.getValue("item_price")) || 0
var quantity = parseInt(g_form.getValue("quantity")) || 1
g_form.setValue("total_cost", (price * quantity).toFixed(2))
}
在 onSubmit 时进行验证
function onSubmit() {
// Validate business justification for high-cost items
var cost = parseFloat(g_form.getValue("total_cost"))
var justification = g_form.getValue("business_justification")
if (cost > 1000 && !justification) {
g_form.showFieldMsg("business_justification", "Required for items over $1000", "error")
return false
}
// Validate date is in future
var neededBy = g_form.getValue("needed_by")
var today = new GlideDateTime().getDate().getValue()
if (neededBy < today) {
g_form.showFieldMsg("needed_by", "Date must be in the future", "error")
return false
}
return true
}
变量集
创建可重复使用的变量集
Variable Set: User Contact Information
├── contact_name (Single Line Text)
├── contact_email (Email)
├── contact_phone (Single Line Text)
└── preferred_contact (Choice: Email, Phone, Either)
Use in multiple catalog items:
- New Laptop Request
- Software Installation
- Network Access Request
访问变量集值
// In workflow or script
var ritm = current // sc_req_item
// Access variable from variable set
var contactEmail = ritm.variables.contact_email
var preferredContact = ritm.variables.preferred_contact
目录工作流/流程
审批模式
Flow Trigger: sc_req_item created
├── If: Total cost > $5000
│ └── Request Approval: Department Manager
│ └── If: Rejected
│ └── Update: RITM state = Closed Incomplete
├── If: Total cost > $25000
│ └── Request Approval: VP
├── Create: Catalog Task for Fulfillment
└── Wait: Task completion
履行脚本
// In catalog item's "Execution Plan" or workflow
var ritm = current // sc_req_item
// Create an incident from catalog request
var inc = new GlideRecord("incident")
inc.initialize()
inc.setValue("short_description", ritm.short_description)
inc.setValue("description", ritm.description)
inc.setValue("caller_id", ritm.request.requested_for)
inc.setValue("category", ritm.variables.category)
inc.setValue("priority", ritm.variables.urgency)
inc.insert()
// Link incident to request
ritm.setValue("u_fulfillment_record", inc.getUniqueValue())
ritm.update()
记录生成器
通过目录创建事件
// Record Producer: Report an Issue
// Table: incident
// Script:
// Map variables to incident fields
current.short_description = producer.short_description
current.description = producer.description
current.caller_id = gs.getUserID()
current.category = producer.category
current.subcategory = producer.subcategory
current.priority = producer.urgency == "urgent" ? "2" : "3"
// Set assignment based on category
if (producer.category == "network") {
current.assignment_group.setDisplayValue("Network Support")
} else {
current.assignment_group.setDisplayValue("Service Desk")
}
订单指南
多步骤申请向导
Order Guide: New Employee Onboarding
├── Step 1: Employee Information
│ └── Variable Set: Employee Details
├── Step 2: Hardware Selection
│ ├── Catalog Item: Laptop
│ ├── Catalog Item: Monitor
│ └── Catalog Item: Peripherals
├── Step 3: Software Requests
│ └── Rule: Show software based on department
├── Step 4: Access Requests
│ └── Cascade Variable: Copy employee info
└── Submit: Creates multiple RITMs
订单指南规则
// Rule: Show software items based on department
function rule(item, guide_variables) {
var dept = guide_variables.department
// Show engineering software only for Engineering
if (item.name == "Engineering Software Suite") {
return dept == "engineering"
}
// Show finance software only for Finance
if (item.name == "Financial Tools") {
return dept == "finance"
}
return true // Show all other items
}
定价与审批
动态定价
// Catalog Item Script (Pricing)
// Runs when item is added to cart
var basePrice = parseFloat(current.price) || 0
var quantity = parseInt(current.variables.quantity) || 1
var expedited = current.variables.expedited == "true"
var total = basePrice * quantity
if (expedited) {
total *= 1.5 // 50% rush fee
}
current.recurring_price = 0
current.price = total
审批规则
Approval Definition: High-Value Purchases
Condition: total_cost > 5000
Approver: requested_for.manager
Wait for: Approval
Rejection action: Cancel request
最佳实践
- 变量命名 - 使用具有描述性的全小写名称(不含空格)
- 变量集 - 重复使用常见的变量组
- 引用限定条件 - 仅筛选相关记录
- 客户端脚本 - 尽量减少服务器调用(谨慎使用 GlideAjax)
- 履行 - 创建任务,不要直接完成
- 测试 - 使用不同的用户角色进行测试
- 移动设备 - 在手机/平板电脑上测试目录项目
- 文档 - 为变量添加帮助文本
评论
支持 Markdown