hl-api-changelog/changelogs-v2/2026-08/04_5368_v3合同管理完整接口与订单号搜索-修改接口-管理后台.md
API Changelog Bot 090b25a484
一些检查失败了
changelog-filename-gate / validate (push) Failing after 2s
docs(changelog): 2026-08 批量补齐 author/关联联系人章节(yst格式),5558 从 v1 目录迁至 v2
2026-08-05 22:01:46 +08:00

50 KiB

schema, ticket, title, consumer, change_type, author, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer change_type author backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 5368 v3 合同管理完整接口与订单号搜索 admin 修改接口 yaosutu(GIT) deployed verified implemented pi-main-session hl-admin@5925a3ff810b5ef0dbce027a0057e343a1910446 2026-08-04T22:35:00+08:00 PR #5501 已合并 dev-v3;deploy-panel 任务 0eae2ffb 成功,hl-order-service-v3 8086/8186 双实例 UP。已通过有效管理后台鉴权验证 Gateway 合同列表 12 个只读用例与目标合同详情;列表/详情 teamNo 一致。QA 报告因未保存含 PII 的详情截图仍为 PARTIAL,不影响已完成的运行时功能门禁。 2026-08-04 dev-v3

🔧【修改接口·管理后台】v3 合同管理完整接口与订单号搜索 (#5368)

PR: #5501 | 服务: hl-order-service-v3 | 更新日期: 2026-08-04 范围: 仅 8 个 admin Controller 的 56 个 /v3/admin/* 端点;不含 internal、mp、callback、job。

1. 接口背景与历史文档关系

管理后台合同页需要统一使用 v3 读写链路,并在合同列表按订单号定位数据。本文同时给出该页面依赖的全部 admin 契约,便于前端一次性移除 v1/v3 混用。

与已发布的 2026-07/31_5368_非订单页面统一补齐真实团号与团号搜索 的关系:

  • 2026-07 文档对应 PR #5386 / commit c9d1b12618,已约定 teamNo: string|null、列表 teamNo 搜索、详情返回 teamNo 和 v3 完整写侧。
  • 本文对应 PR #5501;不重复声称上述能力是本次新增,而是补齐全量 admin 契约并说明本次仅有的两项可见变化。

2. 本次真实变更

# 接口 原来 现在
1 GET /v3/admin/contract/list 无独立 orderNo 查询参数 新增可选 orderNo,对人类可读订单号做包含匹配
2 同上 teamNo / contactName 文本边界未完整固化 orderNo / teamNo / contactName 统一 trim;全空白忽略;%_\ 都按字面字符匹配;多条件按 AND 组合

N+1 消除是内部性能修复,不属于前端契约变更。

3. 通用协议

  • 认证:所有端点都需要管理后台 JWT;旅行社敏感写操作按接口标注需 ADMIN 或 SUPER_ADMIN。
  • 成功包装:{ "code":200,"data":...,"message":"操作成功","success":true },字段名是 message,不是 msg
  • 分页包装:data.records / data.total / data.page / data.pageSize
  • 失败包装:{ "code":业务错误码,"data":null,"message":"可读提示","success":false }
  • 幂等GET 幂等;PUT 为目标状态更新时可重试;POST 创建/上传不得盲目重试;DELETE 不保证重复调用仍成功。
  • 金额按 JSON string 消费;雪花 ID 按 string 消费,不得转 JavaScript Number

变更接口完整接口清单,56

Controller 数量 路径域
AdminContractController 15 /v3/admin/contract
AdminContractSchemeController 7 /v3/admin/contract/scheme
AdminContractSchemeAttachmentController 4 /v3/admin/contract/scheme/<schemeId>/attachments
AdminContractSchemeTourGuideController 4 /v3/admin/contract/scheme/<schemeId>/tour-guides
AdminClauseTemplateController 6 /v3/admin/contract/clause-template
AdminTravelAgencyController 11 /v3/admin/travel-agency
AdminTravelAgencyQualificationController 4 /v3/admin/travel-agency/<agencyId>/qualification
AdminTravelAgencyPaymentController 5 /v3/admin/travel-agency/<agencyId>/payment

5. 接口详情

5.1 AdminContractController15

5.1.1 创建合同(标准模式)

  • 场景/协议:手工填写全量签约数据;POST /v3/admin/contract/create;管理员 JWT;非幂等。
  • 请求体(全部字段)orderId:long?contractType:string?(TOUR/INSURANCE)platform:string?(12301/LOCAL/TENCENT_ESIGN)vendorCode:string?templateCode:string!agencyCode:string?mchId:string?transactorName:string?transactorPhone:string?destination:string!routeName:string!days:int?nights:int?departureDate:date!returnDate:date!departureCity:string?groupId:string?signatoryMode:int?(1..3)signatoryName:string!signatoryPhone:string!signatoryIdType:int?signatoryIdNumber:string!signingPlace:string?adultCost:decimal!childCost:decimal?totalAmount:decimal!paymentMethod:int?(1..3)disputeResolution:int?(1..2)tribunalName:string?litigationCourt:string?contactName:string!contactPhone:string!supplementaryClause:string?travelers:array!accordingContract:boolean?accordingContractPhase:object?contractNum:string?holdNum:string?paymentDescription:string?paymentOther:string?agreeToBuyInsurance:boolean?insuranceCompany:string?insuranceCoverage:string?insurancePremium:string?insuranceProductName:string?insurancePurchaseMethod:int?(1..3)guideServiceCost:decimal?paymentTime:string?startHour:int?(0..23)endHour:int?(0..23)touristCondition:string?schemeId:string?travelers[]name:string!gender:string?(0/1/2)age:int?idCardType:int?(1/2)idCardNo:string!phone:string?isSigner:boolean?isChild:boolean?nationality:string?race:string?roomGroupNo:int?
  • 响应(完整)ContractDetailVOcontractId:string, orderId:string, schemeId:string|null, orderNo:string|null, teamNo:string|null, templateCode, templateName, contractNumber, platform, contractType, contractTypeLabel, mode, modeLabel, status, statusLabel, signUrl, qrCodeUrl, fileUrl, agencyCode, travelAgencyName, destination, departureDate, returnDate, totalAmount:string, touristCount:int, contactName, contactPhone, createTime, supplementaryClause, travelers[], statusLogs[]travelers[]={ travelerId:string,name,idCardType,idCardTypeLabel,idCardNo,phone,isSigner }statusLogs[]={ logId:string,contractId:string,oldStatus,oldStatusLabel,newStatus,newStatusLabel,source,sourceLabel,rawPayload,createTime }
  • 边界/错误:行程未确认 510220;已有有效合同 510214;模板不存在 510215;签署人手机缺失 510213;必填/长度/手机格式错误返回参数校验失败。
  • 典型示例:请求 { "orderId":"2079000000000000001","templateCode":"TOURAGE_STANDARD","destination":"呼伦贝尔","routeName":"草原5日","departureDate":"2026-08-10","returnDate":"2026-08-14","signatoryName":"张某","signatoryPhone":"138****8000","signatoryIdNumber":"110101********1234","adultCost":"3000.00","totalAmount":"6000.00","contactName":"张某","contactPhone":"138****8000","travelers":[{ "name":"张某","idCardNo":"110101********1234","isSigner":true }] };响应 { "code":200,"data":{ "contractId":"2080000000000000001","orderId":"2079000000000000001","status":"GENERATED","totalAmount":"6000.00","travelers":[],"statusLogs":[] },"message":"操作成功","success":true }

5.1.2 按方案创建合同

  • 场景/协议:后台从订单与方案自动组装合同;POST /v3/admin/contract/create-by-scheme; JWT;非幂等。
  • 入参:请求体 orderId:string!schemeId:string!
  • 响应(完整):与 5.1.1 的 ContractDetailVO 字段完全一致:contractId,orderId,schemeId,orderNo,teamNo,templateCode,templateName,contractNumber,platform,contractType,contractTypeLabel,mode,modeLabel,status,statusLabel,signUrl,qrCodeUrl,fileUrl,agencyCode,travelAgencyName,destination,departureDate,returnDate,totalAmount,touristCount,contactName,contactPhone,createTime,supplementaryClause,travelers[],statusLogs[]
  • 边界/错误:方案不存在/已停用 510205;方案未配模板 510206;订单信息失败 510207;行程未确认 510220;已有合同 510214
  • 示例:请求 { "orderId":"2079000000000000001","schemeId":"2020001" };响应 { "code":200,"data":{ "contractId":"2080000000000000001","orderId":"2079000000000000001","schemeId":"2020001","status":"GENERATED","travelers":[],"statusLogs":[] },"message":"操作成功","success":true }

5.1.3 作废合同

  • 场景/协议:不可恢复地作废有效合同;POST /v3/admin/contract/<id>/invalidate; JWT;重复调用不保证成功。
  • 入参:路径 id:string! 合同 ID;无请求体。
  • 响应(完整)ContractVO={ contractId,orderId,schemeId,orderNo,teamNo,templateCode,templateName,contractNumber,platform,contractType,contractTypeLabel,mode,modeLabel,status,statusLabel,signUrl,qrCodeUrl,fileUrl,agencyCode,travelAgencyName,destination,departureDate,returnDate,totalAmount:string,touristCount,contactName,contactPhone,createTime }
  • 边界/错误:合同不存在 510001;缺合同编号 510003;上游作废失败 510104
  • 示例:请求 POST /v3/admin/contract/2080000000000000001/invalidate 无 body;响应 { "code":200,"data":{ "contractId":"2080000000000000001","status":"VOIDED","statusLabel":"已作废" },"message":"操作成功","success":true }

5.1.4 合同列表(本 PR 修改)

  • 场景/协议:合同管理分页列表;GET /v3/admin/contract/list; JWT;幂等。
  • Query全部page:int?=1pageSize:int?=10orderId:string?status:string?platform:string?orderNo:string?teamNo:string?contactName:string?。三个文本条件都 trim;全空白忽略;% / _ / \ 字面匹配;条件间 AND。
  • 响应(完整)PageResult.records[] 每项为 ContractVO={ contractId,orderId,schemeId,orderNo,teamNo,templateCode,templateName,contractNumber,platform,contractType,contractTypeLabel,mode,modeLabel,status,statusLabel,signUrl,qrCodeUrl,fileUrl,agencyCode,travelAgencyName,destination,departureDate,returnDate,totalAmount:string,touristCount,contactName,contactPhone,createTime };顶层 total:long,page:int,pageSize:int
  • 边界orderNo=% 只匹配订单号中真实的 %,不会全表命中;orderNo= 等价于未传;无结果返回空 records
  • 示例:请求 GET /v3/admin/contract/list?page=1&pageSize=10&orderNo=HL2026&teamNo=26-08;响应 { "code":200,"data":{ "records":[{ "contractId":"2080000000000000001","orderId":"2079000000000000001","orderNo":"HL202608040001","teamNo":"26-0804","status":"SIGNED","totalAmount":"6000.00" }],"total":1,"page":1,"pageSize":10 },"message":"操作成功","success":true }

5.1.5 合同详情

  • 场景/协议:查看合同、出行人和状态日志;GET /v3/admin/contract/<id>; JWT;幂等。
  • 入参:路径 id:string!
  • 响应(完整)ContractDetailVO全字段:contractId,orderId,schemeId,orderNo,teamNo,templateCode,templateName,contractNumber,platform,contractType,contractTypeLabel,mode,modeLabel,status,statusLabel,signUrl,qrCodeUrl,fileUrl,agencyCode,travelAgencyName,destination,departureDate,returnDate,totalAmount,touristCount,contactName,contactPhone,createTime,supplementaryClause,travelers[{ travelerId,name,idCardType,idCardTypeLabel,idCardNo,phone,isSigner }],statusLogs[{ logId,contractId,oldStatus,oldStatusLabel,newStatus,newStatusLabel,source,sourceLabel,rawPayload,createTime }]
  • 错误/示例:不存在 510001。请求 GET /v3/admin/contract/2080000000000000001;响应 { "code":200,"data":{ "contractId":"2080000000000000001","orderId":"2079000000000000001","teamNo":"26-0804","totalAmount":"6000.00","travelers":[{ "travelerId":"2081000000000000001","name":"张某" }],"statusLogs":[] },"message":"操作成功","success":true }

5.1.6 下载合同文件

  • 场景/协议:取得已签署/已上报合同下载 URL;GET /v3/admin/contract/<id>/download; JWT;幂等。
  • 入参/响应:路径 id:string!data:string 为下载 URL,无其他 data 字段。
  • 错误/边界510001 不存在;510101 未签署完成;510102 文件 URL 缺失。
  • 示例:请求 GET /v3/admin/contract/2080000000000000001/download;响应 { "code":200,"data":"https://example.invalid/signed/contract.pdf?token=masked","message":"操作成功","success":true }

5.1.7 重发签署短信

  • 场景/协议:为未完成签署的合同重发短信;POST /v3/admin/contract/<id>/resend-sms; JWT;有 1 分钟频控,不可并发重试。
  • 入参/响应:路径 id:string!data:boolean
  • 错误/边界510001510005 已签署、510006 过于频繁、510007 合同编号缺失、510008 联系人手机缺失。
  • 示例:请求 POST /v3/admin/contract/2080000000000000001/resend-sms 无 body;响应 { "code":200,"data":true,"message":"操作成功","success":true }

5.1.8 合同模板列表

  • 场景/协议:创建合同时选择平台模板;GET /v3/admin/contract/templates; JWT;幂等。
  • Queryplatform:string? (12301 等)。
  • 响应(完整)data[] 每项 templateId:string,templateCode:string,templateName:string,platform:string,mode:string,status:string,description:string|null,createTime:datetime
  • 示例:请求 GET /v3/admin/contract/templates?platform=12301;响应 { "code":200,"data":[{ "templateId":"101","templateCode":"TOURAGE_STANDARD","templateName":"标准旅游合同","platform":"12301","mode":"STANDARD","status":"ACTIVE","description":null,"createTime":"2026-08-01T10:00:00" }],"message":"操作成功","success":true }

5.1.9 刷新合同状态

  • 场景/协议:主动从合同平台同步最新状态;GET /v3/admin/contract/<id>/status; JWT;查询可重试,但可产生状态更新。
  • 入参/响应:路径 id:string!ContractVO完整字段同 5.1.3。
  • 错误/示例510001510103 缺合同编号。请求 GET /v3/admin/contract/2080000000000000001/status;响应 { "code":200,"data":{ "contractId":"2080000000000000001","status":"SIGNED","statusLabel":"已签署" },"message":"操作成功","success":true }

5.1.10 按订单查询全部合同

  • 场景/协议:查询订单下包含已作废数据的全部合同;GET /v3/admin/contract/by-order/<orderId>; JWT;幂等。
  • 入参/响应orderId:string!data[] 每项为 5.1.3 的完整 ContractVO。无记录返回 []
  • 示例:请求 GET /v3/admin/contract/by-order/2079000000000000001;响应 { "code":200,"data":[{ "contractId":"2080000000000000001","orderId":"2079000000000000001","status":"SIGNED","totalAmount":"6000.00" }],"message":"操作成功","success":true }

5.1.11 获取订单有效合同

  • 场景/协议:取指定订单最新非作废合同;GET /v3/admin/contract/active-by-order/<orderId>; JWT;幂等。
  • 入参/响应orderId:string!data 为 5.1.3 的完整 ContractVO,没有有效合同时可为 null
  • 示例:请求 GET /v3/admin/contract/active-by-order/2079000000000000001;响应 { "code":200,"data":{ "contractId":"2080000000000000001","status":"SIGNED","totalAmount":"6000.00" },"message":"操作成功","success":true }

5.1.12 可用合同平台列表

  • 场景/协议:展示已注册平台及可用性;GET /v3/admin/contract/platforms; JWT;幂等;无入参。
  • 响应(完整)data[] 每项 platformName:string,displayName:string,available:boolean
  • 示例:请求 GET /v3/admin/contract/platforms;响应 { "code":200,"data":[{ "platformName":"12301","displayName":"12301团队报送","available":true }],"message":"操作成功","success":true }

5.1.13 已配置旅行社列表

  • 场景/协议:按平台筛选可用旅行社;GET /v3/admin/contract/agencies; JWT;幂等。
  • Queryplatform:string?
  • 响应(完整)data[] 每项 code,agencyName,licenseNumber,businessLicenseNumber,agencyAddress,agencyCountry,agencyState,agencyCity,agencyDistrict,transactorName,transactorPhone,regionId,businessScope,zjParentId,appId,signKey,teamReportAppId,teamReportSignKey,mchId,complaintPhone,email,supportedPlatforms[],bankCard,complaintProvince,complaintCity,complaintAreaCode,complaintAddress,tribunalName,litigationCourt。注意其中存在高敏配置,仅在授权后台使用,不得写日志/埋点。
  • 示例:请求 GET /v3/admin/contract/agencies?platform=12301;响应 { "code":200,"data":[{ "code":"hulai","agencyName":"呼籁旅行社","licenseNumber":"L-XX-100001","supportedPlatforms":["12301"],"appId":"***","signKey":"***" }],"message":"操作成功","success":true }

5.1.14 报备合同(线下签约)

  • 场景/协议:线下签完后上报监管平台;POST /v3/admin/contract/report; JWT;非幂等。
  • 请求体:字段、必填性与校验完全同 5.1.1 CreateContractRequest
  • 响应(完整):与 5.1.1 ContractDetailVO 完全一致。
  • 错误/边界:参数校验;未知旅行社 510201;上报失败 510203;腾讯电子签不支持 SYNC 510403
  • 示例:请求同 5.1.1,platform=12301;响应 { "code":200,"data":{ "contractId":"2080000000000000002","mode":"SYNC","status":"REPORTED","travelers":[],"statusLogs":[] },"message":"操作成功","success":true }

5.1.15 上传已签署合同 PDF

  • 场景/协议:仅 SYNC 合同上传签署后 PDF;POST /v3/admin/contract/<id>/upload-pdf; JWT;非幂等。
  • 入参:路径 id:string!multipart/form-datafile:file!
  • 响应(完整)5.1.3 的完整 ContractVO
  • 错误/边界510001510105 缺合同编号、510106 当前状态不允许、510107 上传失败;ONLINE/STANDARD 合同不适用。
  • 示例:请求 POST /v3/admin/contract/2080000000000000002/upload-pdf + file=@signed-contract.pdf;响应 { "code":200,"data":{ "contractId":"2080000000000000002","mode":"SYNC","status":"UPLOADED","fileUrl":"https://example.invalid/signed.pdf" },"message":"操作成功","success":true }

5.2 AdminContractSchemeController7

ContractSchemeVO 完整字段:schemeId:string,name,description,contractPlatform,vendorCode,channel,contractTemplateCode,templateCode,contractTemplateName,contractMode,signatoryMode,agencyCode,agencyName,supplementaryClause,transactorName,transactorPhone,sortOrder,status,createTimeContractSchemeRequest 完整字段:name:string!(max100),description:string?(max500),contractPlatform:string?(max50),vendorCode:string?(max32),channel:string?(max32),contractTemplateCode:string?(max50;兼容 templateCode/template_code),contractMode:string?(max50),signatoryMode:int?(1..3),agencyCode:string?(max50),supplementaryClause:string?(max2000),transactorName:string?(max50),transactorPhone:string?(11位手机),sortOrder:int?

5.2.1 启用方案列表

  • GET /v3/admin/contract/scheme/list;产品/合同方案下拉;JWT;幂等;无入参。
  • 响应(完整)data[] 每项包含上述 ContractSchemeVO 全部 19 字段,仅返回 status=ACTIVE
  • 示例GET .../list{ "code":200,"data":[{ "schemeId":"2020001","name":"标准方案","contractPlatform":"12301","contractMode":"STANDARD","status":"ACTIVE" }],"message":"操作成功","success":true }

5.2.2 全部方案列表

  • GET /v3/admin/contract/scheme/list-all;方案管理页;JWT;幂等;无入参。
  • 响应(完整)data[] 每项包含 ContractSchemeVO 全部 19 字段,包含 ACTIVE/INACTIVE。
  • 示例GET .../list-all{ "code":200,"data":[{ "schemeId":"2020001","name":"标准方案","status":"ACTIVE" },{ "schemeId":"2020002","name":"旧方案","status":"INACTIVE" }],"message":"操作成功","success":true }

5.2.3 方案详情

  • GET /v3/admin/contract/scheme/<schemeId>;编辑回显;JWT;幂等;路径 schemeId:string!
  • 响应(完整)ContractSchemeVO 全部 19 字段。不存在返回 510209
  • 示例GET .../2020001{ "code":200,"data":{ "schemeId":"2020001","name":"标准方案","contractPlatform":"12301","contractTemplateCode":"A00001","templateCode":"A00001","status":"ACTIVE" },"message":"操作成功","success":true }

5.2.4 创建方案

  • POST /v3/admin/contract/scheme;新增平台/模板/签约模式配置;JWT;非幂等。
  • 请求体:上述 ContractSchemeRequest 全部 13 字段。响应:上述 ContractSchemeVO 全部 19 字段。
  • 边界/错误name 必填;手机/长度/签署模式校验;未知旅行社 510201
  • 示例:请求 { "name":"标准方案","contractPlatform":"12301","contractTemplateCode":"A00001","contractMode":"STANDARD","signatoryMode":1,"agencyCode":"hulai","sortOrder":10 };响应 { "code":200,"data":{ "schemeId":"2020001","name":"标准方案","status":"ACTIVE" },"message":"操作成功","success":true }

5.2.5 更新方案

  • PUT /v3/admin/contract/scheme/<schemeId>;编辑方案;JWT;目标更新可重试。
  • 入参:路径 schemeId:string! + ContractSchemeRequest 全部字段。响应ContractSchemeVO 全部字段。
  • 边界/错误:已用方案创建的合同不受后续修改影响;不存在 510209
  • 示例:请求 PUT .../2020001 + { "name":"标准方案V2","contractPlatform":"12301","contractMode":"STANDARD" };响应 { "code":200,"data":{ "schemeId":"2020001","name":"标准方案V2","status":"ACTIVE" },"message":"操作成功","success":true }

5.2.6 切换启停状态

  • PUT /v3/admin/contract/scheme/<schemeId>/toggle-status;启用/停用方案;JWT;每次翻转,非幂等。
  • 入参schemeId:string!;无 body。响应ContractSchemeVO 全部字段。不存在 510209
  • 示例PUT .../2020001/toggle-status{ "code":200,"data":{ "schemeId":"2020001","status":"INACTIVE" },"message":"操作成功","success":true }

5.2.7 删除方案

  • DELETE /v3/admin/contract/scheme/<schemeId>;软删除;JWT;不保证重复调用成功。
  • 入参/响应schemeId:string!;成功 data:null,无其他响应字段。
  • 错误/边界:不存在 510209;被产品引用 510218;引用校验不可用 510219
  • 示例DELETE .../2020001{ "code":200,"data":null,"message":"操作成功","success":true }

5.3 AdminContractSchemeAttachmentController4

AttachmentResp 完整字段:attachmentId:string,schemeId:string,fileName:string,ossUrl:string,ossKey:string,fileSize:long,fileType:string,sortOrder:int,createTime:datetime

5.3.1 附件列表

  • GET /v3/admin/contract/scheme/<schemeId>/attachments;按 sortOrder 升序回显;JWT;幂等;schemeId:string!
  • 响应(完整)data[] 每项含 AttachmentResp 全部 9 字段;无配置返回 []
  • 示例GET .../2020001/attachments{ "code":200,"data":[{ "attachmentId":"1010001","schemeId":"2020001","fileName":"service.pdf","ossUrl":"https://example.invalid/a.pdf","ossKey":"contract/a.pdf","fileSize":1024,"fileType":"PDF","sortOrder":10,"createTime":"2026-08-04T10:00:00" }],"message":"操作成功","success":true }

5.3.2 上传附件

  • POST /v3/admin/contract/scheme/<schemeId>/attachments;上传合同方案附件;JWT;非幂等。
  • 入参schemeId:string!;multipart file:file!fileType:string?(PDF/IMAGE/OTHER)sortOrder:int?响应AttachmentResp 全部 9 字段。
  • 错误/边界空文件、超限、OSS 不可用或上传失败都返回 510508
  • 示例POST .../2020001/attachments + file=@service.pdf&fileType=PDF&sortOrder=10{ "code":200,"data":{ "attachmentId":"1010001","schemeId":"2020001","fileType":"PDF","sortOrder":10 },"message":"操作成功","success":true }

5.3.3 删除附件

  • DELETE /v3/admin/contract/scheme/<schemeId>/attachments/<attachmentId>;软删;JWT;路径 schemeId:string!,attachmentId:string!;无 body。
  • 响应/错误:成功 data:null;附件不存在或不属于该方案 510506。已生成合同的旧 URL 不受影响。
  • 示例DELETE .../2020001/attachments/1010001{ "code":200,"data":null,"message":"操作成功","success":true }

5.3.4 更新附件排序

  • PUT /v3/admin/contract/scheme/<schemeId>/attachments/<attachmentId>/sort;JWT;目标更新可重试。
  • 入参:路径 schemeId:string!,attachmentId:string!;body sortOrder:int!(>=0)响应data:null
  • 错误/示例:不存在 510506;负数为参数校验失败。请求 { "sortOrder":20 }{ "code":200,"data":null,"message":"操作成功","success":true }

5.4 AdminContractSchemeTourGuideController4

GuideResp={ guideId:string,schemeId:string,name:string,phone:string|null,licenseNumber:string|null,sortOrder:int,createTime:datetime }GuideSave={ name:string!(max50),phone:string?(11位手机,max20),licenseNumber:string?(max64),sortOrder:int?(>=0) }

5.4.1 导游列表

  • GET /v3/admin/contract/scheme/<schemeId>/tour-guides;JWT;幂等;schemeId:string!;未配导游返回 [],不兜底。
  • 响应(完整)data[] 每项含 GuideResp 全部 7 字段。
  • 示例GET .../2020001/tour-guides{ "code":200,"data":[{ "guideId":"3030001","schemeId":"2020001","name":"张某","phone":"138****8000","licenseNumber":"L-XX-100001","sortOrder":0,"createTime":"2026-08-04T10:00:00" }],"message":"操作成功","success":true }

5.4.2 新增导游

  • POST /v3/admin/contract/scheme/<schemeId>/tour-guides;JWT;创建加锁,非幂等。
  • 入参schemeId:string! + GuideSave 全部 4 字段。响应GuideResp 全部 7 字段。
  • 边界/示例:姓名必填;手机格式错误拒绝。请求 { "name":"张某","phone":"13800138000","licenseNumber":"L-XX-100001","sortOrder":0 }{ "code":200,"data":{ "guideId":"3030001","schemeId":"2020001","name":"张某","phone":"13800138000","licenseNumber":"L-XX-100001","sortOrder":0,"createTime":"2026-08-04T10:00:00" },"message":"操作成功","success":true }

5.4.3 修改导游

  • PUT /v3/admin/contract/scheme/<schemeId>/tour-guides/<guideId>;JWT;目标更新可重试。
  • 入参schemeId:string!,guideId:string! + GuideSave 全部字段。响应GuideResp 全部字段。
  • 错误/示例:不存在/归属不符 510507。请求 { "name":"李某","sortOrder":1 }{ "code":200,"data":{ "guideId":"3030001","schemeId":"2020001","name":"李某","sortOrder":1 },"message":"操作成功","success":true }

5.4.4 删除导游

  • DELETE /v3/admin/contract/scheme/<schemeId>/tour-guides/<guideId>;JWT;不保证重复调用成功。
  • 入参/响应schemeId:string!,guideId:string!;成功 data:null。不存在/归属不符 510507
  • 示例DELETE .../2020001/tour-guides/3030001{ "code":200,"data":null,"message":"操作成功","success":true }

5.5 AdminClauseTemplateController6

ClauseTemplateVO={ templateId:string,name:string,content:string,sortOrder:int,status:string,createTime:datetime }ClauseTemplateRequest={ name:string!,content:string!,sortOrder:int? }

5.5.1 启用模板列表

  • GET /v3/admin/contract/clause-template/list;创建合同时选择;JWT;幂等;无入参。
  • 响应(完整)data[] 每项含 ClauseTemplateVO 全部 6 字段,仅 ACTIVE。
  • 示例GET .../list{ "code":200,"data":[{ "templateId":"401","name":"夏季小团","content":"脱敏示例条款","sortOrder":1,"status":"ACTIVE","createTime":"2026-08-04T10:00:00" }],"message":"操作成功","success":true }

5.5.2 全部模板列表

  • GET /v3/admin/contract/clause-template/list-all;模板管理页;JWT;幂等;无入参。
  • 响应(完整)data[] 每项含 ClauseTemplateVO 全部 6 字段,包含 ACTIVE/INACTIVE。
  • 示例GET .../list-all{ "code":200,"data":[{ "templateId":"401","name":"夏季小团","content":"条款","sortOrder":1,"status":"INACTIVE","createTime":"2026-08-04T10:00:00" }],"message":"操作成功","success":true }

5.5.3 创建补充约定模板

  • POST /v3/admin/contract/clause-template;JWT;非幂等。
  • 请求/响应body ClauseTemplateRequest 全部 3 字段;返回 ClauseTemplateVO 全部 6 字段。名称和内容必填。
  • 示例:请求 { "name":"夏季小团","content":"脱敏示例条款","sortOrder":1 }{ "code":200,"data":{ "templateId":"401","name":"夏季小团","content":"脱敏示例条款","sortOrder":1,"status":"ACTIVE","createTime":"2026-08-04T10:00:00" },"message":"操作成功","success":true }

5.5.4 更新补充约定模板

  • PUT /v3/admin/contract/clause-template/<id>;JWT;可重试。
  • 入参/响应id:string! + ClauseTemplateRequest 全部字段;返回 ClauseTemplateVO 全部字段。旧合同快照不受影响。
  • 错误/示例:不存在 510211。请求 { "name":"夏季小团V2","content":"新条款","sortOrder":2 }{ "code":200,"data":{ "templateId":"401","name":"夏季小团V2","content":"新条款","sortOrder":2,"status":"ACTIVE" },"message":"操作成功","success":true }

5.5.5 切换模板启停

  • PUT /v3/admin/contract/clause-template/<id>/toggle-status;JWT;每次翻转,非幂等。
  • 入参/响应id:string!;无 body;返回 ClauseTemplateVO 全部 6 字段。不存在 510211
  • 示例PUT .../401/toggle-status{ "code":200,"data":{ "templateId":"401","name":"夏季小团","content":"条款","sortOrder":1,"status":"INACTIVE","createTime":"2026-08-04T10:00:00" },"message":"操作成功","success":true }

5.5.6 删除补充约定模板

  • DELETE /v3/admin/contract/clause-template/<id>;JWT;软删;重复调用不保证成功。
  • 入参/响应id:string!;成功 data:null。已创建合同保留快照。不存在 510211
  • 示例DELETE .../401{ "code":200,"data":null,"message":"操作成功","success":true }

5.6 AdminTravelAgencyController11

AgencySimpleResp={ agencyId:string,code,agencyName,isPrimary:int,sortOrder:int,createTime,updateTime }

AgencyResp 完整字段:agencyId:string,code,agencyName,licenseNumber,businessLicenseNumber,agencyCountry,agencyState,agencyCity,agencyDistrict,agencyAddress,transactorName,transactorPhone,email,bankCard,complaintPhone,complaintProvince,complaintCity,complaintAreaCode,complaintAddress,tribunalName,litigationCourt,regionId,businessScope,zjParentId,appId,signKey,teamReportAppId,teamReportSignKey,supportedPlatforms,supportedPlatformsList[],supportedPlatformsLabels[],isPrimary,status,statusLabel,sortOrder,visible,remark,qualifications[],payments[],createTime,updateTimeAgencySave 完整字段:code:string!(2..32,小写字母/数字/-),agencyName:string!(max128),licenseNumber:string?(max64),businessLicenseNumber:string!,agencyCountry,agencyState,agencyCity,agencyDistrict,agencyAddress,transactorName,transactorPhone,email,bankCard,complaintPhone,complaintProvince,complaintCity,complaintAreaCode,complaintAddress,tribunalName,litigationCourt,regionId,businessScope,zjParentId:int?,appId,signKey,teamReportAppId,teamReportSignKey,supportedPlatforms:string(JSON array),isPrimary:int?(0/1),status:string?,sortOrder:int?,visible:int?(0/1),remark

5.6.1 旅行社分页

  • GET /v3/admin/travel-agency/page;管理列表;ADMIN+;幂等。
  • Query全部page:int?,pageSize:int?,status:string?(ENABLED/DISABLED),isPrimary:int?(0/1),agencyName:string?
  • 响应(完整)records[] 每项含上述 AgencyResp 全部字段;顶层 total,page,pageSize
  • 示例GET .../page?page=1&pageSize=10&status=ENABLED{ "code":200,"data":{ "records":[{ "agencyId":"7001","code":"hulai","agencyName":"呼籁旅行社","status":"ENABLED","statusLabel":"启用","qualifications":[],"payments":[] }],"total":1,"page":1,"pageSize":10 },"message":"操作成功","success":true }

5.6.2 启用旅行社下拉

  • GET /v3/admin/travel-agency/enabled;ADMIN+;幂等;无入参。
  • 响应(完整)data[] 每项含 AgencySimpleResp 全部 7 字段。
  • 示例GET .../enabled{ "code":200,"data":[{ "agencyId":"7001","code":"hulai","agencyName":"呼籁旅行社","isPrimary":1,"sortOrder":1,"createTime":"2026-08-01T10:00:00","updateTime":"2026-08-04T10:00:00" }],"message":"操作成功","success":true }

5.6.3 产品页可用旅行社

  • GET /v3/admin/travel-agency/enabled-for-product;过滤经营许可证号为空的公司;ADMIN+;幂等;无入参。
  • 响应(完整)data[] 每项含 AgencySimpleResp 全部 7 字段。
  • 示例GET .../enabled-for-product{ "code":200,"data":[{ "agencyId":"7001","code":"hulai","agencyName":"呼籁旅行社","isPrimary":1,"sortOrder":1,"createTime":"2026-08-01T10:00:00","updateTime":"2026-08-04T10:00:00" }],"message":"操作成功","success":true }

5.6.4 按合同平台筛选旅行社

  • GET /v3/admin/travel-agency/enabled-by-platform;合同方案下拉;ADMIN+;幂等。
  • QuerycontractPlatform:string! (12301/TENCENT_ESIGN)。响应AgencySimpleResp 全部 7 字段;主体公司优先、ID 升序。
  • 边界/示例:空值返回“合同平台不能为空”。GET .../enabled-by-platform?contractPlatform=12301{ "code":200,"data":[{ "agencyId":"7001","code":"hulai","agencyName":"呼籁旅行社","isPrimary":1,"sortOrder":1,"createTime":"2026-08-01T10:00:00","updateTime":"2026-08-04T10:00:00" }],"message":"操作成功","success":true }

5.6.5 旅行社详情

  • GET /v3/admin/travel-agency/<id>;含资质和支付子表;ADMIN+;幂等;id:string!
  • 响应(完整):上述 AgencyResp 全部字段;qualifications[] 字段见 5.7;payments[] 字段见 5.8。不存在 594001
  • 示例GET .../7001{ "code":200,"data":{ "agencyId":"7001","code":"hulai","agencyName":"呼籁旅行社","status":"ENABLED","qualifications":[],"payments":[] },"message":"操作成功","success":true }

5.6.6 新建旅行社

  • POST /v3/admin/travel-agency;SUPER_ADMIN;非幂等。
  • 请求体:上述 AgencySave 全部 33 字段。响应data:string 新 agencyId,无其他 data 字段。
  • 边界/错误:编码重复 594010;非 SUPER_ADMIN 594009;编码格式/必填/长度校验。高敏 key 不得打印。
  • 示例:请求 { "code":"demo-agency","agencyName":"示例旅行社","businessLicenseNumber":"9115********0001","supportedPlatforms":"[\"12301\"]","status":"ENABLED","isPrimary":0,"visible":1 }{ "code":200,"data":"7002","message":"操作成功","success":true }

5.6.7 编辑旅行社

  • PUT /v3/admin/travel-agency/<id>;ADMIN+;目标更新可重试。
  • 入参/响应id:string! + AgencySave 全部字段;成功 data:nullcode 编辑时不可改。
  • 错误/示例:不存在 594001。请求 { "code":"hulai","agencyName":"呼籁旅行社","businessLicenseNumber":"9115********0001","status":"ENABLED" }{ "code":200,"data":null,"message":"操作成功","success":true }

5.6.8 停用旅行社

  • PUT /v3/admin/travel-agency/<id>/disable;ADMIN+;路径 id:string!;无 body;目标状态幂等。
  • 响应/错误:成功 data:null;不存在 594001;主体公司不可停用 594005
  • 示例PUT .../7002/disable{ "code":200,"data":null,"message":"操作成功","success":true }

5.6.9 启用旅行社

  • PUT /v3/admin/travel-agency/<id>/enable;ADMIN+;路径 id:string!;无 body;目标状态幂等。
  • 响应/错误:成功 data:null;不存在 594001
  • 示例PUT .../7002/enable{ "code":200,"data":null,"message":"操作成功","success":true }

5.6.10 删除旅行社

  • DELETE /v3/admin/travel-agency/<id>;ADMIN+;强保留语义(状态置 DISABLED;不保证重复调用成功。
  • 入参/响应id:string!;成功 data:null
  • 错误/边界594001;主体公司 594005;本接口不做物理删除。
  • 示例DELETE .../7002{ "code":200,"data":null,"message":"操作成功","success":true }

5.6.11 设为主体公司

  • PUT /v3/admin/travel-agency/<id>/set-primary;SUPER_ADMIN;路径 id:string!;无 body;目标状态幂等。
  • 响应/错误:成功 data:null594001;目标停用或主体约束失败 594005/594006;非 SUPER_ADMIN 594009
  • 示例PUT .../7001/set-primary{ "code":200,"data":null,"message":"操作成功","success":true }

5.7 AdminTravelAgencyQualificationController4

QualificationResp={ qualificationId:string,agencyId:string,name,qualificationType,qualificationTypeLabel,fileUrl,fileType,fileTypeLabel,issueDate,expireDate,sortOrder,remark,createTime,updateTime }QualificationSave={ name:string!(max64),qualificationType:string!(max32),fileUrl:string!,fileType:string?(PDF/IMAGE/OTHER),issueDate:date?,expireDate:date|null,sortOrder:int?,remark:string? }

5.7.1 资质列表

  • GET /v3/admin/travel-agency/<agencyId>/qualification;ADMIN+;幂等;agencyId:string!
  • 响应(完整)data[] 每项含 QualificationResp 全部 14 字段;fileUrl 为有效期 30 分钟的临时 URL。
  • 示例GET .../7001/qualification{ "code":200,"data":[{ "qualificationId":"8001","agencyId":"7001","name":"旅行社业务经营许可证","qualificationType":"TRAVEL_AGENCY_LICENSE","qualificationTypeLabel":"旅行社业务经营许可证","fileUrl":"https://example.invalid/temp?token=masked","fileType":"PDF","fileTypeLabel":"PDF","issueDate":"2024-01-01","expireDate":null,"sortOrder":1,"remark":null,"createTime":"2026-08-01T10:00:00","updateTime":"2026-08-01T10:00:00" }],"message":"操作成功","success":true }

5.7.2 新增资质

  • POST /v3/admin/travel-agency/<agencyId>/qualification;ADMIN+;非幂等。
  • 入参/响应agencyId:string! + QualificationSave 全部 8 字段;成功 data:string 新 qualificationId。
  • 错误/边界:文件无效(>10MB、非 PDF/JPG/PNG、上传失败594008;长期有效传 expireDate:null
  • 示例:请求 { "name":"旅行社业务经营许可证","qualificationType":"TRAVEL_AGENCY_LICENSE","fileUrl":"oss://private/masked.pdf","fileType":"PDF","issueDate":"2024-01-01","expireDate":null,"sortOrder":1 }{ "code":200,"data":"8001","message":"操作成功","success":true }

5.7.3 编辑资质

  • PUT /v3/admin/travel-agency/<agencyId>/qualification/<qualificationId>;ADMIN+;目标更新可重试。
  • 入参/响应:路径中 agencyId 用于 URL 归类,后端操作键为 qualificationId:string!;body QualificationSave 全部字段;成功 data:null
  • 错误/示例:不存在 594001;文件无效 594008。请求 { "name":"经营许可证(新)","qualificationType":"TRAVEL_AGENCY_LICENSE","fileUrl":"oss://private/masked.pdf","fileType":"PDF" }{ "code":200,"data":null,"message":"操作成功","success":true }

5.7.4 删除资质

  • DELETE /v3/admin/travel-agency/<agencyId>/qualification/<qualificationId>;ADMIN+;软删;不保证重复调用成功。
  • 入参/响应qualificationId:string!;成功 data:null;不存在 594001
  • 示例DELETE .../7001/qualification/8001{ "code":200,"data":null,"message":"操作成功","success":true }

5.8 AdminTravelAgencyPaymentController5

PaymentResp={ paymentId:string,agencyId:string,name,mchId,appId,apiV3Key,mchSerialNo,publicKeyId,privateKeyPath,publicKeyPath,isDefault:int,status,statusLabel,remark,createTime,updateTime }PaymentSave={ name:string!(max64),mchId:string!(max32),appId:string!(max64),apiV3Key:string!,mchSerialNo:string?,publicKeyId:string?,isDefault:int?(0/1),status:string?(ENABLED/DISABLED),remark:string? }。这些接口包含高敏密钥/证书信息,仅 SUPER_ADMIN 使用,响应不得写入日志、埋点或客户端持久存储。

5.8.1 支付配置列表

  • GET /v3/admin/travel-agency/<agencyId>/payment;SUPER_ADMIN;幂等;agencyId:string!
  • 响应(完整)data[] 每项含 PaymentResp 全部 16 字段。
  • 示例(脱敏)GET .../7001/payment{ "code":200,"data":[{ "paymentId":"9001","agencyId":"7001","name":"微信支付-主商户","mchId":"1106******39","appId":"wx************ff36","apiV3Key":"***","mchSerialNo":"***","publicKeyId":"PUB_***","privateKeyPath":"cert/***/apiclient_key.pem","publicKeyPath":"cert/***/public_key.pem","isDefault":1,"status":"ENABLED","statusLabel":"启用","remark":null,"createTime":"2026-08-01T10:00:00","updateTime":"2026-08-01T10:00:00" }],"message":"操作成功","success":true }

5.8.2 新增支付配置

  • POST /v3/admin/travel-agency/<agencyId>/payment;SUPER_ADMIN;非幂等。
  • 入参/响应agencyId:string! + PaymentSave 全部 9 字段;成功 data:string 新 paymentId。privateKeyPath/publicKeyPath 不接受前端传入。
  • 错误/边界:商户号重复 594011;非 SUPER_ADMIN 594009;必填/长度校验。
  • 示例(虚构):请求 { "name":"微信支付-主商户","mchId":"1900000001","appId":"wxdemo000000000001","apiV3Key":"***REDACTED***","mchSerialNo":"***REDACTED***","publicKeyId":"PUB_DEMO","isDefault":1,"status":"ENABLED" }{ "code":200,"data":"9001","message":"操作成功","success":true }

5.8.3 编辑支付配置

  • PUT /v3/admin/travel-agency/<agencyId>/payment/<paymentId>;SUPER_ADMIN;目标更新可重试。
  • 入参/响应URL 含 agencyId,操作键为 paymentId:string!;body PaymentSave 全部字段;成功 data:null
  • 错误/示例:不存在 594001;商户号冲突 594011。请求 { "name":"微信支付-主商户","mchId":"1900000001","appId":"wxdemo000000000001","apiV3Key":"***REDACTED***","status":"ENABLED" }{ "code":200,"data":null,"message":"操作成功","success":true }

5.8.4 删除支付配置

  • DELETE /v3/admin/travel-agency/<agencyId>/payment/<paymentId>;SUPER_ADMIN;不保证重复调用成功。
  • 入参/响应paymentId:string!;成功 data:null
  • 错误/边界:不存在 594001;默认商户不可删 594007,须先将另一条设为默认。
  • 示例DELETE .../7001/payment/9002{ "code":200,"data":null,"message":"操作成功","success":true }

5.8.5 设为默认支付商户

  • PUT /v3/admin/travel-agency/<agencyId>/payment/<paymentId>/set-default;SUPER_ADMIN;目标状态幂等。
  • 入参/响应agencyId:string!,paymentId:string!;无 body;成功 data:null
  • 错误/边界:支付配置不存在/归属不符 594001;同一公司最多一条 isDefault=1
  • 示例PUT .../7001/payment/9001/set-default{ "code":200,"data":null,"message":"操作成功","success":true }

6. 枚举/数据字典(按类型分表)

6.1 contract_status

中文 说明
PENDING 待生成 初始等待
GENERATED 已生成 合同已生成,待签署
SIGNING 签署中 平台签署流程中
SIGNED 已签署 签署完成
REPORTED 已上报 SYNC 报备完成
UPLOADED 已上传 SYNC PDF 已上传
VOIDING 作废中 等待平台确认
VOIDED 已作废 终态

6.2 contract_platform

中文 说明
12301 12301 团队报送 监管平台
LOCAL 本地/线下 本地报备
TENCENT_ESIGN 腾讯电子签 电子签约

6.3 contract_mode

中文 说明
STANDARD 电子签约 平台生成并签署
SYNC 线下报备 线下签署后报备/上传

6.4 common_status / contract_scheme_status / contract_template_status

中文 说明
ACTIVE 启用 可供新业务选择
INACTIVE 停用 历史引用不受影响

6.5 contract_attachment_type

中文 说明
PDF PDF PDF 附件
IMAGE 图片 图片附件
OTHER 其他 其他文件

6.6 agency_status

中文 说明
ENABLED 启用 可被产品/合同选择
DISABLED 停用 不可用于新业务

6.7 agency_contract_platform

中文 说明
12301 12301 团队报送 旅行社已开通 12301
TENCENT_ESIGN 腾讯电子签 旅行社已开通腾讯电子签

6.8 agency_qualification_type

中文 说明
BUSINESS_LICENSE 营业执照 公司营业执照
TRAVEL_AGENCY_LICENSE 旅行社业务经营许可证 旅行社经营资质
VALUE_ADDED_TELECOM_LICENSE 增值电信业务经营许可证 电信业务资质

6.9 agency_qualification_file_type

中文 说明
PDF PDF PDF 文件
IMAGE 图片 JPG/PNG 等
OTHER 其他 其他类型(服务端仍会做安全校验)

6.10 其他取值

字段 说明
contractType TOUR / INSURANCE 旅游合同 / 保险单
signatoryMode 1 / 2 / 3 短信 / 现场 / 线下
paymentMethod 1 / 2 / 3 现金 / 转账 / 在线
disputeResolution 1 / 2 诉讼 / 仲裁
insurancePurchaseMethod 1 / 2 / 3 委托旅行社 / 自行购买 / 放弃
gender 0 / 1 / 2 未知 / 男 / 女
idCardType 1 / 2 身份证 / 护照
channel MP / ADMIN / CHANNEL / null 小程序 / 管理端 / 分销 / 兜底

7. 错误码摘要

code 含义 典型接口
510001 合同不存在 详情/作废/下载/刷新/上传
510005-510008 短信重发状态、频控或必要数据缺失 重发短信
510101-510107 下载/刷新/作废/PDF 上传业务校验 合同写操作
510201-510220 旅行社、方案、模板、订单、签署人及重复合同校验 创建/方案管理
510403 腾讯电子签不支持 SYNC 报备合同
510506-510508 附件/导游不存在或上传失败 方案附件/导游
594001 旅行社或其子资源不存在 旅行社/资质/支付
594005-594006 主体公司约束 停用/删除/设为主体
594007 默认支付商户不可删 删除支付配置
594008 资质文件无效 新增/编辑资质
594009 仅 SUPER_ADMIN 可执行 敏感管理操作
594010 旅行社编码重复 新建旅行社
594011 微信支付商户号冲突 新增/编辑支付配置

验证证据

  • PR #5501 已合并merge commit 45117d3d5896515909e303dcbfa9d3616f881803,head f66d236f2aea2d0a63db8cb58d59f2ae74e2b6fb
  • 基于合并代码静态核对 8 个 admin Controller,端点计数 15+7+4+4+6+11+4+5=56
  • 文档本地自检56 个接口小节、只有目标文件进入 commit、git diff --check 通过。
  • deploy-panel 任务 0eae2ffb 执行成功;hl-order-service-v3dev-v3 的 8086/8186 双实例均为 UP。
  • 通过已登录管理后台的有效 Gateway 鉴权完成合同列表真实 HTTP 验证:code=200total=118;共12个只读用例覆盖 orderNo 精确/模糊/trim、teamNo%/_ 字面匹配等边界。
  • 真实非空样本为 orderNo=HL20260803220907715teamNo=26-2489;随后在同一鉴权会话打开目标合同 MOCK-2084280429048741890 详情,详情显示 teamNo=26-2489 且含列表外字段,证明详情调用成功且列表/详情一致。
  • QA 证据报告:D:/work/project-doc/PRPs/reports/5368-contract-teamno-gateway-acceptance.md,状态仍为 PARTIAL。原因是详情页含未脱敏联系电话/签署链接,为避免 PII 落盘未保存截图;运行时列表与详情功能门禁已验证。
  • 本次未查询数据库实时行;上述结论来自部署状态与真实 Gateway HTTP/管理后台详情调用。

8. 业务边界与 v1/v3 数据隔离

  • 根据 Issue #5368 在 2026-08-04 的决策,管理后台合同整页的列表、详情、创建、作废、刷新、下载、短信和上传统一调用 /v3/admin/*
  • v1 存量合同不迁移,自然消亡;新合同全部走 v3。
  • v1 与 v3 合同数据不互通;不得把 v3 响应的 contractId 传给 v1 端点,也不得用 v3 详情读 v1 旧 ID。
  • teamNo 未生成时为 null;不得用 orderNo 伪装团号。
  • 列表多条件为 AND;文本筛选是数据库分页前的包含匹配,total 与翻页结果一致。

9. 修改前后对比

维度 修改前 修改后
订单号搜索 合同列表不能独立按 orderNo 查询 可传 orderNo 包含匹配
文本空白 语义未完整固化 三个文本条件 trim,全空白忽略
LIKE 特殊字符 可能被当作通配符 %_\ 按字面字符
数据版本 前端可能仍混用 v1/v3 合同整页读写统一 v3,v1 存量不迁移

10. 影响评估/回滚

  • 向后兼容:是。orderNo 为新增可选 query;原有参数和响应字段不删除。
  • 前端是否必须同步上线:不必与后端强绑同时上线;但合同页应尽快切到本文的 v3 端点,否则无法正确消费 v3 数据。
  • 回滚后前端行为:停止传递 orderNo;保留原 teamNo/contactName 及其他查询。不得回滚为 v1/v3 混用。

11. 注意事项

  • 前端可清理“拉全量合同后在浏览器按订单号过滤”的 workaround,直接传 orderNo
  • 请求参数中用户输入的 %_\ 不需前端自行转义;正常 URL 编码即可。
  • 支付配置、证书、身份证、手机号和签约密钥都不得写入前端日志/埋点;本文示例全部为虚构脱敏值。

12. 关联/联系人

关联/联系人

链接

联系人

  • 后端负责人: @wx