# -*- coding: utf-8 -*- """票 01 t11:把 5 份同步任务 .bru 写入文档仓(Write 工具无法出 workspace,经此脚本落盘)。""" import io, os, sys sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') BASE = r'D:\code\crm-api-docs\A7 后台管理\用户管理\同步任务' os.makedirs(BASE, exist_ok=True) DOCS = {} DOCS['钉钉组织同步.bru'] = '''meta { name: 钉钉组织同步 type: http seq: 1 tags: [ generated ] } post { url: {{baseUrl}}/api/system/sync/dingtalk body: none auth: inherit } docs { # 钉钉组织同步 `POST /api/system/sync/dingtalk` 发起钉钉组织同步任务(A7-1-2 任务化):建任务行即返回任务编号,同步异步执行;全量同步钉钉部门树与用户(幂等,可重跑)。 > 需 ADMIN 角色。已有运行中任务达到并发上限时返回 61023(已有同步任务运行中)。 > 执行结果(部门/用户新增更新计数、进度、失败明细)经「同步任务详情」按 taskId 查询; > 手动发起触发方式记为 manual,每日自动调度记为 auto;「重新同步」复用本端点。 ## 请求参数 无 ## 请求示例 请求头:Authorization: Bearer {{token}} POST /api/system/sync/dingtalk ## 响应 data 结构 data 为 DtSyncLaunchDTO(发起结果,执行异步进行): | 字段 | 类型 | 说明 | | --- | --- | --- | | taskId | string | 任务ID,用于查同步任务详情 | | taskNo | string | 任务编号,格式 SYNC-MMdd-当日序号 | ## 响应示例 // 示例数据,字段结构以上表为准,非真实返回 ```json { "code": 0, "success": true, "message": "success", "data": { "taskId": "2097168678261866498", "taskNo": "SYNC-0908-01" } } ``` } ''' DOCS['同步任务分页.bru'] = '''meta { name: 同步任务分页 type: http seq: 2 tags: [ generated ] } post { url: {{baseUrl}}/api/system/sync/tasks/page body: formUrlEncoded auth: inherit } body:form-urlencoded { current: 1 size: 10 taskNo: 0908 startTimeFrom: 2026-09-01 startTimeTo: 2026-09-08 triggerType: manual status: running } docs { # 同步任务分页 `POST /api/system/sync/tasks/page` 同步记录分页(A7-1-2,需 ADMIN 角色):任务编号/开始时间范围/触发方式/执行状态筛选,默认按开始时间倒序。 ## 请求参数 | 参数 | 类型 | 必填 | 默认 | 说明 | | --- | --- | --- | --- | --- | | current | int | 否 | 1 | 当前页码,从 1 开始 | | size | int | 否 | 10 | 每页条数,上限 500 | | orderBy | string | 否 | - | 排序字段;缺省按 startTime 倒序 | | asc | boolean | 否 | false | 是否升序 | | taskNo | string | 否 | - | 任务编号模糊匹配(如 0908) | | startTimeFrom | date | 否 | - | 开始时间起(含当天 00:00) | | startTimeTo | date | 否 | - | 开始时间讫(含当天 23:59:59) | | triggerType | string | 否 | - | 触发方式 manual/auto | | status | string | 否 | - | 执行状态 running/success/partial_failed/all_failed | ## 请求示例 请求头:Authorization: Bearer {{token}} Content-Type: application/x-www-form-urlencoded POST /api/system/sync/tasks/page current=1&size=10&taskNo=0908&startTimeFrom=2026-09-01&startTimeTo=2026-09-08&triggerType=manual&status=running ## 响应 data 结构 | 字段 | 类型 | 说明 | | --- | --- | --- | | content[] | array | 任务列表 | | id | string | 任务ID | | taskNo | string | 任务编号 SYNC-MMdd-序号 | | triggerType | string | 触发方式 manual(手动)/ auto(每日自动) | | status | string | 执行状态 running/success/partial_failed/all_failed | | startTime | datetime | 开始时间 | | endTime | datetime | 结束时间,执行中为 null | | deptTotal | int | 钉钉侧部门总数 | | deptInserted | int | 新增部门数 | | deptUpdated | int | 更新部门数 | | userTotal | int | 钉钉侧用户总数(去重) | | userInserted | int | 新增用户数 | | userUpdated | int | 更新用户数 | | errorCount | int | 异常数(失败明细条数) | | progress | int | 进度百分比 0~100(发起 5 → 部门完成 45 → 用户完成 90 → 结束 100) | | total | long | 总条数 | | size | long | 每页条数 | | current | long | 当前页码 | | pages | long | 总页数 | | empty | boolean | 是否空结果 | ## 响应示例 // 示例数据,字段结构以上表为准,非真实返回 ```json { "code": 0, "success": true, "message": "success", "data": { "content": [ { "id": "2097168678261866498", "taskNo": "SYNC-0908-02", "triggerType": "manual", "status": "success", "startTime": "2026-09-08 10:30:00", "endTime": "2026-09-08 10:31:12", "deptTotal": 42, "deptInserted": 0, "deptUpdated": 3, "userTotal": 120, "userInserted": 2, "userUpdated": 5, "errorCount": 0, "progress": 100 } ], "total": 1, "size": 10, "current": 1, "pages": 1, "empty": false } } ``` } ''' DOCS['同步任务详情.bru'] = '''meta { name: 同步任务详情 type: http seq: 3 tags: [ generated ] } get { url: {{baseUrl}}/api/system/sync/tasks/detail body: none auth: inherit } params:query { id: 2097168678261866498 } docs { # 同步任务详情 `GET /api/system/sync/tasks/detail?id=` 同步任务详情(A7-1-2,需 ADMIN 角色):执行结果(部门/用户新增更新计数)、失败对象/接口错误/处理结果、执行进度。 任务不存在返回 61024。 ## 请求参数 | 参数 | 类型 | 必填 | 默认 | 说明 | | --- | --- | --- | --- | --- | | id | string | 是 | - | 任务ID(发起同步返回的 taskId,或分页行 id) | ## 请求示例 请求头:Authorization: Bearer {{token}} GET /api/system/sync/tasks/detail?id=2097168678261866498 ## 响应 data 结构 | 字段 | 类型 | 说明 | | --- | --- | --- | | id | string | 任务ID | | taskNo | string | 任务编号 SYNC-MMdd-序号 | | triggerType | string | 触发方式 manual/auto | | status | string | 执行状态 running/success/partial_failed/all_failed | | startTime | datetime | 开始时间 | | endTime | datetime | 结束时间,执行中为 null | | deptTotal | int | 钉钉侧部门总数 | | deptInserted | int | 新增部门数 | | deptUpdated | int | 更新部门数 | | userTotal | int | 钉钉侧用户总数(去重) | | userInserted | int | 新增用户数 | | userUpdated | int | 更新用户数 | | errorCount | int | 异常数 | | progress | int | 进度百分比 0~100 | | failDetails[] | array | 失败明细(成功为空数组) | | failObject | string | 失败对象(如某部门名/某用户名) | | apiError | string | 接口错误信息 | | handleResult | string | 处理结果(如「保留旧值」) | ## 响应示例 // 示例数据,字段结构以上表为准,非真实返回 ```json { "code": 0, "success": true, "message": "success", "data": { "id": "2097168678261866498", "taskNo": "SYNC-0908-02", "triggerType": "auto", "status": "all_failed", "startTime": "2026-09-08 02:00:00", "endTime": "2026-09-08 02:00:41", "deptTotal": 0, "deptInserted": 0, "deptUpdated": 0, "userTotal": 0, "userInserted": 0, "userUpdated": 0, "errorCount": 1, "progress": 0, "failDetails": [ { "failObject": "钉钉组织同步", "apiError": "钉钉组织同步失败:拉取部门用户失败(errcode=60003)", "handleResult": "本次同步未产生变更,保留同步前资料。" } ] } } ``` } ''' DOCS['读取同步设置.bru'] = '''meta { name: 读取同步设置 type: http seq: 4 tags: [ generated ] } get { url: {{baseUrl}}/api/system/sync/settings body: none auth: inherit } docs { # 读取同步设置 `GET /api/system/sync/settings` 读取钉钉自动同步设置(A7-1-2,需 ADMIN 角色):单例行配置,首次读取自动初始化默认行(每日 02:00 / 间隔 10 分钟 / 重试 2 次 / 并发 1)。 > plan(当前计划)与 nextExecuteTime(下次执行时间)为派生字段不落库; > lastModifierName 取最近修改人姓名。 ## 请求参数 无 ## 请求示例 请求头:Authorization: Bearer {{token}} GET /api/system/sync/settings ## 响应 data 结构 data 为 DtSyncSettingsDTO: | 字段 | 类型 | 说明 | | --- | --- | --- | | id | string | 设置行ID | | autoSyncEnabled | boolean | 自动同步开关 | | dailyTime | string | 每日执行时间 HH:mm | | retryIntervalMinutes | int | 重试间隔(分钟),≥1 | | retryMaxTimes | int | 重试次数,≥1 | | concurrency | int | 并发任务数,≥1 | | plan | string | 当前计划(派生):启用=「每日 HH:mm(运行中)」,停用=「已停用」 | | nextExecuteTime | datetime | 下次执行时间(派生):停用为 null;启用=今日/次日 dailyTime | | lastModifierName | string | 最近修改人姓名,从未修改为 null | | lastModifiedTime | datetime | 最近修改时间,从未修改为 null | ## 响应示例 // 示例数据,字段结构以上表为准,非真实返回 ```json { "code": 0, "success": true, "message": "success", "data": { "id": "2097168678261866499", "autoSyncEnabled": true, "dailyTime": "02:00", "retryIntervalMinutes": 10, "retryMaxTimes": 2, "concurrency": 1, "plan": "每日 02:00(运行中)", "nextExecuteTime": "2026-09-09 02:00:00", "lastModifierName": null, "lastModifiedTime": null } } ``` } ''' DOCS['保存同步设置.bru'] = '''meta { name: 保存同步设置 type: http seq: 5 tags: [ generated ] } post { url: {{baseUrl}}/api/system/sync/settings body: formUrlEncoded auth: inherit } body:form-urlencoded { autoSyncEnabled: true dailyTime: 02:00 retryIntervalMinutes: 10 retryMaxTimes: 2 concurrency: 1 } docs { # 保存同步设置 `POST /api/system/sync/settings` 保存钉钉自动同步设置(A7-1-2,需 ADMIN 角色),返回保存后的完整设置(含派生回显)。 > 边界校验不过返回 61022(同步设置参数非法):dailyTime 须为 HH:mm 格式、 > 重试间隔≥1 分钟、重试次数≥1、并发任务数≥1。 ## 请求参数 | 参数 | 类型 | 必填 | 默认 | 说明 | | --- | --- | --- | --- | --- | | autoSyncEnabled | boolean | 是 | - | 自动同步开关 | | dailyTime | string | 是 | - | 每日执行时间 HH:mm(00:00~23:59) | | retryIntervalMinutes | int | 是 | - | 重试间隔(分钟),≥1 | | retryMaxTimes | int | 是 | - | 重试次数,≥1 | | concurrency | int | 是 | - | 并发任务数,≥1 | ## 请求示例 请求头:Authorization: Bearer {{token}} Content-Type: application/x-www-form-urlencoded POST /api/system/sync/settings autoSyncEnabled=true&dailyTime=02:00&retryIntervalMinutes=10&retryMaxTimes=2&concurrency=1 ## 响应 data 结构 data 为保存后的 DtSyncSettingsDTO(字段同「读取同步设置」): | 字段 | 类型 | 说明 | | --- | --- | --- | | id | string | 设置行ID | | autoSyncEnabled | boolean | 自动同步开关 | | dailyTime | string | 每日执行时间 HH:mm | | retryIntervalMinutes | int | 重试间隔(分钟) | | retryMaxTimes | int | 重试次数 | | concurrency | int | 并发任务数 | | plan | string | 当前计划(派生回显) | | nextExecuteTime | datetime | 下次执行时间(派生回显,停用为 null) | | lastModifierName | string | 最近修改人姓名 | | lastModifiedTime | datetime | 最近修改时间 | ## 响应示例 // 示例数据,字段结构以上表为准,非真实返回 ```json { "code": 0, "success": true, "message": "success", "data": { "id": "2097168678261866499", "autoSyncEnabled": true, "dailyTime": "02:00", "retryIntervalMinutes": 10, "retryMaxTimes": 2, "concurrency": 1, "plan": "每日 02:00(运行中)", "nextExecuteTime": "2026-09-09 02:00:00", "lastModifierName": "管理员", "lastModifiedTime": "2026-09-08 10:35:00" } } ``` } ''' for name, content in DOCS.items(): path = os.path.join(BASE, name) with open(path, 'w', encoding='utf-8', newline='\n') as f: f.write(content) print('OK', name, len(content.encode('utf-8')), 'bytes')