跳转至

CalendarAPIController(日历管理 API)

用户中心模块的工作日历域 CRUD/查询控制器,提供日历(含标准日/特殊日集合)的创建、更新、查找、删除,按名称/域查询、按域列表、按搜索参数分页、按名称计数、保存基本信息(saveCalendar)、按域+名称分页搜索等能力。该控制器由 obpm-runtimeobpm-managerobpm-kms 等宿主服务以 Feign 方式内部调用(CalendarAPI 接口),属于后端服务间数据面接口。

  • 控制器全限定名cn.myapps.usercenter.controller.CalendarAPIController
  • 接口(Feign 契约)cn.myapps.usercenter.controller.CalendarAPI
  • Tag:日历管理
  • 类级 @RequestMapping${myapps.context-path.usercenter:}/calendar
  • 基址<host>/usercenter/calendar
  • 独立部署(obpm-usercenter-war/obpm-usercenter-consul):server.servlet.context-path=/usercenter,占位符 ${myapps.context-path.usercenter:} 缺省为空,故实际基址为 <host>:<port>/usercenter/calendar(war 端口 8080,consul 端口 8088)。
  • 统一部署(obpm-lite):server.servlet.context-path=/,yml 显式配置 myapps.context-path.usercenter=/usercenter,故实际基址同样为 <host>:8888/usercenter/calendar
  • 接口类型:REST 资源

公共说明

鉴权

(据源码)usercenter 模块本身**不定义**任何安全过滤器或鉴权拦截器,仅注册 PersistenceHandlerInterceptor(用于 DAO 资源清理——事务提交与 Hibernate Session 关闭,不做权限判断)。本控制器 /calendar/** 路径下所有端点**不做用户级身份校验**——既不读取 accessToken,也不读取 adminToken/designerToken,控制器方法内也不调用任何 getUser() 之类方法。

usercenter 作为共享库被宿主服务加载后,会继承 obpm-common 提供的 CommonSecurityFilter(由 CommWebMvcConfig@Bean 注册,URL 模式 /*,order=-1,详见 index.md「鉴权说明」),对 /calendar/** 的影响仅限:

  • HTTP 方法限制:未携带合法 systemToken 请求头时,仅允许 GET/POST/HEAD/OPTIONS 方法;直接发起 PUT/DELETE/PATCH 等请求会被 CommonSecurityFilter 以 HTTP 405(HTML 错误页,无 JSON 体)拒绝。
  • systemToken 放行:携带合法 systemToken 请求头(系统间 Feign 调用,JWT 内 username 固定为 systemToken)的请求被标记 pass=true 并绕过上述方法限制——这是本控制器 PUT /updatePUT /saveCalendarDELETE /remove/{id} 在生产中正常工作的前提。

结论:本控制器的真实访问控制依赖**网络层隔离**(仅由可信的内部服务经 Feign 调用,附 systemToken 请求头),并非用户令牌。终端用户不应直接访问这些端点。

响应结构

本控制器不使用统一 Resource 结构(与 ../index.md「统一响应结构」不同)。响应遵循以下规则:

情形 HTTP 状态 响应体
返回值为 void 的方法(创建/更新/删除/保存基本信息)成功 200 空响应体
返回值为领域对象/集合/包装类型的方法成功 200 直接序列化的对象 JSON(如 CalendarPOCollection<CalendarPO>DataPackage<CalendarPO>int),不包裹 errcode/errmsg/data/errors
业务/系统异常 500 {"errcode":500,"errmsg":"<异常信息>"}(由 obpm-common 的 CommonsExceptionResolver 全局异常处理器渲染,仅含 errcode/errmsg 两字段,无 data/errors
HTTP 方法不被允许(无 systemTokenPUT/DELETE 405 HTML 错误页(由 CommonSecurityFilter 直接返回)
系统启动中 500 HTML 错误页(由 CommonSecurityFilter 直接返回)

数据模型:CalendarPO

返回的 CalendarPO 继承自 AuthtimeValueObject,表示一个工作日历。主要字段:idname(日历名称,@NotEmpty)、type(日历类型)、remark(备注)、workingTime(工作时间)、fromCalendarId(来源日历 ID,用于复制场景)、lastModifyDate(最后修改时间)、standardDays(常规日集合 Set<StandardDayPO>,描述每周各工作日的工作时段)、specialDays(特例日集合 Set<SpecialDayPO>,描述特定日期的安排)。StandardDayPO/SpecialDayPO 通过 calendar 字段反向引用所属 CalendarPO——find 端点在返回前会显式将集合内每个 day.calendar 置为 null 以避免 Jackson 循环依赖。

分页结构:DataPackage<CalendarPO>

doQueryListBySearch(POST 与 GET 两个重载)返回 cn.myapps.common.data.DataPackage<CalendarPO>,标准字段为 datas(当前页数据集合)、rowCount(总行数)、pageNo(当前页码)、linesPerPage(每页行数)等。

路径与方法约定

本控制器存在两条 /doQueryList 同路径端点(HTTP 方法不同):GET /doQueryList/{domainId}(按域列表)与 POST /doQueryList(按 ParamsTable 搜索参数分页)。亦存在两条 doQueryListBySearch 方法:POST 版本以请求体 ParamsTable 提交搜索条件;GET 版本(路径 /doQueryListBySearch/{domainId})以 query 参数 sm_name/order 提交关键字与排序。


1. 创建日历

创建新的日历记录。事务保护:失败回滚。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/create(完整:<host>/usercenter/calendar/create
  • 鉴权:内部(建议经 systemToken 的 Feign 调用;直接调用因 POST 方法不被 CommonSecurityFilter 拦截故技术上无需 token,但本控制器为内部数据面接口)
  • Tag:日历管理

请求参数

参数名 位置 类型 必填 说明
body body CalendarPO 日历信息,至少包含 name@NotEmpty);可携带 typeremarkworkingTimestandardDaysspecialDays

请求示例

POST /usercenter/calendar/create HTTP/1.1
Content-Type: application/json
systemToken: <系统间 JWT>

{
  "name": "总部工作日历",
  "type": "standard",
  "workingTime": 480,
  "remark": "周一至周五 9:00-17:00"
}

响应

结构:成功为**空响应体**(返回类型 void);失败为 {"errcode":500,"errmsg":"<异常信息>"},HTTP 500。

成功示例:(HTTP 200,空响应体)

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }

2. 更新日历

根据提供的信息更新日历。事务保护:失败回滚。

  • 接口类型:REST 资源
  • 请求方式PUT
  • 请求路径/update(完整:<host>/usercenter/calendar/update
  • 鉴权:内部(PUT 方法需携带合法 systemToken 请求头,否则被 CommonSecurityFilter 以 HTTP 405 拒绝)
  • Tag:日历管理

请求参数

参数名 位置 类型 必填 说明
body body CalendarPO 待更新日历(须含主键 id),可携带需更新的字段

请求示例

PUT /usercenter/calendar/update HTTP/1.1
Content-Type: application/json
systemToken: <系统间 JWT>

{
  "id": "__CAL001",
  "name": "总部工作日历-new",
  "remark": "调整后时段"
}

响应

结构:成功为**空响应体**(返回类型 void);失败为 {"errcode":500,"errmsg":"<异常信息>"},HTTP 500。若未带 systemToken,HTTP 405(HTML 错误页)。

成功示例:(HTTP 200,空响应体)

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }

3. 根据 ID 查找日历

根据日历 ID 查找日历详情(含常规日集合与特例日集合,集合内反向外键被置空以避免循环依赖)。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/find/{id}(完整:<host>/usercenter/calendar/find/{id}
  • 鉴权:内部
  • Tag:日历管理

请求参数

参数名 位置 类型 必填 说明
id path string 日历 ID

请求示例

GET /usercenter/calendar/find/__CAL001 HTTP/1.1
systemToken: <系统间 JWT>

响应

结构:成功为 CalendarPO 对象 JSON(不包裹 Resource);未找到时由 DAO 行为决定(通常返回 null 或抛异常进入 CommonsExceptionResolver)。

成功示例

{
  "id": "__CAL001",
  "name": "总部工作日历",
  "type": "standard",
  "workingTime": 480,
  "remark": "周一至周五 9:00-17:00",
  "standardDays": [
    { "id": "__SD001", "weekDays": 1, "workingDayStatus": "01", "calendar": null }
  ],
  "specialDays": [
    { "id": "__SP001", "calendar": null }
  ]
}

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }

4. 根据 ID 删除日历

根据日历 ID 删除日历。事务保护:失败回滚。

  • 接口类型:REST 资源
  • 请求方式DELETE
  • 请求路径/remove/{id}(完整:<host>/usercenter/calendar/remove/{id}
  • 鉴权:内部(DELETE 方法需携带合法 systemToken 请求头,否则被 CommonSecurityFilter 以 HTTP 405 拒绝)
  • Tag:日历管理

请求参数

参数名 位置 类型 必填 说明
id path string 日历 ID

请求示例

DELETE /usercenter/calendar/remove/__CAL001 HTTP/1.1
systemToken: <系统间 JWT>

响应

结构:成功为**空响应体**(返回类型 void);失败为 {"errcode":500,"errmsg":"<异常信息>"},HTTP 500。若未带 systemToken,HTTP 405(HTML 错误页)。

成功示例:(HTTP 200,空响应体)

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }

5. 按名称查询日历

根据日历名称和域 ID 查询单个日历。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/doViewByName/{domainId}(完整:<host>/usercenter/calendar/doViewByName/{domainId}
  • 鉴权:内部
  • Tag:日历管理

请求参数

参数名 位置 类型 必填 说明
domainId path string 域 ID
name query string 日历名称

请求示例

GET /usercenter/calendar/doViewByName/__DMN001?name=总部工作日历 HTTP/1.1
systemToken: <系统间 JWT>

响应

结构:成功为 CalendarPO 对象 JSON(不包裹 Resource);未找到时由 DAO 行为决定。

成功示例

{
  "id": "__CAL001",
  "name": "总部工作日历",
  "domain": { "id": "__DMN001" }
}

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }

6. 根据域 ID 查询日历列表

根据域 ID 查询该域下的全部日历列表。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/doQueryList/{domainId}(完整:<host>/usercenter/calendar/doQueryList/{domainId}
  • 鉴权:内部
  • Tag:日历管理

请求参数

参数名 位置 类型 必填 说明
domainId path string 域 ID

请求示例

GET /usercenter/calendar/doQueryList/__DMN001 HTTP/1.1
systemToken: <系统间 JWT>

响应

结构:成功为 Collection<CalendarPO> JSON 数组(不包裹 Resource)。

成功示例

[
  { "id": "__CAL001", "name": "总部工作日历", "type": "standard" }
]

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }

7. 按搜索参数分页查询日历

根据 ParamsTable 搜索参数分页查询日历列表。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/doQueryList(完整:<host>/usercenter/calendar/doQueryList
  • 鉴权:内部
  • Tag:日历管理

注:此端点与端点 6 同路径但 HTTP 方法不同(POST 走搜索分页、GET 走按域列表)。

请求参数

参数名 位置 类型 必填 说明
params body ParamsTable 搜索参数映射(透传至 DAO,可包含 _domain_name 等条件键)
page query int 页码(1 起)
lines query int 每页条数

请求示例

POST /usercenter/calendar/doQueryList?page=1&lines=20 HTTP/1.1
Content-Type: application/json
systemToken: <系统间 JWT>

{ "_domain": "__DMN001", "_name": "总部" }

响应

结构:成功为 DataPackage<CalendarPO> 对象 JSON(不包裹 Resource),含 datasrowCountpageNolinesPerPage 等字段。

成功示例

{
  "datas": [
    { "id": "__CAL001", "name": "总部工作日历" }
  ],
  "rowCount": 1,
  "pageNo": 1,
  "linesPerPage": 20
}

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }

8. 按名称查询日历数量

根据日历名称和域 ID 统计匹配的日历数量(用于重名校验等场景)。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/queryCountByName/{domainId}(完整:<host>/usercenter/calendar/queryCountByName/{domainId}
  • 鉴权:内部
  • Tag:日历管理

请求参数

参数名 位置 类型 必填 说明
domainId path string 域 ID
name query string 日历名称

请求示例

GET /usercenter/calendar/queryCountByName/__DMN001?name=总部工作日历 HTTP/1.1
systemToken: <系统间 JWT>

响应

结构:成功为 int(裸数字,不包裹 Resource)。

成功示例

1

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }

9. 保存日历基本信息

按主键更新日历的名称与备注(仅这两项;不修改 standardDays/specialDays 等关联集合)。事务保护:失败回滚。

  • 接口类型:REST 资源
  • 请求方式PUT
  • 请求路径/saveCalendar(完整:<host>/usercenter/calendar/saveCalendar
  • 鉴权:内部(PUT 方法需携带合法 systemToken 请求头,否则被 CommonSecurityFilter 以 HTTP 405 拒绝)
  • Tag:日历管理

请求参数

参数名 位置 类型 必填 说明
id query string 日历 ID
name query string 日历名称
remark query string 备注(required=false,缺省不修改或由 DAO 决定)

请求示例

PUT /usercenter/calendar/saveCalendar?id=__CAL001&name=总部工作日历-new&remark=调整后 HTTP/1.1
systemToken: <系统间 JWT>

响应

结构:成功为**空响应体**(返回类型 void);失败为 {"errcode":500,"errmsg":"<异常信息>"},HTTP 500。若未带 systemToken,HTTP 405(HTML 错误页)。

成功示例:(HTTP 200,空响应体)

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }

10. 按域和名称搜索日历(GET 分页)

根据域 ID 和日历名称(sm_name)分页搜索日历,支持排序。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/doQueryListBySearch/{domainId}(完整:<host>/usercenter/calendar/doQueryListBySearch/{domainId}
  • 鉴权:内部
  • Tag:日历管理

请求参数

参数名 位置 类型 必填 说明
domainId path string 域 ID(路径模式包含 {domainId} 占位,URL 中必须提供该段)
domainId query string 域 ID(源码同时声明为 @RequestParam——即查询条件实际取自 query 参数,与路径占位同名,调用时需两处都传同一值)
sm_name query string 日历名称关键字(参数名 sm_name 为源码原始命名,前缀 sm_ 表「搜索-名称」)
order query string 排序方式
page query int 页码(1 起)
lines query int 每页条数

注:源码此端点的路径模板声明了 {domainId} 占位(仅用于 URL 匹配),而方法参数却以 @RequestParam 接收(实际绑定值取自 query),二者同名但属历史遗留。实际调用建议在 URL 路径段与 query 上同时传 domainId 以确保命中。

请求示例

GET /usercenter/calendar/doQueryListBySearch/__DMN001?domainId=__DMN001&sm_name=总部&order=asc&page=1&lines=20 HTTP/1.1
systemToken: <系统间 JWT>

响应

结构:成功为 DataPackage<CalendarPO> 对象 JSON(不包裹 Resource),含 datasrowCountpageNolinesPerPage 等字段。

成功示例

{
  "datas": [
    { "id": "__CAL001", "name": "总部工作日历" }
  ],
  "rowCount": 1,
  "pageNo": 1,
  "linesPerPage": 20
}

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }

11. 按名称和域查询日历

根据日历名称和域 ID 分页查询日历集合(仅返回当前页数据,不带分页元数据)。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/queryByNameAndDomain/{domainId}(完整:<host>/usercenter/calendar/queryByNameAndDomain/{domainId}
  • 鉴权:内部
  • Tag:日历管理

请求参数

参数名 位置 类型 必填 说明
domainId path string 域 ID
name query string 日历名称
page query int 页码(1 起)
lines query int 每页条数

请求示例

GET /usercenter/calendar/queryByNameAndDomain/__DMN001?name=总部&page=1&lines=20 HTTP/1.1
systemToken: <系统间 JWT>

响应

结构:成功为 Collection<CalendarPO> JSON 数组(当前页数据不包裹 Resource;返回类型非 DataPackage,故不带分页元数据)。

成功示例

[
  { "id": "__CAL001", "name": "总部工作日历", "domain": { "id": "__DMN001" } }
]

失败示例

{ "errcode": 500, "errmsg": "<异常信息>" }