models.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. package work
  2. import (
  3. "dashoo.cn/opms_libary/myerrors"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "net/url"
  8. )
  9. const (
  10. //SysApprovalChange 审批实例变更
  11. SysApprovalChange = "sys_approval_change"
  12. )
  13. func marshalIntoJSONBody(x interface{}) ([]byte, error) {
  14. y, err := json.Marshal(x)
  15. if err != nil {
  16. // should never happen unless OOM or similar bad things
  17. return nil, fmt.Errorf("go-workwx: failed to marshal request: %w", err)
  18. }
  19. return y, nil
  20. }
  21. type reqAccessToken struct {
  22. CorpID string
  23. CorpSecret string
  24. }
  25. func (x reqAccessToken) intoURLValues() url.Values {
  26. return url.Values{
  27. "corpid": {x.CorpID},
  28. "corpsecret": {x.CorpSecret},
  29. }
  30. }
  31. type respCommon struct {
  32. ErrCode int64 `json:"errcode"`
  33. ErrMsg string `json:"errmsg"`
  34. }
  35. // IsOK 响应体是否为一次成功请求的响应
  36. //
  37. // 实现依据: https://work.weixin.qq.com/api/doc#10013
  38. //
  39. // > 企业微信所有接口,返回包里都有errcode、errmsg。
  40. // > 开发者需根据errcode是否为0判断是否调用成功(errcode意义请见全局错误码)。
  41. // > 而errmsg仅作参考,后续可能会有变动,因此不可作为是否调用成功的判据。
  42. func (x *respCommon) IsOK() bool {
  43. return x.ErrCode == 0
  44. }
  45. func (x *respCommon) TryIntoErr() error {
  46. if x.IsOK() {
  47. return nil
  48. }
  49. return myerrors.ThirdPluginError(errors.New(fmt.Sprintf("ErrCode:%v, ErrMsg:%v", x.ErrCode, x.ErrMsg)), "企业微信接口调用失败")
  50. }
  51. type respAccessToken struct {
  52. respCommon
  53. AccessToken string `json:"access_token"`
  54. ExpiresInSecs int64 `json:"expires_in"`
  55. }
  56. type reqJSAPITicketAgentConfig struct{}
  57. func (x reqJSAPITicketAgentConfig) intoURLValues() url.Values {
  58. return url.Values{
  59. "type": {"agent_config"},
  60. }
  61. }
  62. type reqJSAPITicket struct{}
  63. func (x reqJSAPITicket) intoURLValues() url.Values {
  64. return url.Values{}
  65. }
  66. type respJSAPITicket struct {
  67. respCommon
  68. Ticket string `json:"ticket"`
  69. ExpiresInSecs int64 `json:"expires_in"`
  70. }
  71. // reqConvertUserIDToOpenID userid转openid 请求
  72. type reqConvertUserIDToOpenID struct {
  73. UserID string `json:"userid"`
  74. }
  75. // respConvertUserIDToOpenID userid转openid 响应
  76. type respConvertUserIDToOpenID struct {
  77. respCommon
  78. OpenID string `json:"openid"`
  79. }
  80. func (x reqConvertUserIDToOpenID) intoBody() ([]byte, error) {
  81. return marshalIntoJSONBody(x)
  82. }
  83. // reqConvertOpenIDToUserID openid转userid 请求
  84. type reqConvertOpenIDToUserID struct {
  85. OpenID string `json:"openid"`
  86. }
  87. // respConvertUserIDToOpenID openid转userid 响应
  88. type respConvertOpenIDToUserID struct {
  89. respCommon
  90. UserID string `json:"userid"`
  91. }
  92. func (x reqConvertOpenIDToUserID) intoBody() ([]byte, error) {
  93. return marshalIntoJSONBody(x)
  94. }
  95. // SizeType qrcode尺寸类型
  96. //
  97. // 1: 171 x 171; 2: 399 x 399; 3: 741 x 741; 4: 2052 x 2052
  98. type SizeType int
  99. const (
  100. // SizeTypeMini 171 x 171
  101. SizeTypeMini SizeType = iota + 1
  102. // SizeTypeSmall 399 x 399
  103. SizeTypeSmall
  104. // SizeTypeMedium 741 x 741
  105. SizeTypeMedium
  106. // SizeTypeLarge 2052 x 2052
  107. SizeTypeLarge
  108. )
  109. // reqUserIDByMobile 手机号获取 userid 请求
  110. type reqUserIDByMobile struct {
  111. Mobile string `json:"mobile"`
  112. }
  113. func (x reqUserIDByMobile) intoBody() ([]byte, error) {
  114. return marshalIntoJSONBody(x)
  115. }
  116. // respUserIDByMobile 手机号获取 userid 响应
  117. type respUserIDByMobile struct {
  118. respCommon
  119. UserID string `json:"userid"`
  120. }
  121. // EmailType 用户邮箱的类型
  122. //
  123. // 1表示用户邮箱是企业邮箱(默认)
  124. // 2表示用户邮箱是个人邮箱
  125. type EmailType int
  126. const (
  127. // EmailTypeCorporate 企业邮箱
  128. EmailTypeCorporate EmailType = 1
  129. // EmailTypePersonal 个人邮箱
  130. EmailTypePersonal EmailType = 2
  131. )
  132. // reqUserIDByEmail 邮箱获取 userid 请求
  133. type reqUserIDByEmail struct {
  134. Email string `json:"email"`
  135. EmailType EmailType `json:"email_type"`
  136. }
  137. func (x reqUserIDByEmail) intoBody() ([]byte, error) {
  138. return marshalIntoJSONBody(x)
  139. }
  140. // respUserIDByEmail 邮箱获取 userid 响应
  141. type respUserIDByEmail struct {
  142. respCommon
  143. UserID string `json:"userid"`
  144. }
  145. // reqUserInfoGet 获取访问用户身份
  146. type reqUserInfoGet struct {
  147. // 通过成员授权获取到的code,最大为512字节。每次成员授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
  148. Code string
  149. }
  150. func (x reqUserInfoGet) intoURLValues() url.Values {
  151. return url.Values{
  152. "code": {x.Code},
  153. }
  154. }
  155. // reqJSCode2Session 临时登录凭证校验
  156. type reqJSCode2Session struct {
  157. JSCode string
  158. }
  159. func (x reqJSCode2Session) intoURLValues() url.Values {
  160. return url.Values{
  161. "js_code": {x.JSCode},
  162. "grant_type": {"authorization_code"},
  163. }
  164. }
  165. // respJSCode2Session 临时登录凭证校验
  166. type respJSCode2Session struct {
  167. respCommon
  168. JSCodeSession
  169. }
  170. // JSCodeSession 临时登录凭证
  171. type JSCodeSession struct {
  172. CorpID string `json:"corpid"`
  173. UserID string `json:"userid"`
  174. SessionKey string `json:"session_key"`
  175. }
  176. // reqAuthCode2UserInfo 获取访问用户身份
  177. type reqAuthCode2UserInfo struct {
  178. Code string
  179. }
  180. func (x reqAuthCode2UserInfo) intoURLValues() url.Values {
  181. return url.Values{
  182. "code": {x.Code},
  183. }
  184. }
  185. // respAuthCode2UserInfo 获取访问用户身份响应
  186. type respAuthCode2UserInfo struct {
  187. respCommon
  188. AuthCodeUserInfo
  189. }
  190. // AuthCodeUserInfo 访问用户身份
  191. type AuthCodeUserInfo struct {
  192. UserID string `json:"userid,omitempty"`
  193. UserTicket string `json:"user_ticket,omitempty"`
  194. OpenID string `json:"openid,omitempty"`
  195. ExternalUserID string `json:"external_userid,omitempty"`
  196. }
  197. type reqOAGetTemplateDetail struct {
  198. TemplateID string `json:"template_id"`
  199. }
  200. func (x reqOAGetTemplateDetail) intoBody() ([]byte, error) {
  201. return marshalIntoJSONBody(x)
  202. }
  203. type respOAGetTemplateDetail struct {
  204. respCommon
  205. OATemplateDetail
  206. }
  207. type reqOAApplyEvent struct {
  208. OAApplyEvent
  209. }
  210. func (x reqOAApplyEvent) intoBody() ([]byte, error) {
  211. return marshalIntoJSONBody(x)
  212. }
  213. type respOAApplyEvent struct {
  214. respCommon
  215. // SpNo 表单提交成功后,返回的表单编号
  216. SpNo string `json:"sp_no"`
  217. }
  218. type reqOAGetApprovalInfo struct {
  219. StartTime string `json:"starttime"`
  220. EndTime string `json:"endtime"`
  221. Cursor int `json:"cursor"`
  222. Size uint32 `json:"size"`
  223. Filters []OAApprovalInfoFilter `json:"filters"`
  224. }
  225. func (x reqOAGetApprovalInfo) intoBody() ([]byte, error) {
  226. return marshalIntoJSONBody(x)
  227. }
  228. type respOAGetApprovalInfo struct {
  229. respCommon
  230. // SpNoList 审批单号列表,包含满足条件的审批申请
  231. SpNoList []string `json:"sp_no_list"`
  232. }
  233. type reqOAGetApprovalDetail struct {
  234. // SpNo 审批单编号。
  235. SpNo string `json:"sp_no"`
  236. }
  237. func (x reqOAGetApprovalDetail) intoBody() ([]byte, error) {
  238. return marshalIntoJSONBody(x)
  239. }
  240. type respOAGetApprovalDetail struct {
  241. respCommon
  242. // Info 审批申请详情
  243. Info OAApprovalDetail `json:"info"`
  244. }
  245. // TaskCardBtn 任务卡片消息按钮
  246. type TaskCardBtn struct {
  247. // Key 按钮key值,用户点击后,会产生任务卡片回调事件,回调事件会带上该key值,只能由数字、字母和“_-@”组成,最长支持128字节
  248. Key string `json:"key"`
  249. // Name 按钮名称
  250. Name string `json:"name"`
  251. // ReplaceName 点击按钮后显示的名称,默认为“已处理”
  252. ReplaceName string `json:"replace_name"`
  253. // Color 按钮字体颜色,可选“red”或者“blue”,默认为“blue”
  254. Color string `json:"color"`
  255. // IsBold 按钮字体是否加粗,默认false
  256. IsBold bool `json:"is_bold"`
  257. }
  258. // Article news 类型的文章
  259. type Article struct {
  260. // 标题,不超过128个字节,超过会自动截断(支持id转译)
  261. Title string `json:"title"`
  262. // 描述,不超过512个字节,超过会自动截断(支持id转译)
  263. Description string `json:"description"`
  264. // 点击后跳转的链接。 最长2048字节,请确保包含了协议头(http/https),小程序或者url必须填写一个
  265. URL string `json:"url"`
  266. // 图文消息的图片链接,最长2048字节,支持JPG、PNG格式,较好的效果为大图 1068*455,小图150*150
  267. PicURL string `json:"picurl"`
  268. // 小程序appid,必须是与当前应用关联的小程序,appid和pagepath必须同时填写,填写后会忽略url字段
  269. AppID string `json:"appid"`
  270. // 点击消息卡片后的小程序页面,最长128字节,仅限本小程序内的页面。appid和pagepath必须同时填写,填写后会忽略url字段
  271. PagePath string `json:"pagepath"`
  272. }
  273. // MPArticle mpnews 类型的文章
  274. type MPArticle struct {
  275. // 标题,不超过128个字节,超过会自动截断(支持id转译)
  276. Title string `json:"title"`
  277. // 图文消息缩略图的media_id, 可以通过素材管理接口获得。此处thumb_media_id即上传接口返回的media_id
  278. ThumbMediaID string `json:"thumb_media_id"`
  279. // 图文消息的作者,不超过64个字节
  280. Author string `json:"author"`
  281. // 图文消息点击“阅读原文”之后的页面链接
  282. ContentSourceURL string `json:"content_source_url"`
  283. // 图文消息的内容,支持html标签,不超过666 K个字节(支持id转译)
  284. Content string `json:"content"`
  285. // 图文消息的描述,不超过512个字节,超过会自动截断(支持id转译)
  286. Digest string `json:"digest"`
  287. }
  288. // Source 卡片来源样式信息,不需要来源样式可不填写
  289. type Source struct {
  290. // 来源图片的url,来源图片的尺寸建议为72*72
  291. IconURL string `json:"icon_url"`
  292. // 来源图片的描述,建议不超过20个字,(支持id转译)
  293. Desc string `json:"desc"`
  294. // 来源文字的颜色,目前支持:0(默认) 灰色,1 黑色,2 红色,3 绿色
  295. DescColor int `json:"desc_color"`
  296. }
  297. // ActionList 操作列表,列表长度取值范围为 [1, 3]
  298. type ActionList struct {
  299. // 操作的描述文案
  300. Text string `json:"text"`
  301. // 操作key值,用户点击后,会产生回调事件将本参数作为EventKey返回,回调事件会带上该key值,最长支持1024字节,不可重复
  302. Key string `json:"key"`
  303. }
  304. // ActionMenu 卡片右上角更多操作按钮
  305. type ActionMenu struct {
  306. // 更多操作界面的描述
  307. Desc string `json:"desc"`
  308. ActionList []ActionList `json:"action_list"`
  309. }
  310. // MainTitle 一级标题
  311. type MainTitle struct {
  312. // 一级标题,建议不超过36个字,文本通知型卡片本字段非必填,但不可本字段和sub_title_text都不填,(支持id转译)
  313. Title string `json:"title"`
  314. // 标题辅助信息,建议不超过160个字,(支持id转译)
  315. Desc string `json:"desc"`
  316. }
  317. // QuoteArea 引用文献样式
  318. type QuoteArea struct {
  319. // 引用文献样式区域点击事件,0或不填代表没有点击事件,1 代表跳转url,2 代表跳转小程序
  320. Type int `json:"type"`
  321. // 点击跳转的url,quote_area.type是1时必填
  322. URL string `json:"url"`
  323. // 引用文献样式的标题
  324. Title string `json:"title"`
  325. // 引用文献样式的引用文案
  326. QuoteText string `json:"quote_text"`
  327. // 小程序appid,必须是与当前应用关联的小程序,appid和pagepath必须同时填写,填写后会忽略url字段
  328. AppID string `json:"appid"`
  329. // 点击消息卡片后的小程序页面,最长128字节,仅限本小程序内的页面。appid和pagepath必须同时填写,填写后会忽略url字段
  330. PagePath string `json:"pagepath"`
  331. }
  332. // EmphasisContent 关键数据样式
  333. type EmphasisContent struct {
  334. // 关键数据样式的数据内容,建议不超过14个字
  335. Title string `json:"title"`
  336. // 关键数据样式的数据描述内容,建议不超过22个字
  337. Desc string `json:"desc"`
  338. }
  339. // HorizontalContentList 二级标题+文本列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6
  340. type HorizontalContentList struct {
  341. // 二级标题,建议不超过5个字
  342. KeyName string `json:"keyname"`
  343. // 二级文本,如果horizontal_content_list.type是2,该字段代表文件名称(要包含文件类型),建议不超过30个字,(支持id转译)
  344. Value string `json:"value"`
  345. // 链接类型,0或不填代表不是链接,1 代表跳转url,2 代表下载附件,3 代表点击跳转成员详情
  346. Type int `json:"type,omitempty"`
  347. // 链接跳转的url,horizontal_content_list.type是1时必填
  348. URL string `json:"url,omitempty"`
  349. // 附件的media_id,horizontal_content_list.type是2时必填
  350. MediaID string `json:"media_id,omitempty"`
  351. // 成员详情的userid,horizontal_content_list.type是3时必填
  352. Userid string `json:"userid,omitempty"`
  353. }
  354. // JumpList 跳转指引样式的列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过3
  355. type JumpList struct {
  356. // 跳转链接类型,0或不填代表不是链接,1 代表跳转url,2 代表跳转小程序
  357. Type int `json:"type"`
  358. // 跳转链接样式的文案内容,建议不超过18个字
  359. Title string `json:"title"`
  360. // 跳转链接的url,jump_list.type是1时必填
  361. URL string `json:"url,omitempty"`
  362. // 跳转链接的小程序的appid,必须是与当前应用关联的小程序,jump_list.type是2时必填
  363. Appid string `json:"appid,omitempty"`
  364. // 跳转链接的小程序的pagepath,jump_list.type是2时选填
  365. PagePath string `json:"pagepath,omitempty"`
  366. }
  367. // CardAction 整体卡片的点击跳转事件,text_notice必填本字段
  368. type CardAction struct {
  369. // 跳转事件类型,1 代表跳转url,2 代表打开小程序。text_notice卡片模版中该字段取值范围为[1,2]
  370. Type int `json:"type"`
  371. // 跳转事件的url,card_action.type是1时必填
  372. URL string `json:"url"`
  373. // 跳转事件的小程序的appid,必须是与当前应用关联的小程序,card_action.type是2时必填
  374. Appid string `json:"appid"`
  375. // 跳转事件的小程序的pagepath,card_action.type是2时选填
  376. Pagepath string `json:"pagepath"`
  377. }
  378. // ImageTextArea 左图右文样式,news_notice类型的卡片,card_image和image_text_area两者必填一个字段,不可都不填
  379. type ImageTextArea struct {
  380. // 左图右文样式区域点击事件,0或不填代表没有点击事件,1 代表跳转url,2 代表跳转小程序
  381. Type int `json:"type"`
  382. // 点击跳转的url,image_text_area.type是1时必填
  383. URL string `json:"url"`
  384. // 点击跳转的小程序的appid,必须是与当前应用关联的小程序,image_text_area.type是2时必填
  385. AppID string `json:"appid,omitempty"`
  386. // 点击跳转的小程序的pagepath,image_text_area.type是2时选填
  387. PagePath string `json:"pagepath,omitempty"`
  388. // 左图右文样式的标题
  389. Title string `json:"title"`
  390. // 左图右文样式的描述
  391. Desc string `json:"desc"`
  392. // 左图右文样式的图片url
  393. ImageURL string `json:"image_url"`
  394. }
  395. // CardImage 图片样式,news_notice类型的卡片,card_image和image_text_area两者必填一个字段,不可都不填
  396. type CardImage struct {
  397. // 图片的url
  398. URL string `json:"url"`
  399. // 图片的宽高比,宽高比要小于2.25,大于1.3,不填该参数默认1.3
  400. AspectRatio float32 `json:"aspect_ratio"`
  401. }
  402. // ButtonSelection 按钮交互型
  403. type ButtonSelection struct {
  404. // 下拉式的选择器的key,用户提交选项后,会产生回调事件,回调事件会带上该key值表示该题,最长支持1024字节
  405. QuestionKey string `json:"question_key"`
  406. // 下拉式的选择器的key,用户提交选项后,会产生回调事件,回调事件会带上该key值表示该题,最长支持1024字节
  407. Title string `json:"title"`
  408. // 选项列表,下拉选项不超过 10 个,最少1个
  409. OptionList []struct {
  410. // 下拉式的选择器选项的id,用户提交后,会产生回调事件,回调事件会带上该id值表示该选项,最长支持128字节,不可重复
  411. ID string `json:"id"`
  412. // 下拉式的选择器选项的文案,建议不超过16个字
  413. Text string `json:"text"`
  414. } `json:"option_list"`
  415. // 默认选定的id,不填或错填默认第一个
  416. SelectedID string `json:"selected_id"`
  417. }
  418. type Button struct {
  419. // 按钮点击事件类型,0 或不填代表回调点击事件,1 代表跳转url
  420. Type int `json:"type,omitempty"`
  421. // 按钮文案,建议不超过10个字
  422. Text string `json:"text"`
  423. // 按钮样式,目前可填1~4,不填或错填默认1
  424. Style int `json:"style,omitempty"`
  425. // 按钮key值,用户点击后,会产生回调事件将本参数作为EventKey返回,回调事件会带上该key值,最长支持1024字节,不可重复,button_list.type是0时必填
  426. Key string `json:"key,omitempty"`
  427. // 跳转事件的url,button_list.type是1时必填
  428. URL string `json:"url,omitempty"`
  429. }
  430. // CheckBox 选择题样式
  431. type CheckBox struct {
  432. // 选择题key值,用户提交选项后,会产生回调事件,回调事件会带上该key值表示该题,最长支持1024字节
  433. QuestionKey string `json:"question_key"`
  434. // 选项list,选项个数不超过 20 个,最少1个
  435. OptionList []struct {
  436. // 选项id,用户提交选项后,会产生回调事件,回调事件会带上该id值表示该选项,最长支持128字节,不可重复
  437. ID string `json:"id"`
  438. // 选项文案描述,建议不超过17个字
  439. Text string `json:"text"`
  440. // 该选项是否要默认选中
  441. IsChecked bool `json:"is_checked"`
  442. } `json:"option_list" validate:"required,min=1,max=20"`
  443. // 选择题模式,单选:0,多选:1,不填默认0
  444. Mode int `json:"mode" validate:"omitempty,oneof=0 1"`
  445. }
  446. // SubmitButton 提交按钮样式
  447. type SubmitButton struct {
  448. // 按钮文案,建议不超过10个字,不填默认为提交
  449. Text string `json:"text"`
  450. // 提交按钮的key,会产生回调事件将本参数作为EventKey返回,最长支持1024字节
  451. Key string `json:"key"`
  452. }
  453. // SelectList 下拉式的选择器列表,multiple_interaction类型的卡片该字段不可为空,一个消息最多支持 3 个选择器
  454. type SelectList struct {
  455. // 下拉式的选择器题目的key,用户提交选项后,会产生回调事件,回调事件会带上该key值表示该题,最长支持1024字节,不可重复
  456. QuestionKey string `json:"question_key"`
  457. // 下拉式的选择器上面的title
  458. Title string `json:"title,omitempty"`
  459. // 默认选定的id,不填或错填默认第一个
  460. SelectedID string `json:"selected_id,omitempty"`
  461. OptionList []OptionList `json:"option_list"`
  462. }
  463. // 项列表,下拉选项不超过 10 个,最少1个
  464. type OptionList struct {
  465. // 下拉式的选择器选项的id,用户提交选项后,会产生回调事件,回调事件会带上该id值表示该选项,最长支持128字节,不可重复
  466. ID string `json:"id"`
  467. // 下拉式的选择器选项的文案,建议不超过16个字
  468. Text string `json:"text"`
  469. }
  470. // TemplateCardType 模板卡片的类型
  471. type TemplateCardType string
  472. const (
  473. CardTypeTextNotice TemplateCardType = "text_notice" // 文本通知型
  474. CardTypeNewsNotice TemplateCardType = "news_notice" // 图文展示型
  475. CardTypeButtonInteraction TemplateCardType = "button_interaction" // 按钮交互型
  476. CardTypeVoteInteraction TemplateCardType = "vote_interaction" // 投票选择型
  477. CardTypeMultipleInteraction TemplateCardType = "multiple_interaction" // 多项选择型
  478. )
  479. type TemplateCard struct {
  480. CardType TemplateCardType `json:"card_type"`
  481. Source Source `json:"source"`
  482. ActionMenu *ActionMenu `json:"action_menu,omitempty" validate:"required_with=TaskID"`
  483. TaskID string `json:"task_id,omitempty" validate:"required_with=ActionMenu"`
  484. MainTitle *MainTitle `json:"main_title"`
  485. QuoteArea *QuoteArea `json:"quote_area,omitempty"`
  486. // 文本通知型
  487. EmphasisContent *EmphasisContent `json:"emphasis_content,omitempty"`
  488. SubTitleText string `json:"sub_title_text,omitempty"`
  489. // 图文展示型
  490. ImageTextArea *ImageTextArea `json:"image_text_area,omitempty"`
  491. CardImage *CardImage `json:"card_image,omitempty"`
  492. HorizontalContentList []HorizontalContentList `json:"horizontal_content_list"`
  493. JumpList []JumpList `json:"jump_list"`
  494. CardAction *CardAction `json:"card_action,omitempty"`
  495. // 按钮交互型
  496. ButtonSelection *ButtonSelection `json:"button_selection,omitempty"`
  497. ButtonList []Button `json:"button_list,omitempty" validate:"omitempty,max=6"`
  498. // 投票选择型
  499. CheckBox *CheckBox `json:"checkbox,omitempty"`
  500. SelectList []SelectList `json:"select_list,omitempty" validate:"max=3"`
  501. SubmitButton *SubmitButton `json:"submit_button,omitempty"`
  502. }
  503. type TemplateCardUpdateMessage struct {
  504. UserIds []string `json:"userids" validate:"omitempty,max=100"`
  505. PartyIds []int64 `json:"partyids" validate:"omitempty,max=100"`
  506. TagIds []int32 `json:"tagids" validate:"omitempty,max=100"`
  507. AtAll int `json:"atall,omitempty"`
  508. ResponseCode string `json:"response_code"`
  509. Button struct {
  510. ReplaceName string `json:"replace_name"`
  511. } `json:"button" validate:"required_without=TemplateCard"`
  512. TemplateCard TemplateCard `json:"template_card" validate:"required_without=Button"`
  513. ReplaceText string `json:"replace_text,omitempty"`
  514. }