// Package house_listing 提供房源/挂牌领域服务。 package house_listing import ( "context" "github.com/gogf/gf/v2/errors/gerror" "service.xpcool.com/internal/consts" "service.xpcool.com/internal/dao" "service.xpcool.com/internal/library/response" "service.xpcool.com/internal/model/do" "service.xpcool.com/internal/model/dto" ) // IListing 房源/挂牌领域服务接口。 type IListing interface { List(context.Context, dto.HouseListingFilter) ([]dto.HouseListingVO, int, error) Create(context.Context, dto.HouseListingInput) (uint64, error) Update(context.Context, dto.HouseListingInput) error Delete(context.Context, uint64) error BatchMark(context.Context, []uint64, string, int) (int64, error) } type listing struct{} var localListing IListing func NewListing() IListing { return &listing{} } // Listing 返回已注册的房源服务实现。 func Listing() IListing { if localListing == nil { panic("Listing implementation not registered") } return localListing } // RegisterListing 注册房源服务实现。 func RegisterListing(i IListing) { localListing = i } // List 分页查询房源,关联小区名,支持多维筛选(管理列表与看板共用)。 func (s *listing) List(ctx context.Context, f dto.HouseListingFilter) ([]dto.HouseListingVO, int, error) { m := dao.HouseListing.Ctx(ctx).As("l").LeftJoin("house_community c", "l.community_id=c.id") m = m.Fields("l.*, c.name AS community_name") if f.CommunityId > 0 { m = m.Where("l.community_id", f.CommunityId) } if f.Keyword != "" { m = m.Where("l.house_no LIKE ? OR l.layout LIKE ?", "%"+f.Keyword+"%", "%"+f.Keyword+"%") } if f.Layout != "" { m = m.Where("l.layout", f.Layout) } if f.Source != "" { m = m.Where("l.source", f.Source) } if f.Region != "" { m = m.Where("c.region", f.Region) } if f.PriceMin > 0 { m = m.WhereGTE("l.total_price", f.PriceMin) } if f.PriceMax > 0 { m = m.WhereLTE("l.total_price", f.PriceMax) } if f.AreaMin > 0 { m = m.WhereGTE("l.area", f.AreaMin) } if f.AreaMax > 0 { m = m.WhereLTE("l.area", f.AreaMax) } if f.Status > 0 { m = m.Where("l.status", f.Status) } if f.IsBargain > 0 { m = m.Where("l.is_bargain", 1) } if f.Confidence > 0 { m = m.Where("l.confidence", 1) } total, err := m.Clone().Count() if err != nil { return nil, 0, gerror.Wrap(err, "count listing") } var list []dto.HouseListingVO if err = m.Clone().Page(f.Page, f.Size).OrderDesc("l.id").Scan(&list); err != nil { return nil, 0, gerror.Wrap(err, "query listing list") } return list, total, nil } // Create 新增房源。 func (s *listing) Create(ctx context.Context, in dto.HouseListingInput) (uint64, error) { id, err := dao.HouseListing.Ctx(ctx).Data(do.HouseListing{ CommunityId: in.CommunityId, BuildingId: in.BuildingId, HouseNo: in.HouseNo, Layout: in.Layout, Area: in.Area, UsableArea: in.UsableArea, Orientation: in.Orientation, Floor: in.Floor, TotalFloors: in.TotalFloors, Decoration: in.Decoration, TotalPrice: in.TotalPrice, UnitPrice: in.UnitPrice, ListPrice: in.ListPrice, Source: in.Source, SourceHouseId: in.SourceHouseId, SourceUrl: in.SourceUrl, MatchGroupId: in.MatchGroupId, OnMarketDays: in.OnMarketDays, PriceChangeCount: in.PriceChangeCount, Status: in.Status, Confidence: in.Confidence, IsBargain: in.IsBargain, }).InsertAndGetId() if err != nil { return 0, gerror.Wrap(err, "insert listing") } return uint64(id), nil } // Update 更新房源。 func (s *listing) Update(ctx context.Context, in dto.HouseListingInput) error { _, err := dao.HouseListing.Ctx(ctx).Where(do.HouseListing{Id: in.Id}).Data(do.HouseListing{ CommunityId: in.CommunityId, BuildingId: in.BuildingId, HouseNo: in.HouseNo, Layout: in.Layout, Area: in.Area, UsableArea: in.UsableArea, Orientation: in.Orientation, Floor: in.Floor, TotalFloors: in.TotalFloors, Decoration: in.Decoration, TotalPrice: in.TotalPrice, UnitPrice: in.UnitPrice, ListPrice: in.ListPrice, MatchGroupId: in.MatchGroupId, Status: in.Status, Confidence: in.Confidence, IsBargain: in.IsBargain, }).Update() if err != nil { return gerror.Wrap(err, "update listing") } return nil } // Delete 软删除房源。 func (s *listing) Delete(ctx context.Context, id uint64) error { if _, err := dao.HouseListing.Ctx(ctx).Where(do.HouseListing{Id: id}).Delete(); err != nil { return gerror.Wrap(err, "delete listing") } return nil } // BatchMark 批量标记房源(置信度/笋盘/状态),字段白名单防注入。 func (s *listing) BatchMark(ctx context.Context, ids []uint64, field string, value int) (int64, error) { var data do.HouseListing switch field { case "confidence": data = do.HouseListing{Confidence: value} case "isBargain": data = do.HouseListing{IsBargain: value} case "status": data = do.HouseListing{Status: value} default: return 0, response.Error(consts.CodeInvalidParam, "unsupported mark field") } res, err := dao.HouseListing.Ctx(ctx).WhereIn("id", ids).Data(data).Update() if err != nil { return 0, gerror.Wrap(err, "batch mark listing") } affected, _ := res.RowsAffected() return affected, nil }