Some checks failed
Build and Deploy (service.xpcool.com) / build-and-deploy (push) Failing after 35s
- 新增新房预售证表 house_presale 存储预售许可信息 - 为 house_community 表添加 avg_price 字段存储小区参考均价 - 增强服务器操作审计日志功能,新增管理员账号、IP归属地、错误信息、UA等字段 - 实现纯Go版IP归属地离线解析器,无外部依赖,支持二分查找 - 优化看房列表查询逻辑,修复Fields设置位置导致的SQL语法错误 - 集成招聘模块,添加独立数据库配置和Bark推送服务支持 - 重构日志查询接口,支持多维度筛选和综合分页列表展示 - 更新DAO实体结构同步数据库表结构调整
179 lines
5.3 KiB
Go
179 lines
5.3 KiB
Go
// 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")
|
|
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().Fields("l.*, c.name AS community_name").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
|
|
}
|