表单自定义控件
要求
适用环境
- 私有部署
- SAAS
ONES 系统版本
v6.100.0+
ONES CLI 版本
v1.70.1+
npm install -g @ones/cli --registry=https://npm.partner.ones.cn/registry/
ones --version
1.70.1
能力概述
本文档主要介绍如何通过功能扩展在工作项详情表单,新建表单,步骤表单中添加自定义表单控件。
功能扩展配置
配置
在 config/plugin.yaml中添加如下配置
oauth:
type:
- user
scope:
- read:project:issueField
extension:
- formControlExtension:
provider: smsprov2
slots:
- name: ones:form:control:content
entryUrl: modules/ones-form-control-content-nLtK/index.html
- name: ones:form:control:settings
entryUrl: modules/ones-form-control-settings-71OJ/index.html
config:
name: 自定义控件name
fieldUUIDs:
- 9ax9ExKt
- M3Fgzu3F
- EGx9jsaH
- LS5aqwaW
supportForms:
- detail
- create
- transition
controlTips: 控件描述
注:oauth 相关的配置主要跟 Open API 有关,插件可以按需配置。具体参考文档:Open API
插槽说明
| 插件名称 | 说明 |
|---|---|
| ones:form:control:content | 表单自定义控件在表单中渲染的内容插槽。 |
| ones:form:control:settings | 表单自定义控件在表单配置器中实现自定义配置的设置插槽。如果表单自定义控件不需要自定义配置,可以不实现这个插槽。 |
config 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| name | string | 表单自定义控件名称 |
| fieldUUIDs | string[] | 表单自定义控件包含的属性列表 |
| supportForms | "detail" | "create" | "transition" | 表单自定义控件支持的表单,目前只有三种(detail,create,transition)。目前 create 必须跟 detail 一起使用。 |
| controlTips | string | 控件描述,在表单配置器中展示,可以不配置。 |
前端实现
表单自定义控件内容插槽
- 创建插槽内容渲染的入口文件
web/src/modules/ones-form-control-content-nLtK/index.tsx。
import React from 'react'
import ReactDOM from 'react-dom'
import { ConfigProvider } from '@ones-design/core'
import { lifecycle, OPProvider } from '@ones-op/bridge'
import './index.css'
import { ControlContentExtension } from './control_content_extension'
ReactDOM.render(
<ConfigProvider>
<OPProvider>
<ControlContentExtension/>
</OPProvider>
</ConfigProvider>,
document.getElementById('ones-mf-root'),
)
lifecycle.onDestroy(() => {
ReactDOM.unmountComponentAtNode(document.getElementById('ones-mf-root') as HTMLElement)
})
- 实现
ControlContentExtension组件。
import React, { useEffect } from 'react'
import type { FC } from 'react'
import { useExtensionContext, useExtensionConfig } from '@ones-op/sdk'
export const ControlContentExtension: FC = () => {
// 在插件内部调用useExtensionContext获取到标品传递给插件的上下文参数。调用useExtensionConfig获取到插件配置。
const extensionContext = useExtensionContext()
const extensionConfig = useExtensionConfig()
const {
fields,
fieldsConfig,
ctx,
values,
onSubmit,
onPermissionDenied,
type,
inEditor,
onChange,
settings,
} = extensionContext
return <div>your business logic</div>
}
extensionContext参数说明
| 字段 | 类型 | 说明 | 详情表单 | 新建表单 | 步骤表单 |
|---|---|---|---|---|---|
| name | string | 表单自定义控件名称 | ✅ | ✅ | ✅ |
| inEditor | boolean | 是否在表单配置器中 | ✅ | ✅ | ✅ |
| type | "detail" | "create" | "transition" | 当前表单类型 | ✅ | ✅ | ✅ |
| fields | IField[] | 属性基本信息 | ✅ | ✅ | ✅ |
| fieldsConfig | Record<string, FieldConfig> | 属性在表单中的配置,包括:visible,required,placeholder,hasPermission | ✅ | ✅ | ✅ |
| values | Record<string, any> | 属性在表单中的值 | ✅ | ✅ | ✅ |
| settings | Record<string, any> | 自定义控件在表单上的配置 | ✅ | ✅ | ✅ |
| ctx | ControlContentExtensionContext | 上下文信息 | ✅ | ✅ | ✅ |
| onPermissionDenied | (fieldUUID: string) => void | 没有权限的情况下根据 fieldUUID 弹出对应的toast 文案,具体逻辑标品来处理 | ✅ | ||
| onInit | (config: IControlExtensionInitConfig) => void | 表单自定义控件初始化配置,如果控件内部对属性设置了必填,可以将控件内部的validate 方法传递给标品,标品在提交数据的时候调用 | ✅ | ✅ | |
| onSubmit | (values: Record<string, { value: unknown; submitType?: SubmitTypeEnum }> ) => Promise<void> | 提交数据的回调 | ✅ | ||
| onChange | (value: Record<string, any>) => void; | 新建表单/步骤表单内数据发生变化后的回调 | ✅ | ✅ |
IControlExtensionInitConfig类型
export type ControlExtensionValidate = () => Promise<any>
export interface IControlExtensionInitConfig {
validate?: ControlExtensionValidate // 验证成功 resolve,失败 reject
}
ControlContentExtensionContext类型
export interface ControlContentExtensionContext {
taskUUID?: string // 工作项 UUID,仅详情表单,步骤表单会传递,
projectUUID?: string // 项目 UUID
issueTypeUUID?: string // 工作项类型 UUID
taskDetailViewMode?: TaskDetailViewMode // 工作项详情布局,仅详情表单会传递
taskStatus?: TaskStatus // 工作项状态,仅详情表单
transitionUUID?: string // 步骤流UUID,仅步骤表单才会有
formValues?: Record<string, any> // 表单的值,仅新建表单和步骤表单有
}
export enum TaskDetailViewMode {
Wide = 'wide', // 宽详情布局
Narrow = 'narrow', // 窄详情布局
}
export interface TaskStatus {
uuid: string
category: string
name: string
}
-
流程说明:
详情表单:调用
onSubmit传入表单自定义控件内部编辑好的数据,标品监听到onSubmit事件后会将接收到的参数调用 update 接口更新工作项属性的值。新建表单和步骤表单:调用
onChange传入表单自定义控件内部编辑好的数据,标品监听到onChange事件后,会将接收到的值保存到表单内部,最后在点击确定按钮的时候统一提交数据。
表单自定义控件配置插槽
- 创建插槽自定义配置的入口文件
web/src/modules/ones-form-control-settings-71OJ/index.tsx。
import React from 'react'
import ReactDOM from 'react-dom'
import { ConfigProvider } from '@ones-design/core'
import { lifecycle, OPProvider } from '@ones-op/bridge'
import { ControlSettingsExtension } from './control_settings_extension'
import './index.css'
ReactDOM.render(
<ConfigProvider>
<OPProvider>
<ControlSettingsExtension />
</OPProvider>
</ConfigProvider>,
document.getElementById('ones-mf-root'),
)
lifecycle.onDestroy(() => {
ReactDOM.unmountComponentAtNode(document.getElementById('ones-mf-root') as HTMLElement)
})
- 实现
ControlSettingsExtension组件。
import React, { useEffect } from 'react'
import type { FC } from 'react'
import { useExtensionContext, useExtensionConfig } from '@ones-op/sdk'
export const ControlSettingsExtension: FC = () => {
// 在插件内部调用useExtensionContext获取到标品传递给插件的上下文参数。调用useExtensionConfig获取到插件配置。
const extensionContext = useExtensionContext()
const extensionConfig = useExtensionConfig()
return <div>your business logic</div>
}
extensionContext参数说明
| 名称 | 类型 | 描述 |
|---|---|---|
| name | string | 插件的名称 |
| type | 'detail' | 'create' | 'transition' | 表单类型 |
| fields | IField[] | 属性基本信息 |
| value | Record<string, any> | 控件历史保存的配置 |
| ctx | ControlSettingsExtensionContext | 上下文信息 |
| onChange | (value: Record<string, any>) => Promise<void> | 控件配置发生改变后的回调 |
ControlSettingsExtensionContext类型
export interface ControlSettingsExtensionContext {
projectUUID?: string // 项目 UUID
issueTypeUUID?: string // 工作项类型 UUID
transitionUUID?: string // 步骤流UUID,仅步骤表单才会有
}
- 流程说明:
插件内部将编辑好的数据,通过onChange回调给标品,标品监听到 onChange 事件后会将接收到的参数保存到表单配置中。在渲染的时候会将配置读取出来,用 settings 字段传递给插件。