From 8c5e139bfd45d761326ffbc21c3897e2b97e4ff3 Mon Sep 17 00:00:00 2001 From: xiaoqu Date: Mon, 26 Oct 2026 17:56:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(sync):=20=E6=96=B0=E5=A2=9E=20buildings=20?= =?UTF-8?q?=E6=B5=81=E8=BE=93=E5=87=BA=E6=A5=BC=E5=BA=A7=E5=9D=90=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/me/iiv/agent/entity/m0/Building.java | 57 ++++++++++++++++++ .../iiv/agent/mapper/m0/BuildingMapper.java | 7 +++ .../agent/mcp/sync/BuildingsSyncEntity.java | 60 +++++++++++++++++++ .../iiv/agent/mcp/sync/SyncChangeSchemas.java | 15 +++++ .../me/iiv/agent/mcp/tool/ChangesTools.java | 11 ++++ 5 files changed, 150 insertions(+) create mode 100644 xiaoqu-agent-service/src/main/java/me/iiv/agent/entity/m0/Building.java create mode 100644 xiaoqu-agent-service/src/main/java/me/iiv/agent/mapper/m0/BuildingMapper.java create mode 100644 xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/BuildingsSyncEntity.java diff --git a/xiaoqu-agent-service/src/main/java/me/iiv/agent/entity/m0/Building.java b/xiaoqu-agent-service/src/main/java/me/iiv/agent/entity/m0/Building.java new file mode 100644 index 0000000..dd78dad --- /dev/null +++ b/xiaoqu-agent-service/src/main/java/me/iiv/agent/entity/m0/Building.java @@ -0,0 +1,57 @@ +package me.iiv.agent.entity.m0; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; +import java.util.Date; + +/** 楼座(b0.building):设备安装的物理位置,含经纬度。 */ +@TableName("building") +public class Building implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + private String name; + private Long propertyId; + private String address; + private String province; + private String city; + private String countyseat; + private Double longitude; + private Double latitude; + + @TableField("soft_delete") + private Integer softDelete; + + @TableField("create_time") + private Date createTime; + + @TableField("modify_time") + private Date modifyTime; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public String getName() { return name; } + public void setName(String name) { this.name = name; } + public Long getPropertyId() { return propertyId; } + public void setPropertyId(Long propertyId) { this.propertyId = propertyId; } + public String getAddress() { return address; } + public void setAddress(String address) { this.address = address; } + public String getProvince() { return province; } + public void setProvince(String province) { this.province = province; } + public String getCity() { return city; } + public void setCity(String city) { this.city = city; } + public String getCountyseat() { return countyseat; } + public void setCountyseat(String countyseat) { this.countyseat = countyseat; } + public Double getLongitude() { return longitude; } + public void setLongitude(Double longitude) { this.longitude = longitude; } + public Double getLatitude() { return latitude; } + public void setLatitude(Double latitude) { this.latitude = latitude; } + public Integer getSoftDelete() { return softDelete; } + public void setSoftDelete(Integer softDelete) { this.softDelete = softDelete; } + public Date getCreateTime() { return createTime; } + public void setCreateTime(Date createTime) { this.createTime = createTime; } + public Date getModifyTime() { return modifyTime; } + public void setModifyTime(Date modifyTime) { this.modifyTime = modifyTime; } +} diff --git a/xiaoqu-agent-service/src/main/java/me/iiv/agent/mapper/m0/BuildingMapper.java b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mapper/m0/BuildingMapper.java new file mode 100644 index 0000000..dba9824 --- /dev/null +++ b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mapper/m0/BuildingMapper.java @@ -0,0 +1,7 @@ +package me.iiv.agent.mapper.m0; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import me.iiv.agent.entity.m0.Building; + +public interface BuildingMapper extends BaseMapper { +} diff --git a/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/BuildingsSyncEntity.java b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/BuildingsSyncEntity.java new file mode 100644 index 0000000..8d78a5f --- /dev/null +++ b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/BuildingsSyncEntity.java @@ -0,0 +1,60 @@ +package me.iiv.agent.mcp.sync; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import me.iiv.agent.entity.m0.Building; +import me.iiv.agent.entity.m0.User; +import me.iiv.agent.mapper.m0.BuildingMapper; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** buildings 同步实体(b0.building 楼座,含经纬度)。 */ +@Component +public class BuildingsSyncEntity extends AbstractSyncEntity implements SyncEntity { + + public static final String NAME = "buildings"; + + final BuildingMapper buildingMapper; + + public BuildingsSyncEntity(BuildingMapper buildingMapper) { + this.buildingMapper = buildingMapper; + } + + @Override + public String name() { + return NAME; + } + + @Override + public List fetchPage(Long fromTs, long cutoffTs, Long cursorMt, Long cursorId, + int limit, User user) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + applyWindow(wrapper, fromTs, cutoffTs, cursorMt, cursorId); + applyOrderAndLimit(wrapper, limit); + List rows = buildingMapper.selectList(wrapper); + List out = new ArrayList<>(rows.size()); + for (Building row : rows) { + long mt = ChangesEngine.effectiveTs(row.getModifyTime(), row.getCreateTime()); + out.add(new SyncRow(toItem(row, mt), mt, row.getId())); + } + return out; + } + + private Map toItem(Building row, long mt) { + boolean deleted = row.getSoftDelete() != null && row.getSoftDelete() == 1; + Date effective = row.getModifyTime() != null ? row.getModifyTime() : row.getCreateTime(); + return SyncChangeSchemas.toMap(new SyncChangeSchemas.BuildingChange( + stableId(row.getId()), stableId(row.getPropertyId()), + row.getName(), row.getAddress(), + row.getProvince(), row.getCity(), row.getCountyseat(), + row.getLongitude(), row.getLatitude(), + ChangesEngine.iso(effective), mt, deleted ? ChangesEngine.iso(effective) : null)); + } + + private static String stableId(Long id) { + return id == null ? null : String.valueOf(id); + } +} diff --git a/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/SyncChangeSchemas.java b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/SyncChangeSchemas.java index 6572f95..261ce0d 100644 --- a/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/SyncChangeSchemas.java +++ b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/SyncChangeSchemas.java @@ -85,6 +85,21 @@ final class SyncChangeSchemas { @JsonProperty("deleted_at") String deletedAt) { } + record BuildingChange( + @JsonProperty("building_id") String buildingId, + @JsonProperty("property_id") String propertyId, + String name, + String address, + String province, + String city, + String countyseat, + Double longitude, + Double latitude, + @JsonProperty("updated_at") String updatedAt, + long version, + @JsonProperty("deleted_at") String deletedAt) { + } + record ContractChange( @JsonProperty("contract_id") String contractId, @JsonProperty("contract_no") String contractNo, diff --git a/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/tool/ChangesTools.java b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/tool/ChangesTools.java index 5713d55..bea9bc9 100644 --- a/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/tool/ChangesTools.java +++ b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/tool/ChangesTools.java @@ -88,6 +88,17 @@ public class ChangesTools implements ToolObject { return changesEngine.execute(PropertiesSyncEntity.NAME, syncToken, cursor, limit); } + @XqTool(category = "sync", kind = "read") + @Tool(name = "buildings.changes.list", description = "增量同步楼座主数据(b0.building,含经纬度)。" + PROTOCOL_DESC + + "items 字段:building_id/property_id/name/address/province/city/countyseat/" + + "longitude/latitude/updated_at/version/deleted_at。") + public Map buildingsChangesList( + @ToolParam(required = false, description = SYNC_TOKEN_DESC) String syncToken, + @ToolParam(required = false, description = CURSOR_DESC) String cursor, + @ToolParam(required = false, description = LIMIT_DESC) Integer limit) { + return changesEngine.execute(BuildingsSyncEntity.NAME, syncToken, cursor, limit); + } + @XqTool(category = "sync", kind = "read") @Tool(name = "contracts.changes.list", description = "增量同步合同主数据(m2.contract_new)。" + PROTOCOL_DESC + "items 字段:contract_id/contract_no/contract_name/status(PENDING/REJECTED/ACTIVE/EXPIRED/TERMINATED)/"