---
title: 表单定义
---
在 Halo 2.0,在 Console 端的所有表单我们都使用了 [FormKit](https://github.com/formkit/formkit) 的方案。FormKit 不仅支持使用 Vue 组件的形式来构建表单,同时支持使用 Schema 的形式来构建。因此,我们的 [Setting](https://github.com/halo-dev/halo/blob/87ccd61ae5cd35a38324c30502d4e9c0ced41c6a/src/main/java/run/halo/app/core/extension/Setting.java#L20) 资源中的表单定义,都是使用 FormKit Schema 来定义的,最常用的场景即主题和插件的设置表单定义。当然,如果要在 Halo 2.0 的插件中使用,也可以参考 FormKit 的文档使用 Vue 组件的形式使用,但不需要在插件中引入 FormKit。
此文档将不会介绍 FormKit 的具体使用教程,因为我们已经很好的集成了 FormKit,并且使用方式基本无异。此文章将介绍 Halo 2.0 中表单定义的一些规范,以及额外的一些输入组件。
FormKit 相关文档:
- Form Schema: [https://formkit.com/essentials/schema](https://formkit.com/essentials/schema)
- FormKit Inputs: [https://formkit.com/inputs](https://formkit.com/inputs)
:::tip
目前不支持 FormKit Pro 中的输入组件,但 Halo 额外提供了部分输入组件,将在下面文档列出。
:::
## Setting 资源定义方式
```yaml title="settings.yaml"
apiVersion: v1alpha1
kind: Setting
metadata:
name: foo-setting
spec:
forms:
- group: group_1
label: 分组 1
formSchema:
- $formkit: radio
name: color_scheme
label: 默认配色
value: system
options:
- label: 跟随系统
value: system
- label: 深色
value: dark
- label: 浅色
value: light
- group: group_2
label: 分组 2
formSchema:
- $formkit: text
name: username
label: 用户名
value: ""
- $formkit: password
name: password
label: 密码
value: ""
```
:::tip
需要注意的是,FormKit Schema 本身应该是 JSON 格式的,但目前我们定义一个表单所使用的是 YAML,可能在参考 FormKit 写法时需要手动转换一下。
:::
字段说明:
1. `metadata.name`:设置资源的名称,建议以 `-setting` 结尾。
2. `spec.forms`:表单定义,可以定义多个表单,每个表单都有一个 `group` 字段,用于区分不同的表单。
3. `spec.forms[].label`:表单的标题。
4. `spec.forms[].formSchema`:表单的定义,使用 FormKit Schema 来定义。虽然我们使用的 YAML,但与 FormKit Schema 完全一致。
## 组件类型
除了 FormKit 官方提供的常用输入组件之外,Halo 还额外提供了一些输入组件,这些输入组件可以在 Form Schema 中使用。
### verificationForm
#### 描述
用于远程验证一组数据是否符合要求的组件。
#### 参数
- `action`:对目标数据进行验证的接口地址
- `label`:验证按钮文本
- `submitAttrs`:验证按钮的额外属性
#### 示例
```yaml
- $formkit: verificationForm
action: /apis/console.api.halo.run/v1alpha1/verify/verify-password
label: 账户校验
children:
- $formkit: text
label: "用户名"
name: username
validation: required
- $formkit: password
label: "密码"
name: password
validation: required
```
:::tip
尽管 `verificationForm` 本身是一个输入组件,但与其他输入组件不同的是,它仅仅用于包装待验证的数据,所以并不会破坏原始数据的格式。例如上述示例中的值在保存后为:
```json
{
"username": "admin",
"password": "admin"
}
```
而不是
```json
{
"verificationForm": {
"username": "admin",
"password": "admin"
}
}
```
:::
示例中发送至验证地址的值为如下格式:
```json
{
"username": "admin",
"password": "admin"
}
```
当验证接口返回成功响应时,则验证通过,否则验证失败。
若用户在验证失败时想显示错误信息,可以在验证接口返回错误信息,该错误信息的结构定义需遵循 [RFC 7807 - Problem Details for HTTP APIs](https://datatracker.ietf.org/doc/html/rfc7807.html) 。例如:
```json
{
"title": "无效凭据",
"status": 401,
"detail": "用户名或密码错误。"
}
```
UI 效果:
### repeater
#### 描述
一组重复的输入组件,可以用于定义一组数据,最终得到的数据为一个对象的数组,可以方便地让使用者对其进行增加、移除、排序等操作。
#### 参数
- `min`:数组最小要求数量,默认为 `0`
- `max`:数组最大容量,默认为 `Infinity`,即无限制
- `addButton`:是否显示添加按钮
- `addLabel`:添加按钮的文本
- `upControl`:是否显示上移按钮
- `downControl`:是否显示下移按钮
- `insertControl`:是否显示插入按钮
- `removeControl`:是否显示移除按钮
#### 示例
```yaml
- $formkit: repeater
name: socials
label: 社交账号
value: []
max: 5
min: 1
children:
- $formkit: select
name: enabled
id: enabled
label: 是否启用
options:
- label: 是
value: true
- label: 否
value: false
- $formkit: text
# 在 Repeater 中进行条件判断的方式,当 enabled 为 true 时才显示
if: "$value.enabled === true",
name: name
label: 名称
value: ""
- $formkit: text
if: "$value.enabled === true",
name: url
label: 地址
value: ""
```
:::tip
使用 `repeater` 类型时,一定要设置默认值,如果不需要默认有任何元素,可以设置为 `[]`。
:::
其中 `name` 和 `url` 即数组对象的属性,最终保存表单之后得到的值为以下形式:
```json
{
"socials": [
{
"name": "GitHub",
"url": "https://github.com/halo-dev"
}
]
}
```
UI 效果:
### attachment
#### 描述
附件类型的输入框,支持直接调用附件库弹框选择附件。
#### 参数
- `accepts`:文件类型,数据类型为 `string[]`。
#### 示例
```yaml
- $formkit: attachment
name: logo
label: Logo
accepts:
- "image/png"
- "video/mp4"
- "audio/*"
value: ""
```
### code
#### 描述
代码编辑器的输入组件,集成了 [Codemirror](https://codemirror.net/)。
#### 参数
- `language`:代码语言,目前支持 `yaml` `html` `javascript` `css` `json`。
- `height`:代码编辑器的高度。
#### 示例
```yaml
- $formkit: code
name: footer_code
label: 页脚代码注入
value: ""
language: yaml
```
### menuCheckbox
#### 描述
菜单复选框,用于选择系统内的导航菜单。其中选择的值为菜单资源 `metadata.name` 的集合。
#### 示例
```yaml
- $formkit: menuCheckbox
name: menus
label: 菜单
value: []
```
### menuRadio
#### 描述
菜单单选框,用于选择系统内的导航菜单。其中选择的值为菜单资源 `metadata.name`。
#### 示例
```yaml
- $formkit: menuRadio
name: menu
label: 菜单
value: ""
```
### postSelect
#### 描述
文章选择器,用于选择系统内的文章。其中选择的值为文章资源 `metadata.name`。
#### 示例
```yaml
- $formkit: postSelect
name: post
label: 文章
value: ""
```
### singlePageSelect
#### 描述
单页选择器,用于选择系统内的独立页面。其中选择的值为独立页面资源 `metadata.name`。
#### 示例
```yaml
- $formkit: singlePageSelect
name: singlePage
label: 单页
value: ""
```
### categorySelect
#### 描述
文章分类选择器,用于选择系统内的文章分类。其中选择的值为文章分类资源 `metadata.name`。
#### 示例
```yaml
- $formkit: categorySelect
name: category
label: 分类
value: ""
```
### categoryCheckbox
#### 描述
文章分类复选框,用于选择系统内的文章分类。其中选择的值为文章分类资源 `metadata.name` 的集合。
#### 示例
```yaml
- $formkit: categoryCheckbox
name: categories
label: 分类
value: []
```
### tagSelect
#### 描述
文章标签选择器,用于选择系统内的文章标签。其中选择的值为文章标签资源 `metadata.name`。
#### 示例
```yaml
- $formkit: tagSelect
name: tag
label: 标签
value: ""
```
### tagCheckbox
#### 描述
文章标签复选框,用于选择系统内的文章标签。其中选择的值为文章标签资源 `metadata.name` 的集合。
#### 示例
```yaml
- $formkit: tagCheckbox
name: tags
label: 标签
value: []
```