表单预填充

自动预填充对象创建表单、搜索表单和转换表单中的字段值。

本文档介绍如何使用 API 方法预填充 iTop 表单中的字段值。更多详细内容请参考 iTop 官方文档

概述

iTop 已经内置了一些自动预填充行为:

  • 搜索预设:编辑 Team 并添加成员时,Person 搜索会自动按 Team 的组织过滤
  • 创建预设:在编辑 User Request 时创建新的 Caller Person,该 Person 的组织会自动填充为 User Request 的组织

对于 95% 的情况这些自动行为已经足够,但某些特殊场景需要通过 API 方法进行定制。

前置条件:熟悉教程中使用的语法,并已创建扩展。

API 方法

方法说明
PrefillSearchForm(&$aContextParam)预设相关对象的搜索框字段
PrefillCreationForm(&$aContextParam)预设对象创建表单字段
PrefillTransitionForm(&$aContextParam)预设转换表单字段

这些方法可以在以下场景中使用:

  • 从菜单/操作调用
  • 在间接 LinkedSet 属性(n:n 关系)中添加对象时
  • 从编辑对象时 ExternalKey 属性旁的 + 按钮(1:n 关系)
  • 从 LinkedSet 属性的行内编辑模式(n:1 关系)

预填充搜索表单

源对象类上定义,预设每个相关对象搜索框中的字段。

上下文参数

参数说明
$aContextParam['dest_class']搜索的目标类
$aContextParam['filter']过滤条件(DBObjectSearch 对象)
$aContextParam['user']当前登录用户的用户名
$aContextParam['origin']consoleportal

示例:按提供商过滤服务

在 Contract 类上,限制搜索仅返回提供商的服务,以及客户和提供商的联系人及文档:

/** 示例:在 Contract 类上修改搜索,仅搜索:
 *      提供商的服务
 *      客户和提供商的联系人及文档 **/
public function PrefillSearchForm(&$aContextParam)
{
  // 如果搜索的是 'Service' 类或其子类
  if($aContextParam['dest_class'] == 'Service'
     || is_subclass_of($aContextParam['dest_class'], 'Service'))
  {
    // 如果搜索类有 'org_id' 属性且 Contract 的 provider_id 不为空
    if(MetaModel::IsValidAttCode($aContextParam['dest_class'],'org_id')
       && !empty($this->Get('provider_id')))
    {
        // 移除默认搜索设置的任何条件
        $aContextParam['filter']->ResetCondition();
        // 设置搜索类的 org_id 条件为 Contract 的提供商
        $aContextParam['filter']->AddCondition('org_id', $this->Get('provider_id'));
    }
  }
  // 如果搜索的是 Contact 或 Document 类或其子类
  elseif (($aContextParam['dest_class'] == 'Contact'
          || is_subclass_of($aContextParam['dest_class'], 'Contact'))
          || ($aContextParam['dest_class'] == 'Document'
          || is_subclass_of($aContextParam['dest_class'], 'Document')))
  {
    if(MetaModel::IsValidAttCode($aContextParam['dest_class'],'org_id'))
    {
      $aOrgIds = array();
      if(!empty($this->Get('provider_id'))) $aOrgIds[] = $this->Get('provider_id');
      if(!empty($this->Get('org_id')))      $aOrgIds[] = $this->Get('org_id');

      if(count($aOrgIds)>0)
      {
         // 使用 IN 参数设置多个 org_id 条件
         $aContextParam['filter']->ResetCondition();
         $aContextParam['filter']->AddCondition('org_id', $aOrgIds , 'IN');
      }
    }
  }
}

示例:限制为 Server 子类

class UserRequest extends Ticket
{
    /**
     * 限制 CI 搜索仅返回 Server 类
     * 并允许用户设置其他 Server 字段作为搜索条件
     */
    public function PrefillSearchForm(&$aContextParam)
    {
        if($aContextParam['dest_class'] == 'FunctionalCI')
        {
            // 将 FunctionalCI 搜索改为仅搜索 Server
            $aContextParam['filter']->ChangeClass('Server');
        }
    }
}

使用 ChangeClass('Server')AddCondition('finalclass', 'Server') 更好,因为前者允许使用任何 Server 字段作为搜索条件,而后者仅限于 FunctionalCI 的字段。

示例:使用关系过滤

class UserRequest extends Ticket
{
    /**
     * 限制 CI 搜索仅返回与请求者关联的 PC
     * SELECT PC JOIN lnkContactToFunctionalCI AS L ON L.functionalci_id=PC.id
     * WHERE L.contact_id = :this->caller_id
     */
    public function PrefillSearchForm(&$aContextParam)
    {
        if($aContextParam['dest_class'] == 'FunctionalCI')
        {
            // 过滤为仅 PC
            $aContextParam['filter']->AddCondition('finalclass', 'PC');
            // 搜索 lnkContactToFunctionalCI
            $oSearchLnk = new DBObjectSearch('lnkContactToFunctionalCI');
            // 限制为与请求者相关的链接
            $oSearchLnk->AddCondition('contact_id', $this->Get('caller_id'));
            // 将链接搜索与 FunctionalCI 搜索关联
            $aContextParam['filter']->AddCondition_ReferencedBy($oSearchLnk, 'functionalci_id');
        }
    }
}

预填充创建表单

预设类的创建表单字段。

  • 自动机制已完成预设工作,如果对象是从另一个对象创建的,字段可能已被填充
  • $this 引用即将创建的对象

上下文参数

参数说明
$aContextParam['user']当前登录用户的用户名
$aContextParam['origin']consoleportal
$aContextParam['source_obj']仅在创建外部键对象时可用(例如从 Person 创建 Team)

示例 1:从 ServiceSubcategory 创建 RequestTemplate

public function PrefillCreationForm(&$aContextParam)
{
    $id = $this->Get('servicesubcategory_id');
    if ($id != 0)
    {
        // 获取原始对象
        $oSubcategoryObject = MetaModel::GetObject('ServiceSubCategory', $id, false);
        // 使用原始对象的字段值预填充其他数据
        $this->Set('service_id', $oSubcategoryObject->Get('service_id'));
    }
}

示例 2:预设 Contract 的日期和提供商

public function PrefillCreationForm(&$aContextParam)
{
    // 如果尚未设置,将合同开始日期预设为当前日期
    if(empty($this->Get('start_date'))) {
        $this->Set('start_date', time());
    }

    // 获取当前用户
    $oUser = UserRights::GetUserObject();
    // 将合同提供商预设为当前用户的组织
    // 注意:'org_id' 仅在 iTop 2.5.0 及以上版本的 User 类中可用
    $this->Set('provider_id', $oUser->Get('org_id'));
}

示例 3:预设 UserRequest 的请求者

public function PrefillCreationForm(&$aContextParam)
{
    // 获取当前用户
    $oUser = UserRights::GetUserObject();
    // 将 caller 字段预填充为用户的联系人
    $this->SetIfNull('caller_id', $oUser->Get('contactid'));

    return true;
}

预填充转换表单

预设转换表单中的值:

  • 此时转换尚未执行
  • $this 引用即将应用转换的当前对象

上下文参数

参数说明
$aContextParam['expected_attributes']['attribute_code']表单中属性的显示标志
$aContextParam['origin']consoleportal
$aContextParam['stimulus']应用的刺激

示例:“分配给我” 逻辑

如果分配或重新分配工单,且工单未分配给我,同时我是该工单派发团队的一员,则在进入转换表单时将我的名字预设为 “agent”:

public function PrefillTransitionForm(&$aContextParam)
{
  $oPerson = UserRights::GetContactObject();
  // 如果当前用户有关联的 Person 且处于分配转换
  if ($oPerson && ($aContextParam['stimulus'] == 'ev_assign'
      || $aContextParam['stimulus'] == 'ev_reassign'))
  {
    $iTicketAgentId = $this->Get('agent_id');
    $iPersonId = $oPerson->GetKey();

    // 如果 agent 不是当前用户
    if ($iTicketAgentId != $iPersonId )
    {
      // 检查当前联系人是否可以分配给该工单
      $iTicketTeamId = $this->Get('team_id');

      $oTeamLinkSet = $oPerson->Get('team_list');
      $bIsInTeam = false;
      while($oTeamLink = $oTeamLinkSet->Fetch())
      {
        $iTeam = $oTeamLink->Get('team_id');
        if ($iTicketTeamId == $iTeam) { $bIsInTeam = true; }
      }
      if($bIsInTeam)
      {
        $this->Set('agent_id', $iPersonId);
        // 移除 MUST CHANGE 标志
        if(array_key_exists('agent_id', $aContextParam['expected_attributes']))
        {
          $aContextParam['expected_attributes']['agent_id'] = ~OPT_ATT_MUSTCHANGE & $aContextParam['expected_attributes']['agent_id'];
        }
      }
    }
  }
}

已知限制

  • 当 agent 被预设为用户名时,工单详情中的显示也会更新,仿佛修改已完成,可能造成混淆
  • 用户可以通过将 agent 设置回之前的值来绕过 “must-change” 标志

在 XML 中集成方法

以下是在 XML 数据模型定义中声明上述方法的示例:

<class id="RequestTemplate" _delta="must_exist">
    <methods>
        <method id="PrefillCreationForm" _delta="define">
            <static>false</static>
            <access>public</access>
            <type>Overload-DBObject</type>
            <arguments>
                <argument id="1">
                    <type>reference</type>
                    <mandatory>true</mandatory>
                </argument>
            </arguments>
            <code><![CDATA[public function PrefillCreationForm(&$aContextParam)
          {       // 函数代码    }]]>
            </code>
        </method>
    </methods>
</class>

参考


原文:https://www.itophub.io/wiki/page?id=3_2_0:customization:form_prefill

2025/07/09 16:07 by127.0.0.1

版本:3_2_0/customization/form_prefill.txt · Last modified: 2025/07/09 16:07 by 127.0.0.1