开放API对接接口文档.md 35.8 KB

UrbanOps 开放 API 对接接口文档

版本: v1.1
更新日期: 2026-06-25
适用对象: 第三方系统对接开发人员 / Co-Claw AI 助手
鉴权方式: HMAC-SHA256 API 签名


目录

  1. 概述
  2. 签名鉴权机制
  3. 通用规范
  4. 接口 1:团队考核查询(Co-Claw AI 专用)
  5. 接口 2:人员查询
  6. 接口 3:班组查询
  7. 接口 4:考勤查询
  8. 接口 5:工单查询
  9. 接口 6:物料查询
  10. 接口 7:全量工单统计
  11. 错误码说明
  12. 附录:客户端签名代码示例

1. 概述

1.1 基本信息

项目 说明
接口协议 HTTPS
接口地址 https://{host}/open-api/
鉴权方式 HMAC-SHA256 API 签名(详见第2节)
响应格式 JSON
字符编码 UTF-8

1.2 接口列表

# 接口名称 路径 方法 说明
1 团队考核查询 /open-api/team-assessment/query GET Co-Claw AI 专用:班组/人员考核聚合接口,含考勤/工单/耗材三维评分
2 人员查询 /open-api/staff/query GET 获取人员档案,支持按部门筛选
3 班组查询 /open-api/teams/query GET 获取班组信息,含班组长和人员数量
4 考勤查询 /open-api/attendance/query GET 获取考勤打卡数据
5 工单查询 /open-api/tasks/query GET 获取工单全生命周期数据
6 物料查询 /open-api/materials/query GET 获取物料消耗与照片数据
7 全量工单统计 /open-api/full-order-statistics/query GET 获取公司/班组工单/巡查/养护完成数量

1.3 接入前提

接入前需向 UrbanOps 平台申请以下凭证(由运维人员配置到 Redis):

参数 说明
appId 应用唯一标识(由平台分配)
appSecret 应用密钥(妥善保管,不可泄露)

2. 签名鉴权机制

2.1 签名参数

每个请求必须携带以下 4 个请求头

请求头 类型 必填 说明
appId String 平台分配的应用 ID
timestamp String 当前 Unix 时间戳(毫秒),与服务器时间误差不能超过 60 秒
nonce String 随机字符串,长度 ≥ 10,每次请求必须不同(防重放)
sign String 签名字符串(SHA256 计算结果,小写十六进制

2.2 签名算法

签名字符串构造规则

签名字符串 = queryParams(按key字母序排列的value拼接) 
           + headerParams(按key字母序排列的value拼接)
           + appSecret

具体步骤:

  1. 排序 Query 参数值:将 URL 中所有 query 参数按 key 字母升序排列,拼接所有 value
  2. 拼接 Header 参数值:按 key 字母升序(即 appIdnoncetimestamp),依次拼接它们的值
  3. 追加 appSecret:在最后拼接 appSecret
  4. 计算 SHA256:对上述完整字符串计算 SHA256 哈希,转为小写十六进制字符串

签名公式

sign = SHA256(
    sortedQueryParamValues 
    + appId值 + nonce值 + timestamp值 
    + appSecret
)

注意:GET 请求无 body,body 部分为空字符串(不参与签名)。

2.3 签名示例

假设:

  • appId = my_app_001
  • appSecret = abc123xyz
  • 请求 URL:/open-api/staff/query?deptId=100

步骤拆解:

queryParams(sorted by key): 
  deptId=100
  → values = "100"

headerParams(sorted by key):
  appId=my_app_001, nonce=a1b2c3d4e5f6, timestamp=1749696000000
  → values = "my_app_001" + "a1b2c3d4e5f6" + "1749696000000"

signStr = "100" + "my_app_001" + "a1b2c3d4e5f6" + "1749696000000" + "abc123xyz"

sign = SHA256(signStr)

2.4 签名校验规则

校验项 规则 失败返回
appId 非空 必须传递 400 签名不正确
timestamp 时效 ` serverTime - timestamp
nonce 长度 len(nonce) ≥ 10 400 签名不正确
sign 非空 必须传递 400 签名不正确
签名比对 serverSign == clientSign 400 签名不正确
nonce 防重放 同一 appId + nonce 组合只能使用一次 900 存在重复请求

3. 通用规范

3.1 通用响应格式

{
  "code": 0,
  "msg": "成功",
  "data": [ ... ]
}
字段 类型 说明
code Integer 0 表示成功,非 0 表示失败
msg String 提示信息
data Array 业务数据列表(根据查询条件返回所有匹配记录)

3.2 日期时间格式

所有日期时间字段统一使用格式:yyyy-MM-dd HH:mm:ss

示例:2026-06-11 09:00:00


4. 接口 1:团队考核查询(Co-Claw AI 专用)⭐

设计定位:本接口专为 Co-Claw AI 助手设计,提供班组/人员考核数据的一站式聚合查询。 接口内部完成考勤、工单、耗材三维度评分计算,Co-Claw 可直接使用返回的得分和扣分明细进行考核分析, 无需自行计算。默认只返回汇总指标(includeDetail=false),Token 友好。

4.1 考核背景

本接口基于《房山区园林所养护队智慧化管理制度》设计,考核满分 100 分,三大维度:

维度 满分 主要扣分规则
工单上线率与及时率 40分 超24h补录 -1分/次 · 超时>2h -1分/次
人员考勤管理 30分 缺勤/未打卡 -1分/次 · 缺共同处理人 -1分/次 · 未佩戴工卡 -1分/次 · 班组长记录仪未开 -1分/次
人机材录入 30分 工单完成24h内未上报耗材 -2分/次

4.2 基本信息

项目 说明
路径 /open-api/team-assessment/query
方法 GET
说明 团队考核聚合查询。支持 team 模式(班组→人员+工单→考勤+耗材,三层结构)和 staff 模式(人员→考勤+工单→耗材)

4.3 请求参数

参数 类型 必填 默认值 说明
keyword String 查询关键字:班组名称或人员姓名,支持模糊匹配
queryMode String team 查询模式:team 按班组查询 / staff 按人员查询
startDate String 当月1日 考核开始日期(格式:yyyy-MM-dd)
endDate String 今天 考核结束日期(格式:yyyy-MM-dd)
includeDetail Boolean false 是否返回明细数据。false 仅返回汇总指标(推荐),true 同时返回考勤明细和工单耗材明细

4.4 响应字段(queryMode=team)

顶层结构

字段 类型 说明
queryMode String 查询模式(teamstaff
period PeriodVO 考核周期
teams Array 班组考核列表(team 模式)
staffList Array 人员考核列表(staff 模式,与 teams 互斥)

TeamVO — 班组考核(第一层)

字段 类型 说明
teamId Long 班组ID
teamName String 班组名称
parentTeamName String 上级部门名称(所属养护所)
leaderName String 班组长姓名
totalMembers Long 班组人数
score ScoreVO 考核得分(详见下方)
orderStats OrderStatsVO 工单统计
attendanceStats AttendanceStatsVO 考勤统计
materialStats MaterialStatsVO 耗材统计
members Array 人员列表(第二层,含个人考核指标)
orders Array 工单列表(第二层,含耗材)

ScoreVO — 考核得分

字段 类型 说明
total Integer 总分(满分100)
orderScore Integer 工单得分(满分40)
attendanceScore Integer 考勤得分(满分30)
materialScore Integer 人机材得分(满分30)
deductions Array 扣分明细列表

DeductionVO:

字段 类型 说明
rule String 扣分规则描述
count Integer 触发次数
points Integer 扣分(负数)

OrderStatsVO — 工单统计

字段 类型 说明
totalOrders Long 总工单数
completedOrders Long 已完成工单数
completionRate BigDecimal 完成率(%)
onlineRate BigDecimal 线上化率(%)
responseWithin30Min Long 30分钟内响应数
responseRate30Min BigDecimal 30分钟响应率(%)
overdueOrders Long 超期工单数
lateSupplementOrders Long 超24小时补录工单数

AttendanceStatsVO — 考勤统计

字段 类型 说明
totalCheckins Long 总打卡次数
absentCount Long 缺勤人次
missedCheckinCount Long 未触发电子围栏打卡次数
trajectoryLowCount Long 轨迹覆盖率不达标次数
missingCoHandlerCount Long 缺共同处理人次数
missingCardCount Long 未佩戴工卡次数
multiCardViolation Boolean 是否存在一人多卡违规
leaderRecorderOffCount Long 班组长记录仪未开机次数

MaterialStatsVO — 耗材统计

字段 类型 说明
ordersWithMaterial Long 已上报耗材的工单数
ordersMissingMaterial Long 缺耗材上报的工单数
totalMaterialItems Long 耗材总用量
materialTypes Long 耗材种类数

MemberVO — 人员信息(第二层)

字段 类型 说明
userId Long 人员ID
userName String 姓名
mobile String 手机号
postNames String 岗位名称(逗号分隔)
cardNumber String 工卡号
isInner Integer 是否内部人员(1=内部,2=外部)
personalScore PersonalScoreVO 个人考核指标
attendances Array 考勤明细(第三层includeDetail=true 时返回)
orders Array 个人工单(第三层includeDetail=true 时返回)

PersonalScoreVO — 个人考核指标

字段 类型 说明
attendanceDays Long 出勤天数
lateCount Long 迟到次数
absentCount Long 缺勤次数
assignedOrders Long 承担工单数
completedOrders Long 完成工单数
completionRate BigDecimal 完成率(%)
overdueOrders Long 超期工单数
materialReported Long 已上报耗材工单数
materialMissing Long 缺耗材上报工单数

OrderVO — 工单信息(第二层/第三层)

字段 类型 说明
orderNo String 工单号
orderName String 工单名称
orderType String 工单类型:Q=快速,C=普通,O=其他
workerName String 接单人姓名
status Integer 审批状态
buzStatus String 业务状态(completed=已完成)
commitDate String 发布时间
finishDate String 完成时间
expectedFinishDate String 期望完成时间
responseMinutes Long 响应时长(分钟)
isOverdue Boolean 是否超期(finishDate > expectedFinishDate
isLateSupplement Boolean 是否超24小时补录
hasMaterialReported Boolean 是否已上报耗材
coHandlers Array 共同处理人姓名
materials Array 耗材明细(第三层includeDetail=true 时返回)

其他嵌套 VO

AttendanceRecordVO:

字段 类型 说明
punchType String 打卡类型(上班/下班)
punchTime String 打卡时间
address String 打卡地址

MaterialVO:

字段 类型 说明
materialName String 耗材名称
specifications String 规格
userCount Long 使用数量
unitName String 单位
classifyName String 分类

PeriodVO:

字段 类型 说明
start String 考核开始日期(yyyy-MM-dd)
end String 考核结束日期(yyyy-MM-dd)

4.5 请求示例

# team 模式:按班组名称查询考核数据(仅汇总)
curl -X GET "https://test.jichengshanshui.com.cn:28302/open-api/team-assessment/query?keyword=养护一班&queryMode=team&startDate=2026-06-01&endDate=2026-06-30" \
  -H "appId: my_app_001" \
  -H "timestamp: 1749696000000" \
  -H "nonce: c3d4e5f6g7h8i9j0" \
  -H "sign: ..."

# staff 模式:按人员姓名查询考核数据(含考勤明细和工单耗材)
curl -X GET "https://test.jichengshanshui.com.cn:28302/open-api/team-assessment/query?keyword=张三&queryMode=staff&includeDetail=true" \
  -H "appId: my_app_001" \
  -H "timestamp: 1749696000000" \
  -H "nonce: d4e5f6g7h8i9j0k1" \
  -H "sign: ..."

4.6 响应示例(team 模式,includeDetail=false)

{
  "code": 0,
  "msg": "成功",
  "data": {
    "queryMode": "team",
    "period": {
      "start": "2026-06-01",
      "end": "2026-06-30"
    },
    "teams": [
      {
        "teamId": 100,
        "teamName": "养护一班",
        "parentTeamName": "房山区园林所",
        "leaderName": "张三",
        "totalMembers": 15,
        "score": {
          "total": 85,
          "orderScore": 34,
          "attendanceScore": 25,
          "materialScore": 26,
          "deductions": [
            { "rule": "工单超24小时补录", "count": 1, "points": -1 },
            { "rule": "工单超时>2小时", "count": 2, "points": -2 },
            { "rule": "缺勤/未打卡", "count": 5, "points": -5 },
            { "rule": "人机材24h内未上报", "count": 1, "points": -2 }
          ]
        },
        "orderStats": {
          "totalOrders": 45,
          "completedOrders": 42,
          "completionRate": 93.3,
          "onlineRate": 97.8,
          "responseWithin30Min": 40,
          "responseRate30Min": 88.9,
          "overdueOrders": 2,
          "lateSupplementOrders": 1
        },
        "attendanceStats": {
          "totalCheckins": 570,
          "absentCount": 5,
          "missedCheckinCount": 5,
          "trajectoryLowCount": 1,
          "missingCoHandlerCount": 0,
          "missingCardCount": 0,
          "multiCardViolation": false,
          "leaderRecorderOffCount": 0
        },
        "materialStats": {
          "ordersWithMaterial": 42,
          "ordersMissingMaterial": 1,
          "totalMaterialItems": 230,
          "materialTypes": 15
        },
        "members": [
          {
            "userId": 1001,
            "userName": "张三",
            "mobile": "13800138001",
            "postNames": "班组长,技术员",
            "cardNumber": "DEV001",
            "isInner": 1,
            "personalScore": {
              "attendanceDays": 28,
              "lateCount": 0,
              "absentCount": 0,
              "assignedOrders": 8,
              "completedOrders": 8,
              "completionRate": 100.0,
              "overdueOrders": 0,
              "materialReported": 8,
              "materialMissing": 0
            }
          }
        ],
        "orders": [
          {
            "orderNo": "WO202606250001",
            "orderName": "树木修剪",
            "orderType": "C",
            "workerName": "张三",
            "status": 1,
            "buzStatus": "completed",
            "commitDate": "2026-06-25 09:00:00",
            "finishDate": "2026-06-25 16:30:00",
            "expectedFinishDate": "2026-06-25 18:00:00",
            "responseMinutes": 15,
            "isOverdue": false,
            "isLateSupplement": false,
            "hasMaterialReported": true,
            "coHandlers": ["李四"]
          }
        ]
      }
    ]
  }
}

4.7 响应示例(staff 模式,includeDetail=true)

{
  "code": 0,
  "msg": "成功",
  "data": {
    "queryMode": "staff",
    "period": {
      "start": "2026-06-01",
      "end": "2026-06-25"
    },
    "staffList": [
      {
        "userId": 1001,
        "userName": "张三",
        "mobile": "13800138001",
        "deptId": 100,
        "deptName": "养护一班",
        "postNames": "班组长",
        "cardNumber": "DEV001",
        "isInner": 1,
        "assessment": {
          "attendanceDays": 28,
          "lateCount": 0,
          "absentCount": 0,
          "assignedOrders": 8,
          "completedOrders": 8,
          "completionRate": 100.0,
          "overdueOrders": 0,
          "materialReported": 8,
          "materialMissing": 0
        },
        "attendances": [
          { "punchType": "上班", "punchTime": "2026-06-25 08:00:00", "address": "北京市房山区xx路" },
          { "punchType": "下班", "punchTime": "2026-06-25 17:30:00", "address": "北京市房山区xx路" }
        ],
        "orders": [
          {
            "orderNo": "WO202606250001",
            "orderName": "树木修剪",
            "orderType": "C",
            "workerName": "张三",
            "status": 1,
            "buzStatus": "completed",
            "commitDate": "2026-06-25 09:00:00",
            "finishDate": "2026-06-25 16:30:00",
            "expectedFinishDate": "2026-06-25 18:00:00",
            "responseMinutes": 15,
            "isOverdue": false,
            "isLateSupplement": false,
            "hasMaterialReported": true,
            "coHandlers": ["李四"],
            "materials": [
              {
                "materialName": "高效氯氰菊酯",
                "specifications": "500ml/瓶",
                "userCount": 2,
                "unitName": "瓶",
                "classifyName": "药品"
              }
            ]
          }
        ]
      }
    ]
  }
}

4.8 使用建议(Co-ClawCo-Claw)

场景 推荐参数 说明
月底考核排名 keyword=养护&queryMode=team 模糊查询所有养护班组,返回考核得分用于排名
单班组详情分析 keyword=养护一班&queryMode=team&includeDetail=true 查看特定班组全部明细,分析扣分原因
个人绩效查询 keyword=张三&queryMode=staff&includeDetail=true 查看某人出勤、工单、耗材完整记录
日常快速巡检 keyword=养护&includeDetail=false 只看汇总指标,Token 最少

5. 接口 2:人员查询

4.1 基本信息

项目 说明
路径 /open-api/staff/query
方法 GET
说明 获取人员基础档案信息,支持按部门、姓名、手机号等条件筛选

4.2 请求参数

参数 类型 必填 说明
name String 姓名,模糊匹配
mobile String 手机号,模糊匹配
deptId Long 部门ID,精确匹配
status Integer 状态:0=启用,1=禁用
busiLine String 业务线:yl=园林,wy=物业,sz=市政

4.3 响应字段

字段 类型 说明
id Long 人员ID
username String 用户名
nickname String 姓名
mobile String 手机号
deptId Long 部门ID
deptName String 部门名称(如"养护一班")
postIds Array 岗位ID列表
postNames String 岗位名称(逗号分隔,如"班组长,技术员")
busiLine String 业务线
status Integer 状态(0=启用,1=禁用)
cardNumber String 工卡号(设备编号,用于考勤打卡)
isInner Integer 是否内部人员(1=内部,2=外部)
createTime String 入职日期(格式:yyyy-MM-dd HH:mm:ss)

4.4 请求示例

curl -X GET "https://test.jichengshanshui.com.cn:28302/open-api/staff/query?deptId=100" \
  -H "appId: my_app_001" \
  -H "timestamp: 1749696000000" \
  -H "nonce: a1b2c3d4e5f6g7h8" \
  -H "sign: 3a5f8c9e2b1d4f6a8c0e2b4d6f8a0c2e4b6d8f0a"

4.5 响应示例

{
  "code": 0,
  "msg": "成功",
  "data": [
    {
        "id": 1001,
        "username": "zhangsan",
        "nickname": "张三",
        "mobile": "13800138001",
        "deptId": 100,
        "deptName": "养护一班",
        "postIds": [10, 20],
        "postNames": "班组长,技术员",
        "busiLine": "yl",
        "status": 0,
        "cardNumber": "DEV001",
        "isInner": 1,
        "createTime": "2024-01-15 00:00:00"
      }
    ],
    "total": 150
  }

6. 接口 3:班组查询

5.1 基本信息

项目 说明
路径 /open-api/teams/query
方法 GET
说明 获取组织架构班组信息,含班组长、所属养护所、人员数量

5.2 请求参数

参数 类型 必填 说明
name String 班组名称,模糊匹配
parentId Long 父部门ID(上级组织),精确匹配
status Integer 状态:0=启用,1=禁用

5.3 响应字段

字段 类型 说明
id Long 班组ID
name String 班组名称
parentId Long 父部门ID
parentName String 父部门名称(所属养护所)
leaderUserId Long 班组长人员ID(Staff.id)
leaderUserName String 班组长姓名
memberCount Long 人员数量
sort Integer 排序
status Integer 状态(0=启用,1=禁用)

5.4 请求示例

curl -X GET "https://test.jichengshanshui.com.cn:28302/open-api/teams/query" \
  -H "appId: my_app_001" \
  -H "timestamp: 1749696000000" \
  -H "nonce: b2c3d4e5f6g7h8i9" \
  -H "sign: ..."

5.5 响应示例

{
  "code": 0,
  "msg": "成功",
  "data": [
    {
        "id": 100,
        "name": "养护一班",
        "parentId": 1,
        "parentName": "蓟城山水集团",
        "leaderUserId": 1001,
        "leaderUserName": "张三",
        "memberCount": 15,
        "sort": 1,
        "status": 0
      }
    ],
    "total": 12
  }
}

7. 接口 4:考勤查询

6.1 基本信息

项目 说明
路径 /open-api/attendance/query
方法 GET
说明 获取电子围栏打卡与位置数据,支持按班组、人员、时间范围筛选

6.2 请求参数

参数 类型 必填 说明
userId Long 人员ID,精确匹配
deptId Long 部门ID(班组),精确匹配
busiLine String 业务线
punchType String 打卡类型(上班/下班)
startTime String 开始时间(格式:yyyy-MM-dd HH:mm:ss)
endTime String 结束时间(格式:yyyy-MM-dd HH:mm:ss)

6.3 响应字段

字段 类型 说明
id Integer 记录ID
deviceCode String 设备编码
deviceName String 设备名称
punchType String 打卡类型
userId Long 人员ID
nickname String 人员姓名
deptId Long 部门ID
deptName String 部门名称
address String 打卡地址
latGcj02 BigDecimal 高德纬度(GCJ-02坐标系)
lngGcj02 BigDecimal 高德经度(GCJ-02坐标系)
lat BigDecimal WGS84纬度
lng BigDecimal WGS84经度
createTime String 打卡时间

注意:当前版本暂不支持"轨迹点集""是否佩戴工卡""记录仪状态"字段(数据库无对应存储)。待业务系统确认后将补充。

6.4 响应示例

{
  "code": 0,
  "msg": "成功",
  "data": [
    {
        "id": 1,
        "deviceCode": "DEV001",
        "deviceName": "打卡机01",
        "punchType": "上班",
        "userId": 1001,
        "nickname": "张三",
        "deptId": 100,
        "deptName": "养护一班",
        "address": "北京市西城区xx路xx号",
        "latGcj02": 39.9042,
        "lngGcj02": 116.4074,
        "lat": 39.9010,
        "lng": 116.4030,
        "createTime": "2026-06-11 08:30:00"
      }
    ],
    "total": 320
  }
}

8. 接口 5:工单查询

7.1 基本信息

项目 说明
路径 /open-api/tasks/query
方法 GET
说明 获取工单全生命周期数据,含发布时间、状态、接单渠道、共同处理人

7.2 请求参数

参数 类型 必填 说明
orderNo String 工单号,模糊匹配
orderName String 工单名称,模糊匹配
busiLine String 业务线
status Integer 审批状态
buzStatus String 业务状态
workerId Long 接单人ID
startDate String 发布时间起始(yyyy-MM-dd HH:mm:ss)
endDate String 发布时间截止(yyyy-MM-dd HH:mm:ss)

7.3 响应字段

字段 类型 说明
id Long 工单ID
orderNo String 工单号
orderName String 工单名称
orderType String 工单类型:Q=快速,C=普通,O=其他
busiLine String 业务线
commitDate String 发布时间(工单派发时间)
finishDate String 完成时间
userId Long 发布人ID
userName String 发布人姓名
workerId Long 接单人ID
workerName String 接单人姓名
coHandlers Array 共同处理人姓名列表
woSourceName String 接单渠道(小程序/人工派单等)
status Integer 审批状态
buzStatus String 业务状态
remark String 备注
photos Array 工单附件照片

PhotoVO 结构:

字段 类型 说明
busiType String 业务类型:01=问题照片,02=处理中,03=完成
fileName String 文件名
url String 文件URL

7.4 响应示例

{
  "code": 0,
  "msg": "成功",
  "data": [
    {
        "id": 5001,
        "orderNo": "WO202606110001",
        "orderName": "树木修剪",
        "orderType": "C",
        "busiLine": "yl",
        "commitDate": "2026-06-11 09:00:00",
        "finishDate": null,
        "userId": 1,
        "userName": "管理员",
        "workerId": 1001,
        "workerName": "张三",
        "coHandlers": ["李四", "王五"],
        "woSourceName": "小程序",
        "status": 1,
        "buzStatus": "processing",
        "remark": "紧急处理",
        "photos": [
          {
            "busiType": "01",
            "fileName": "problem.jpg",
            "url": "https://xxx.com/file/abc.jpg"
          }
        ]
      }
    ],
    "total": 85
  }
}

9. 接口 6:物料查询

8.1 基本信息

项目 说明
路径 /open-api/materials/query
方法 GET
说明 获取物料消耗记录与人机材照片数据,支持按工单筛选

8.2 请求参数

参数 类型 必填 说明
orderNo String 工单号,精确匹配
classifyName String 物料分类名,模糊匹配
typeName String 物料类型名,模糊匹配
userId Long 使用人ID
startDate String 开始时间(yyyy-MM-dd HH:mm:ss)
endDate String 结束时间(yyyy-MM-dd HH:mm:ss)

8.3 响应字段

字段 类型 说明
id Long 记录ID
orderNo String 关联工单号
materialName String 物料名称
specifications String 规格
userCount Long 使用数量
unitName String 单位
classifyName String 物料分类
typeName String 物料类型
typeDetailName String 物料明细类型
userId Long 使用人ID
userName String 使用人姓名
source Integer 来源:1=工单,2=巡检,3=养护
createTime String 上传时间
photos Array 人机材照片(结构同工单接口)

8.4 响应示例

{
  "code": 0,
  "msg": "成功",
  "data": [
    {
        "id": 3001,
        "orderNo": "WO202606110001",
        "materialName": "高效氯氰菊酯",
        "specifications": "500ml/瓶",
        "userCount": 5,
        "unitName": "瓶",
        "classifyName": "药品",
        "typeName": "杀虫剂",
        "typeDetailName": "有机磷",
        "userId": 1001,
        "userName": "张三",
        "source": 1,
        "createTime": "2026-06-11 14:30:00",
        "photos": [
          {
            "busiType": "02",
            "fileName": "material.jpg",
            "url": "https://xxx.com/file/def.jpg"
          }
        ]
      }
    ],
    "total": 45
  }
}

10. 接口 7:全量工单统计

9.1 基本信息

项目 说明
路径 /open-api/full-order-statistics/query
方法 GET
说明 获取各公司/班组在一段时间内实际完成的工单数量、巡查记录数量、养护记录数量

9.2 请求参数

参数 类型 必填 说明
companyId Long 公司/班组ID,精确匹配
companyName String 公司/班组名称,模糊匹配
type Integer 类型:1=按公司,2=按班组
startDate String 统计开始日期(格式:yyyy-MM-dd,返回开始日期>=该值的记录)
endDate String 统计结束日期(格式:yyyy-MM-dd,返回结束日期

9.3 响应字段

字段 类型 说明
id Long 记录ID
companyId Long 公司/班组ID
companyName String 公司/班组名称
type Integer 类型:1=按公司,2=按班组
startDate String 统计开始日期
endDate String 统计结束日期
workOrderCount Integer 工单完成数量
inspectionCount Integer 巡查记录数量
maintenanceCount Integer 养护记录数量
remark String 备注
createTime String 创建时间

9.4 请求示例

curl -X GET "https://test.jichengshanshui.com.cn:28302/open-api/full-order-statistics/query?type=1&startDate=2026-06-01&endDate=2026-06-30" \
  -H "appId: my_app_001" \
  -H "timestamp: 1749696000000" \
  -H "nonce: f6g7h8i9j0k1l2m3" \
  -H "sign: ..."

9.5 响应示例

{
  "code": 0,
  "msg": "成功",
  "data": [
    {
      "id": 1,
      "companyId": 100,
      "companyName": "养护一班",
      "type": 1,
      "startDate": "2026-06-01",
      "endDate": "2026-06-30",
      "workOrderCount": 85,
      "inspectionCount": 120,
      "maintenanceCount": 60,
      "remark": "二季度统计",
      "createTime": "2026-06-11 10:00:00"
    }
  ]
}

11. 错误码说明

11.1 签名相关错误

code msg 说明
400 签名不正确 签名验证失败(appId不存在/timestamp超时/nonce长度不足/签名不匹配)
900 存在重复请求 nonce 已被使用(重放攻击检测)

11.2 业务接口错误

code msg 说明
1-100-020-001 人员查询失败 人员查询内部错误
1-100-020-002 班组查询失败 班组查询内部错误
1-100-020-003 考勤查询失败 考勤查询内部错误
1-100-020-004 工单查询失败 工单查询内部错误
1-100-020-005 物料查询失败 物料查询内部错误
1-100-020-006 团队考核查询失败 团队考核聚合查询内部错误
1-900-005-001 全量工单统计不存在 记录不存在
1-900-005-002 相同公司/班组同时间段统计已存在 重复数据校验

11.3 通用错误

code msg 说明
400 参数校验失败 请求参数格式或值不正确
500 系统内部错误 服务器内部异常

12. 附录:客户端签名代码示例

12.1 Java 示例

import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.core.util.RandomUtil;

import java.util.Map;
import java.util.TreeMap;

public class OpenApiClient {

    private static final String BASE_URL = "https://test.jichengshanshui.com.cn:28302";
    private static final String APP_ID = "your_app_id";
    private static final String APP_SECRET = "your_app_secret";

    public static String call(String path, Map<String, Object> params) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String nonce = RandomUtil.randomString(16);
        String sign = buildSign(params, timestamp, nonce);

        String url = BASE_URL + path;
        HttpResponse response = HttpRequest.get(url)
                .form(params)
                .header("appId", APP_ID)
                .header("timestamp", timestamp)
                .header("nonce", nonce)
                .header("sign", sign)
                .execute();
        return response.body();
    }

    private static String buildSign(Map<String, Object> params,
                                     String timestamp, String nonce) {
        StringBuilder sb = new StringBuilder();

        // 1. 排序 query 参数值
        if (params != null && !params.isEmpty()) {
            new TreeMap<>(params).values().stream()
                    .map(String::valueOf).forEach(sb::append);
        }

        // 2. header 参数值(appId, nonce, timestamp 字母序)
        sb.append(APP_ID);
        sb.append(nonce);
        sb.append(timestamp);

        // 3. 追加 appSecret + SHA256
        sb.append(APP_SECRET);
        return DigestUtil.sha256Hex(sb.toString());
    }
}

12.2 Python 示例

import hashlib
import time
import random
import string
import requests

BASE_URL = "https://test.jichengshanshui.com.cn:28302"
APP_ID = "your_app_id"
APP_SECRET = "your_app_secret"

def build_sign(params, timestamp, nonce):
    parts = []
    if params:
        for key in sorted(params.keys()):
            parts.append(str(params[key]))
    parts.append(APP_ID)
    parts.append(nonce)
    parts.append(timestamp)
    parts.append(APP_SECRET)
    sign_str = "".join(parts)
    return hashlib.sha256(sign_str.encode()).hexdigest()

def call(path, params=None):
    if params is None:
        params = {}
    timestamp = str(int(time.time() * 1000))
    nonce = "".join(random.choices(string.ascii_lowercase + string.digits, k=16))
    sign = build_sign(params, timestamp, nonce)
    headers = {
        "appId": APP_ID,
        "timestamp": timestamp,
        "nonce": nonce,
        "sign": sign
    }
    response = requests.get(BASE_URL + path, params=params, headers=headers)
    return response.json()

12.3 Shell (cURL) 示例

#!/bin/bash
APP_ID="your_app_id"
APP_SECRET="your_app_secret"
TIMESTAMP=$(date +%s%3N)
NONCE=$(openssl rand -hex 16)

# 示例:/open-api/staff/query?deptId=100
# query params 排序后 values: deptId=100 → "100"
QUERY_VALUES="100"
HEADER_VALUES="${APP_ID}${NONCE}${TIMESTAMP}"
SIGN_STR="${QUERY_VALUES}${HEADER_VALUES}${APP_SECRET}"
SIGN=$(echo -n "$SIGN_STR" | openssl dgst -sha256 -hex | awk '{print $2}')

curl -X GET "https://test.jichengshanshui.com.cn:28302/open-api/staff/query?deptId=100" \
  -H "appId: ${APP_ID}" \
  -H "timestamp: ${TIMESTAMP}" \
  -H "nonce: ${NONCE}" \
  -H "sign: ${SIGN}"

本文档基于 2026-06-11 代码生成,如有接口变更请同步更新。