UrbanOps 开放 API 对接接口文档
版本: v1.1
更新日期: 2026-06-25
适用对象: 第三方系统对接开发人员 / Co-Claw AI 助手
鉴权方式: HMAC-SHA256 API 签名
目录
- 概述
- 签名鉴权机制
- 通用规范
- 接口 1:团队考核查询(Co-Claw AI 专用)
- 接口 2:人员查询
- 接口 3:班组查询
- 接口 4:考勤查询
- 接口 5:工单查询
- 接口 6:物料查询
- 接口 7:全量工单统计
- 错误码说明
- 附录:客户端签名代码示例
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
具体步骤:
- 排序 Query 参数值:将 URL 中所有 query 参数按 key 字母升序排列,拼接所有 value
- 拼接 Header 参数值:按 key 字母升序(即
appId → nonce → timestamp),依次拼接它们的值
- 追加 appSecret:在最后拼接
appSecret
- 计算 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 |
查询模式(team 或 staff) |
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 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 ss) |
endTime |
String |
否 |
结束时间(格式:yyyy-MM-dd HH 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 ss) |
endDate |
String |
否 |
发布时间截止(yyyy-MM-dd HH 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 ss) |
endDate |
String |
否 |
结束时间(yyyy-MM-dd HH 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 代码生成,如有接口变更请同步更新。