Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

自定义表单数据结构设计 #243

Open
lywTYH opened this issue Apr 9, 2021 · 24 comments
Open

自定义表单数据结构设计 #243

lywTYH opened this issue Apr 9, 2021 · 24 comments

Comments

@lywTYH
Copy link
Contributor

lywTYH commented Apr 9, 2021

自定义字段

客服和管理员进行增删该查

JSON Format

名称 类型 必填 注释
type string true dropdown | multiSelect | text | multiLine | checkbox
description string false 字段描述(此字段并不会在自定义表单显示)
title string true 客服显示字段标题(同时也为字段名,跟 userTitle userDescription 对应)
userTitle string true 终端用户显示字段标题
userDescription string false 终端用户显示字段描述
permission string true 字段权限 editableForUser | readOnlyForUser | agentOnly
requiredForSubmit boolean false (默认为 false) 是否必填
active Boolean true (默认为 true) 是否为激活(考虑到自定义工单使用自定义字段,所以不允许删除字段)
creator Pointer true 创建者,关联 _User 表的字段
createdAt Date true 创建时间
updatedAt Date true 更新时间
objectId String true id

Example

自定义字段可以使用部分字段可以使用自定义变量,数据库存储字段和 api 返回字段并不完全一致,api 的返回会增加编译后的字段。

{
    "type": "checkbox",
    "permission":"editableForUser",
    "requiredForSubmit":false,
    "active":true,

    "description":"112",
    "title": "title {{variable}}",
    "displayTitle":"title testVar", // 编译后的 title
    "userTitle":"title {{custom variable}}",
    "displayUserTitle":"title testVar", // 编译后的 userTitle
    "userDescription":"33\u7ec8\u7aef\u7528\u6237\u663e\u793a\u63cf\u8ff0",

    "creator":{
        "type":"Pointer",
        "className":"_User",
        "objectId":"605aeb3ee7580f00f741d0b9"
    },
    "createdAt":"2021-04-07T11:00:29.755Z","type":"checkbox","title":"22","active":true,
    "updatedAt":"2021-04-07T11:00:29.755Z",
    "objectId":"606d90cd475a4c5d46bf5322",
}


displayTitle displayUserTitle 字段并非数据库存储的字段而是 api 返回对 title userTitle 编译后的字段。description 不支持自定义变量。

目前临时用 js sdk 实现的增删改查不支持自定义变量。后续会用rest api 进行实现。

自定义表单

客服和管理员进行增删该查

JSON Format

名称 类型 必填 注释
name string true 表单名称
userName string true 终端用户显示的 form 表单名称
active Boolean true(默认为 true) 是否为激活
creator Pointer true 创建者,关联 _User 表的字段
createdAt Date true 创建时间
updatedAt Date true 更新时间
objectId String true id

Example

{
  "name": "Snowboard Problem",
  "displayName": "Snowboard Problem",
  "userName": "{{dc.my_display_name}}",
  "displayUserName": "Snowboard Damage",
  "active":true,
  "creator":{
    "type":"Pointer",
    "className":"_User",
    "objectId":"605aeb3ee7580f00f741d0b9"
  },
  "createdAt":"2021-04-07T11:00:29.755Z","type":"checkbox","title":"22","active":true,
  "updatedAt":"2021-04-07T11:00:29.755Z",
  "objectId":"606d90cd475a4c5d46bf5322",
}

displayName displayUserName 字段并非数据库存储的字段而是 api 返回对 name userName 编译后的字段。
后续如果有需求会加入 conditions userConditions 在表单控制字段的权限以及其他约束。

自定义字段的权限如何设计?

自定义字段的权限包含

  • 用户可编辑
  • 用户只读
  • 只限客服
  • 必填

根据权限描述我们使用 role 进行控制, role:agent 代表客服 role:user 代表用户。必填只能单独控制。

自定义字段组成表单时可以调整字段权限,字段的权限并非最终权限而只是为组成表单的默认权限。

权限实际控制在自定义表单和自定义字段的中间表上。

中间表

名称 类型 必填 注释
formId string true 表单 id
filedId string true 字段 id
permission string true 权限
requiredForSubmit boolean true 是否必填
index number true 字段在表单的顺序
createdAt Date true 创建时间
updatedAt Date true 更新时间
objectId String true id

其中 acl 的值 必须与 permission的值相对应。

ACL 与 permission 对应关系为

// 只限客服的字段 ACL -> agentOnly
{
  "role:agent":{
    write:true,
    read:true
  }
}
// 用户只读字段 ACL -> readOnlyForUser
{
  "role:agent":{
    write:true,
    read:true
  },
  "role:user":{
    write:false,
    read:true
  }
}
// 用户可编辑 ACL  -> editableForUser
{
  "role:agent":{
    write:true,
    read:true
  },
  "role:user":{
    write:true,
    read:true
  }
}

如何存储自定义表单的值

使用 键值对 的方式进行存储,其中 key 为表单和字段的中间表 id,值为表单字段值。

具体方法为 扩展工单字段 extraFormData 类型为 object。

这种方法优点是简单 缺点是数据层面上没有做权限控制。

如何获取自定义表单结构以及如何渲染

获取表单的 json 数据描述,根据描述由客户端自由渲染。

实际数据结构根据 api 而定

@lywTYH lywTYH changed the title 自定义表单设计 自定义表单数据结构设计 Apr 9, 2021
@sdjdd
Copy link
Contributor

sdjdd commented Apr 12, 2021

中间表的 formIdfieldId 也用 Pointer 存吧。

@lywTYH
Copy link
Contributor Author

lywTYH commented Apr 12, 2021

是的用 Pointer ,这里只是单纯的描述。实际上并没有建立表

@sdjdd
Copy link
Contributor

sdjdd commented Apr 13, 2021

这种方法优点是简单 缺点是数据层面上没有做权限控制。

我觉的数据层面的权限控制还是有必要的,不然让用户看到客服给他标记的信息就太尴尬拉

@lywTYH
Copy link
Contributor Author

lywTYH commented Apr 13, 2021

这种方法优点是简单 缺点是数据层面上没有做权限控制。

我觉的数据层面的权限控制还是有必要的,不然让用户看到客服给他标记的信息就太尴尬拉

这里还有一种设计是使用中间表 ,其结构为

名称 类型 必填 注释
ticketId string true 工单 id
value object 自定义表单值
createdAt Date true 创建时间
updatedAt Date true 更新时间
objectId String true id

会根据表单和字段的中间表的权限进行查询返回 但是不确定是否能做到,如果不能这个表需要把 表单和字段的中间表 的权限部分复制过来

权限方面总结:

自定义字段并不涉及实际的数据权限,只是设置默认数据权限。
自定义表单由自定义字段组合而成同时确定字段的最终权限。(这里使用中间表保存表单和字段的对应关系,以及最终字段权限。这里已经无法通过表单查询没有权限的字段的数据)

update:

value 类型为 object 并存储整个表单的值

@leeyeh
Copy link
Contributor

leeyeh commented Apr 15, 2021

  • requiredForSubmit 为什么是字段的属性而不是表单的属性?
  • 「字段的权限并非最终权限而只是为组成表单的默认权限」,那命名上最好就体现出来,比如叫 defaultACL
  • 提醒我一下,为什么不改造现在的 Tag 来着?还是说这个是 Tag 的超集?

@lywTYH
Copy link
Contributor Author

lywTYH commented Apr 15, 2021

requiredForSubmit 为什么是字段的属性而不是表单的属性?
「字段的权限并非最终权限而只是为组成表单的默认权限」,那命名上最好就体现出来,比如叫 defaultACL

自定义表单部分目前不打算涉及字段权限只做字段组合所以 requiredForSubmit 需要在字段上设置。

不需要命名体现

提醒我一下,为什么不改造现在的 Tag 来着?还是说这个是 Tag 的超集?

存值这里只是说明 2 种实现方案,实际情况可以用 tag

@sdjdd
Copy link
Contributor

sdjdd commented Apr 15, 2021

现在的 Tag 只用来存 appId ,我觉得算是当初的一个过渡设计,其实可以直接存到 Ticket 表里。
Tag 这个表名也不适合存自定义表单的数据。所以不如舍弃这个历史包袱 👀

@sdjdd
Copy link
Contributor

sdjdd commented Apr 16, 2021

贴一下我的建议:

TicketField

Name Type Mandatory Description
active boolean false -
required boolean false 是否必填
title string true -
type string true 字段类型: dropdown, multi-select, text, multi-line, checkbox, numeric
options array false select, multi-select 的选项

TicketForm

Name Type Mandatory Description
active boolean false -
name string true -
fieldIds array true 字段 ID 组成的数组

TicketFieldValue

Name Type Mandatory Description
ticket Pointer true -
field Pointer true -
value any true -

@lywTYH
Copy link
Contributor Author

lywTYH commented Apr 16, 2021

如果从文档所有的需求上看 以及用 restAPI 约束数据 不考虑 ACL @sdjdd 的建议反而更好

TicketFieldValue 其中 value 可以直接使用一个 object

{
  "fieldId":value
}

另外字段表 少一个字段我忘记加到 issue 上

fieldOptions array<Object> 目前是存储单选和多选的 option value

@sdjdd

This comment has been minimized.

@sdjdd
Copy link
Contributor

sdjdd commented Apr 19, 2021

开搞,争取今天搞定 😤 等需求确定再说 👀

@lywTYH
Copy link
Contributor Author

lywTYH commented Apr 20, 2021

TicketField

Name Type Mandatory Description
active boolean false -
required boolean false 是否必填
type string true 字段类型: dropdown, multi-select, text, multi-line, checkbox, numeric

TicketFieldOption

Name Type Mandatory Description
field pointer true 自定义字段 id
locale string true 语言类型
name string true 自定义字段名称
options array false select, multi-select 的选项

@sdjdd
Copy link
Contributor

sdjdd commented Apr 20, 2021

language ❌
locale ⭕

@lywTYH
Copy link
Contributor Author

lywTYH commented Apr 20, 2021

TicketFieldOption 名字 @sdjdd 你在考虑换下不是很贴切

@leeyeh
Copy link
Contributor

leeyeh commented Apr 20, 2021

fieldId: Pointer ❌
field: Pointer ⭕

@lywTYH
Copy link
Contributor Author

lywTYH commented Apr 20, 2021

@leeyeh 理解没有问题把

可以在某一种语言下进行内容配置

按照这个说法 必填也需要移动到下面表

@leeyeh
Copy link
Contributor

leeyeh commented Apr 20, 2021

No,只有部分字段才会是 per locale 的。

@sdjdd
Copy link
Contributor

sdjdd commented Apr 22, 2021

不好意思没看到你 at 我。现在开始跟进这个 👀

@sdjdd
Copy link
Contributor

sdjdd commented Apr 22, 2021

也就是说:不同语言的下拉框,选项数量是有可能不同的吧?那可不可以更进一步设计成不同语言的字段,类型也有可能不同,比如中文是下拉框,英文就是文本框?

@sdjdd
Copy link
Contributor

sdjdd commented Apr 22, 2021

TicketFieldOption 名字 @sdjdd 你在考虑换下不是很贴切

叫 TicketFieldVariant 如何? @leeyeh

@sdjdd
Copy link
Contributor

sdjdd commented Apr 22, 2021

还需要一个 TicketFieldValue ,就按我 这里 回复的来搞吧

@sdjdd
Copy link
Contributor

sdjdd commented Apr 22, 2021

开搞 😤

@sdjdd
Copy link
Contributor

sdjdd commented Apr 22, 2021

name 改成 title 吧

@leeyeh
Copy link
Contributor

leeyeh commented Apr 22, 2021

也就是说:不同语言的下拉框,选项数量是有可能不同的吧?那可不可以更进一步设计成不同语言的字段,类型也有可能不同,比如中文是下拉框,英文就是文本框?

不管理论上可不可以,我们还是先不支持这样吧。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants