DepartmentAuthtimeController(部门管理)¶
管理企业域下的部门组织架构:查询顶级 / 下级 / 单条部门;分页列表(按名称、上级、状态、排序、自定义扩展字段过滤);部门的创建、更新、批量删除;按钉钉部门 id 反查;按 Excel 文件批量导入部门。
- 类级基址:
${myapps.context-path.manager:}/api/authtime(完整路径:{manager-context}/api/authtime<相对路径>) - Tag:部门模块(控制器源码声明
@Tag(name = "部门模块")) - 控制器源码:
obpm-manager/src/main/java/cn/myapps/manager/authtime/controller/department/DepartmentAuthtimeController.java - 公共说明:
- 类继承
BaseAuthTimeController,通过其success(errmsg, data)/error(errcode, errmsg, errors)返回统一Resource(字段errcode/errmsg/data/errors,结构见 ../index.md「统一响应结构」)。 - 多数端点在
try/catch内捕获Exception并e.printStackTrace()后返回errcode=500、errmsg=e.getMessage()、data=null;业务校验失败常用errcode=4001(部门不存在 / 部门名重复 / 部门名非法 / 上级部门循环引用等)。OBPMValidateException单独捕获并以其校验提示作为errmsg。 - 控制器以
@ResponseStatus显式声明 HTTP 状态码:查询端点200 OK,创建端点201 CREATED,更新 / 删除 / 列表 / 导入200 OK。 - 鉴权说明见 index.md「鉴权说明」(adminToken JWT)。
- 路径变量:
domainid/domainId为企业域 id;id为部门 id(路径声明,用于查询 / 更新 / 钉钉反查);departmentid为部门 id(用于查下级);{id}/{domainid}组合用于「通过钉钉部门 id 反查」(此处的id为钉钉部门 id)。 - 部门序列化字段:
DepartmentVO包含id/name/level/valid/superior/domain/code/fieldExtends等。下级部门列表序列化时过滤superior/domain/lastModifyTime字段,并补充leaf布尔字段标记是否为叶子部门。
1. 获取顶级部门¶
按企业域 id 查询该域的顶级部门(根部门)对象。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/domain/{domainid}/department/root(完整:{manager-context}/api/authtime/domain/{domainid}/department/root) - 鉴权:是(需管理员 adminToken,详见 index.md「鉴权说明」)
- Tag:部门模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
请求示例¶
响应¶
结构:统一 Resource(见 ../index.md「统一响应结构」)。
data:DepartmentVO(顶级部门对象,含 superior/domain/lastModifyTime 等字段)。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": { "id": "__DEPT_ROOT", "name": "组织架构", "level": 0, "valid": 1 },
"errors": null
}
2. 获取下级部门¶
按部门 id 查询其直属下级部门列表,支持按 valid 状态过滤;按当前管理员的部门权限做可见性裁剪——管理员无部门权限时返回全部下级;有部门权限时只返回管理员部门集合及其下级。每个返回节点附加 leaf 字段(无下级时为 true)。序列化时过滤 superior/domain/lastModifyTime。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/domain/{domainid}/department/{departmentid}/subdepartments(完整:{manager-context}/api/authtime/domain/{domainid}/department/{departmentid}/subdepartments) - 鉴权:是
- Tag:部门模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id(路径变量,方法签名持有但实际逻辑未直接使用) |
| departmentid | path | string | 是 | 部门 id |
| valid | query | int | 否 | 状态过滤(1=有效,0=失效),不传则不过滤 |
请求示例¶
响应¶
结构:统一 Resource。
data:Collection<JSONObject>,元素字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | string | 部门 id |
| name | string | 部门名称 |
| level | int | 部门层级 |
| valid | int | 状态(1=有效,0=失效) |
| code | string | 部门编码 |
| leaf | boolean | 是否叶子部门(无下级为 true) |
| 其他 | — | DepartmentVO 中除 superior/domain/lastModifyTime 外的字段 |
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": [
{ "id": "__DEPT02", "name": "研发部", "level": 2, "valid": 1, "code": "RD", "leaf": true }
],
"errors": null
}
3. 获取指定部门¶
按部门 id 查询部门详情。部门不存在时返回 errcode=4001。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/department/{id}(完整:{manager-context}/api/authtime/department/{id}) - 鉴权:是
- Tag:部门模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| id | path | string | 是 | 部门 id |
请求示例¶
响应¶
结构:统一 Resource。
data:DepartmentVO(含 superior/domain 等关联对象)。
| 条件 | errcode | errmsg | data |
|---|---|---|---|
| 部门不存在 | 4001 | 部门不存在 |
null |
| 成功 | 0 | ok | DepartmentVO |
注:方法签名
throws Exception,未捕获doView抛出的异常,命中异常分支时由 Spring 默认异常处理(HTTP 500,无统一Resource体)。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": { "id": "__DEPT01", "name": "研发部", "level": 2, "valid": 1 },
"errors": null
}
4. 创建部门¶
在指定企业域下创建部门。校验:父部门下同名部门不可重复、部门名称非空、部门名称长度 2~50。父部门 id 为空时层级为 0;否则层级为父部门层级 +1。响应 HTTP 状态码 201。
- 接口类型:REST 资源
- 请求方式:
POST - 请求路径:
/domain/{domainid}/department(完整:{manager-context}/api/authtime/domain/{domainid}/department) - 鉴权:是
- Tag:部门模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id(写入部门的 domain 关联) |
| content | body | JSON | 是 | DepartmentVO 序列化字段(见下) |
请求体¶
JSON 对象(application/json),关键字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 是 | 部门名称(长度 2~50,不能为空) |
| superiorid | string | 否 | 上级部门 id(提供时会校验父部门下同名部门不重复,并设置 level=父 level+1;不提供时 level=0) |
| code | string | 否 | 部门编码 |
| valid | int | 否 | 状态(1=有效,0=失效) |
| 其他 | — | 否 | DepartmentVO 其他持久化字段(扩展字段等) |
注:源码会强制
applicationid="",即部门不绑定具体软件。
请求示例¶
POST /api/authtime/domain/__P1UD2yVWpnFpUedONr/department HTTP/1.1
Content-Type: application/json
{ "name": "研发部", "superiorid": "__DEPT01", "code": "RD", "valid": 1 }
响应¶
结构:统一 Resource。
data:DepartmentVO(新建并持久化后的对象,含生成的 id)。
| 条件 | errcode | errmsg | data |
|---|---|---|---|
| 父部门下同名部门已存在 | 4001 | {*[core.department.exist]*} |
null |
| 部门名称为空 | 4001 | {*[core.department.name.illegal]*} |
null |
| 部门名称长度非法 | 4001 | {*[core.name.regex.illegal]*} |
null |
| 业务校验异常 | 500 | <异常信息> 或 OBPMValidateException 校验提示 |
null |
| 成功 | 0 | 保存成功 |
新建 DepartmentVO(HTTP 201) |
成功示例:
{
"errcode": 0,
"errmsg": "保存成功",
"data": { "id": "__NEWDEPT001", "name": "研发部", "level": 2, "valid": 1 },
"errors": null
}
5. 更新部门¶
按部门 id 更新部门信息。校验:上级部门不能为自己的下级(避免循环引用)、部门名称非空与长度 2~50、同名部门重名校验、把部门设为失效前若其下存在以该部门为默认部门的用户则报错、同步刷新直属下级的 level。
- 接口类型:REST 资源
- 请求方式:
PUT - 请求路径:
/domain/{domainid}/department/{id}(完整:{manager-context}/api/authtime/domain/{domainid}/department/{id}) - 鉴权:是
- Tag:部门模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id(写入部门的 domain 关联) |
| id | path | string | 是 | 待更新的部门 id |
| content | body | JSON | 是 | DepartmentVO 序列化字段(见下) |
请求体¶
JSON 对象(application/json),关键字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 是 | 部门名称(长度 2~50,不能为空) |
| superiorid | string | 否 | 新的上级部门 id(提供时会校验不能为当前部门的下级) |
| valid | int | 否 | 状态(设为 0=失效时若存在以该部门为默认部门的用户则报错) |
| code | string | 否 | 部门编码 |
| 其他 | — | 否 | DepartmentVO 其他持久化字段 |
请求示例¶
PUT /api/authtime/domain/__P1UD2yVWpnFpUedONr/department/__DEPT02 HTTP/1.1
Content-Type: application/json
{ "name": "研发一部", "superiorid": "__DEPT01", "valid": 1 }
响应¶
结构:统一 Resource。
data:DepartmentVO(更新后的对象)。
| 条件 | errcode | errmsg | data |
|---|---|---|---|
| 上级部门为自己的下级 | 4001 | 上级部门不能为自己的下级部门 |
null |
| 部门名称为空 | 4001 | {*[core.department.name.illegal]*} |
null |
| 部门名称长度非法 | 4001 | {*[core.name.regex.illegal]*} |
null |
| 部门下存在用户设为默认部门,不可失效 | 500 | 部门下存在用户,不能设为失效! 或 该部门下(...)已设置该部门为默认部门... |
null |
| 同级下同名部门已存在 | 4001 | {*[cn.myapps.core.domain.department.exist]*} |
null |
| 业务校验异常 | 500 | <异常信息> 或 OBPMValidateException 校验提示 |
null |
| 成功 | 0 | 保存成功 |
更新后的 DepartmentVO |
成功示例:
{
"errcode": 0,
"errmsg": "保存成功",
"data": { "id": "__DEPT02", "name": "研发一部", "level": 2, "valid": 1 },
"errors": null
}
6. 获取部门列表¶
按企业域分页查询部门列表,支持按部门名称(name,body 内)、上级部门(superiorid,query 内)、状态(valid)、排序(orderby)、自定义扩展字段(fieldExtends)过滤。
- 接口类型:REST 资源
- 请求方式:
POST - 请求路径:
/domain/{domainid}/departments(完整:{manager-context}/api/authtime/domain/{domainid}/departments) - 鉴权:是
- Tag:部门模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| content | body | JSON | 是 | 过滤包体(字段见下) |
| valid | query | int | 否 | 状态过滤(1=有效,0=失效) |
| currpage | query | string | 否 | 当前页码,缺省 1 |
| pagelines | query | string | 否 | 每页条数,缺省 10 |
| superiorid | query | string | 否 | 上级部门 id |
| orderby | query | string | 否 | 排序字段 |
请求体¶
JSON 对象(application/json):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 否 | 部门名称(模糊匹配) |
| fieldExtends | object | 否 | 自定义字段扩展过滤(键值对 Map) |
请求示例¶
POST /api/authtime/domain/__P1UD2yVWpnFpUedONr/departments?currpage=1&pagelines=20&valid=1 HTTP/1.1
Content-Type: application/json
{ "name": "研发", "fieldExtends": {} }
响应¶
结构:统一 Resource。
data:DataPackage<DepartmentVO>,字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| linesPerPage | int | 每页条数 |
| pageCount | int | 总页数 |
| pageNo | int | 当前页码 |
| rowCount | int | 总记录数 |
| datas | array\<DepartmentVO> | 部门数组 |
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": {
"linesPerPage": 20,
"pageCount": 1,
"pageNo": 1,
"rowCount": 1,
"datas": [ { "id": "__DEPT02", "name": "研发部", "level": 2, "valid": 1 } ]
},
"errors": null
}
7. 删除部门¶
按部门 id 数组批量删除部门(物理删除,doRemove)。
- 接口类型:REST 资源
- 请求方式:
DELETE - 请求路径:
/domain/{domainId}/department(完整:{manager-context}/api/authtime/domain/{domainId}/department) - 鉴权:是
- Tag:部门模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainId | path | string | 是 | 企业域 id(路径变量,方法签名持有但实际逻辑未直接使用) |
| ids | body | string[] | 是 | 待删除的部门 id 数组 |
请求体¶
application/json,字符串数组:
请求示例¶
DELETE /api/authtime/domain/__P1UD2yVWpnFpUedONr/department HTTP/1.1
Content-Type: application/json
[ "__DEPT02" ]
响应¶
结构:统一 Resource。
data:字符串 "删除成功"。
成功示例:
失败示例:8. 通过钉钉部门id和企业域id获取指定部门¶
按钉钉部门 id + 企业域 id 反查映射到本平台的部门。命中为空时返回 errcode=4001,命中多条时返回**第一条**。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/dingding/department/{id}/{domainid}(完整:{manager-context}/api/authtime/dingding/department/{id}/{domainid}) - 鉴权:是
- Tag:部门模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| id | path | string | 是 | 钉钉部门 id |
| domainid | path | string | 是 | 企业域 id |
请求示例¶
响应¶
结构:统一 Resource。
data:DepartmentVO。
| 条件 | errcode | errmsg | data |
|---|---|---|---|
| 未找到对应部门 | 4001 | 部门不存在 |
null |
| 成功 | 0 | ok | DepartmentVO |
注:方法签名
throws Exception,未捕获doQueryByDomainAndDingdingDept抛出的异常,命中异常分支时由 Spring 默认异常处理(HTTP 500,无统一Resource体)。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": { "id": "__DEPT02", "name": "研发部", "level": 2, "valid": 1 },
"errors": null
}
9. 部门导入¶
按上传 Excel 文件路径,把部门批量导入指定企业域。文件扩展名必须为 .xls / .xlsx,否则返回 errcode=4001。
- 接口类型:REST 资源
- 请求方式:
POST - 请求路径:
/domain/{domainid}/department/import(完整:{manager-context}/api/authtime/domain/{domainid}/department/import) - 鉴权:是
- Tag:部门模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| path | query | string | 是 | 上传 Excel 文件的相对路径(相对于 web 根,经 Environment.getRealPath 解析 + SecurityFile.resolveFile 安全校验) |
请求示例¶
POST /api/authtime/domain/__P1UD2yVWpnFpUedONr/department/import?path=/uploads/import/departments.xlsx HTTP/1.1
响应¶
结构:统一 Resource。
data:List<String>(导入结果字符串列表,元素内容取决于导入逻辑,通常含每行成功 / 失败描述)。
| 条件 | errcode | errmsg | data |
|---|---|---|---|
文件非 .xls / .xlsx |
4001 | {*[core.dts.excelimport.config.cannotimport]*} |
null |
| 成功 | 0 | ok | List<String> |
| 抛异常 | 500 | <异常信息> |
null |
成功示例:
失败示例:{ "errcode": 4001, "errmsg": "{*[core.dts.excelimport.config.cannotimport]*}", "data": null, "errors": null }