新增房产AI
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
package com.gxwebsoft.house.controller;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.core.utils.JSONUtil;
|
||||||
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
|
import com.gxwebsoft.common.core.websocket.WebSocketServer;
|
||||||
|
import com.gxwebsoft.house.entity.HouseAiChatRequest;
|
||||||
|
import com.gxwebsoft.house.entity.HouseAiChatResponse;
|
||||||
|
import com.gxwebsoft.house.service.HouseAiChatService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房聊天控制器
|
||||||
|
*/
|
||||||
|
@Tag(name = "AI找房问答")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/house/ai-chat")
|
||||||
|
public class HouseAiChatController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private HouseAiChatService houseAiChatService;
|
||||||
|
@Resource
|
||||||
|
private WebSocketServer webSocketServer;
|
||||||
|
|
||||||
|
@Operation(summary = "发送AI找房问题")
|
||||||
|
@PostMapping("/message")
|
||||||
|
public ApiResult<?> message(@RequestBody HouseAiChatRequest request) {
|
||||||
|
if (request.getUserId() == null || request.getQuestion() == null || request.getQuestion().trim().isEmpty()) {
|
||||||
|
return fail("提问内容不能为空");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
HouseAiChatResponse response = houseAiChatService.answer(request);
|
||||||
|
webSocketServer.sendMessage(String.valueOf(request.getUserId()), JSONUtil.toJSONString(response));
|
||||||
|
return success("处理成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
return fail("AI服务暂时不可用,请稍后再试。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package com.gxwebsoft.house.controller;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||||
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
|
import com.gxwebsoft.common.core.web.BatchParam;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.house.entity.HouseAiConfig;
|
||||||
|
import com.gxwebsoft.house.param.HouseAiConfigParam;
|
||||||
|
import com.gxwebsoft.house.service.HouseAiConfigService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房配置控制器
|
||||||
|
*/
|
||||||
|
@Tag(name = "AI找房配置管理")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/house/ai-config")
|
||||||
|
public class HouseAiConfigController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private HouseAiConfigService houseAiConfigService;
|
||||||
|
|
||||||
|
@Operation(summary = "分页查询AI找房配置")
|
||||||
|
@GetMapping("/page")
|
||||||
|
public ApiResult<PageResult<HouseAiConfig>> page(HouseAiConfigParam param) {
|
||||||
|
return success(houseAiConfigService.pageRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询全部AI找房配置")
|
||||||
|
@GetMapping()
|
||||||
|
public ApiResult<List<HouseAiConfig>> list(HouseAiConfigParam param) {
|
||||||
|
return success(houseAiConfigService.listRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询当前租户AI找房配置")
|
||||||
|
@GetMapping("/current")
|
||||||
|
public ApiResult<HouseAiConfig> current() {
|
||||||
|
return success(houseAiConfigService.getCurrentConfig(getTenantId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "根据id查询AI找房配置")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ApiResult<HouseAiConfig> get(@PathVariable("id") Integer id) {
|
||||||
|
return success(houseAiConfigService.getByIdRel(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "添加AI找房配置")
|
||||||
|
@PostMapping()
|
||||||
|
public ApiResult<?> save(@RequestBody HouseAiConfig houseAiConfig) {
|
||||||
|
if (houseAiConfigService.save(houseAiConfig)) {
|
||||||
|
return success("添加成功");
|
||||||
|
}
|
||||||
|
return fail("添加失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "修改AI找房配置")
|
||||||
|
@PutMapping()
|
||||||
|
public ApiResult<?> update(@RequestBody HouseAiConfig houseAiConfig) {
|
||||||
|
if (houseAiConfigService.updateById(houseAiConfig)) {
|
||||||
|
return success("修改成功");
|
||||||
|
}
|
||||||
|
return fail("修改失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "删除AI找房配置")
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||||
|
if (houseAiConfigService.removeById(id)) {
|
||||||
|
return success("删除成功");
|
||||||
|
}
|
||||||
|
return fail("删除失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "批量修改AI找房配置")
|
||||||
|
@PutMapping("/batch")
|
||||||
|
public ApiResult<?> updateBatch(@RequestBody BatchParam<HouseAiConfig> batchParam) {
|
||||||
|
if (batchParam.update(houseAiConfigService, "config_id")) {
|
||||||
|
return success("修改成功");
|
||||||
|
}
|
||||||
|
return fail("修改失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "批量删除AI找房配置")
|
||||||
|
@DeleteMapping("/batch")
|
||||||
|
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||||
|
if (houseAiConfigService.removeByIds(ids)) {
|
||||||
|
return success("删除成功");
|
||||||
|
}
|
||||||
|
return fail("删除失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package com.gxwebsoft.house.controller;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||||
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
|
import com.gxwebsoft.common.core.web.BatchParam;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.common.system.entity.User;
|
||||||
|
import com.gxwebsoft.house.entity.HouseFaq;
|
||||||
|
import com.gxwebsoft.house.param.HouseFaqParam;
|
||||||
|
import com.gxwebsoft.house.service.HouseFaqService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房常见问题控制器
|
||||||
|
*/
|
||||||
|
@Tag(name = "AI找房常见问题管理")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/house/house-faq")
|
||||||
|
public class HouseFaqController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private HouseFaqService houseFaqService;
|
||||||
|
|
||||||
|
@Operation(summary = "分页查询AI找房常见问题")
|
||||||
|
@GetMapping("/page")
|
||||||
|
public ApiResult<PageResult<HouseFaq>> page(HouseFaqParam param) {
|
||||||
|
return success(houseFaqService.pageRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询全部AI找房常见问题")
|
||||||
|
@GetMapping()
|
||||||
|
public ApiResult<List<HouseFaq>> list(HouseFaqParam param) {
|
||||||
|
return success(houseFaqService.listRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "根据id查询AI找房常见问题")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ApiResult<HouseFaq> get(@PathVariable("id") Integer id) {
|
||||||
|
return success(houseFaqService.getByIdRel(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "添加AI找房常见问题")
|
||||||
|
@PostMapping()
|
||||||
|
public ApiResult<?> save(@RequestBody HouseFaq houseFaq) {
|
||||||
|
User loginUser = getLoginUser();
|
||||||
|
if (loginUser != null) {
|
||||||
|
houseFaq.setUserId(loginUser.getUserId());
|
||||||
|
}
|
||||||
|
if (houseFaqService.save(houseFaq)) {
|
||||||
|
return success("添加成功");
|
||||||
|
}
|
||||||
|
return fail("添加失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "修改AI找房常见问题")
|
||||||
|
@PutMapping()
|
||||||
|
public ApiResult<?> update(@RequestBody HouseFaq houseFaq) {
|
||||||
|
if (houseFaqService.updateById(houseFaq)) {
|
||||||
|
return success("修改成功");
|
||||||
|
}
|
||||||
|
return fail("修改失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "删除AI找房常见问题")
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||||
|
if (houseFaqService.removeById(id)) {
|
||||||
|
return success("删除成功");
|
||||||
|
}
|
||||||
|
return fail("删除失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "批量添加AI找房常见问题")
|
||||||
|
@PostMapping("/batch")
|
||||||
|
public ApiResult<?> saveBatch(@RequestBody List<HouseFaq> list) {
|
||||||
|
if (houseFaqService.saveBatch(list)) {
|
||||||
|
return success("添加成功");
|
||||||
|
}
|
||||||
|
return fail("添加失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "批量修改AI找房常见问题")
|
||||||
|
@PutMapping("/batch")
|
||||||
|
public ApiResult<?> updateBatch(@RequestBody BatchParam<HouseFaq> batchParam) {
|
||||||
|
if (batchParam.update(houseFaqService, "faq_id")) {
|
||||||
|
return success("修改成功");
|
||||||
|
}
|
||||||
|
return fail("修改失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "批量删除AI找房常见问题")
|
||||||
|
@DeleteMapping("/batch")
|
||||||
|
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||||
|
if (houseFaqService.removeByIds(ids)) {
|
||||||
|
return success("删除成功");
|
||||||
|
}
|
||||||
|
return fail("删除失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
package com.gxwebsoft.house.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||||
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
|
import com.gxwebsoft.common.core.web.BatchParam;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.common.system.entity.User;
|
||||||
|
import com.gxwebsoft.house.entity.HouseMessage;
|
||||||
|
import com.gxwebsoft.house.param.HouseMessageParam;
|
||||||
|
import com.gxwebsoft.house.service.HouseMessageService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房留言控制器
|
||||||
|
*/
|
||||||
|
@Tag(name = "AI找房留言管理")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/house/house-message")
|
||||||
|
public class HouseMessageController extends BaseController {
|
||||||
|
|
||||||
|
private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
|
||||||
|
private static final Pattern WECHAT_PATTERN = Pattern.compile("^[a-zA-Z][-_a-zA-Z0-9]{5,19}$");
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private HouseMessageService houseMessageService;
|
||||||
|
|
||||||
|
@Operation(summary = "分页查询AI找房留言")
|
||||||
|
@GetMapping("/page")
|
||||||
|
public ApiResult<PageResult<HouseMessage>> page(HouseMessageParam param) {
|
||||||
|
return success(houseMessageService.pageRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询全部AI找房留言")
|
||||||
|
@GetMapping()
|
||||||
|
public ApiResult<List<HouseMessage>> list(HouseMessageParam param) {
|
||||||
|
return success(houseMessageService.listRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "根据id查询AI找房留言")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ApiResult<HouseMessage> get(@PathVariable("id") Integer id) {
|
||||||
|
return success(houseMessageService.getByIdRel(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "添加AI找房留言")
|
||||||
|
@PostMapping()
|
||||||
|
public ApiResult<?> save(@RequestBody HouseMessage houseMessage) {
|
||||||
|
String error = validateMessage(houseMessage);
|
||||||
|
if (error != null) {
|
||||||
|
return fail(error);
|
||||||
|
}
|
||||||
|
User loginUser = getLoginUser();
|
||||||
|
if (loginUser != null) {
|
||||||
|
houseMessage.setUserId(loginUser.getUserId());
|
||||||
|
}
|
||||||
|
houseMessage.setRealName(houseMessage.getRealName().trim());
|
||||||
|
houseMessage.setPhone(StrUtil.trimToNull(houseMessage.getPhone()));
|
||||||
|
houseMessage.setWechat(StrUtil.trimToNull(houseMessage.getWechat()));
|
||||||
|
houseMessage.setSource(StrUtil.blankToDefault(houseMessage.getSource(), "ai_house"));
|
||||||
|
if (houseMessage.getStatus() == null) {
|
||||||
|
houseMessage.setStatus(0);
|
||||||
|
}
|
||||||
|
if (houseMessageService.save(houseMessage)) {
|
||||||
|
return success("提交成功");
|
||||||
|
}
|
||||||
|
return fail("提交失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "修改AI找房留言")
|
||||||
|
@PutMapping()
|
||||||
|
public ApiResult<?> update(@RequestBody HouseMessage houseMessage) {
|
||||||
|
String error = validateMessage(houseMessage);
|
||||||
|
if (error != null) {
|
||||||
|
return fail(error);
|
||||||
|
}
|
||||||
|
houseMessage.setRealName(houseMessage.getRealName().trim());
|
||||||
|
houseMessage.setPhone(StrUtil.trimToNull(houseMessage.getPhone()));
|
||||||
|
houseMessage.setWechat(StrUtil.trimToNull(houseMessage.getWechat()));
|
||||||
|
if (houseMessageService.updateById(houseMessage)) {
|
||||||
|
return success("修改成功");
|
||||||
|
}
|
||||||
|
return fail("修改失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "删除AI找房留言")
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||||
|
if (houseMessageService.removeById(id)) {
|
||||||
|
return success("删除成功");
|
||||||
|
}
|
||||||
|
return fail("删除失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "批量修改AI找房留言")
|
||||||
|
@PutMapping("/batch")
|
||||||
|
public ApiResult<?> updateBatch(@RequestBody BatchParam<HouseMessage> batchParam) {
|
||||||
|
if (batchParam.update(houseMessageService, "message_id")) {
|
||||||
|
return success("修改成功");
|
||||||
|
}
|
||||||
|
return fail("修改失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "批量删除AI找房留言")
|
||||||
|
@DeleteMapping("/batch")
|
||||||
|
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||||
|
if (houseMessageService.removeByIds(ids)) {
|
||||||
|
return success("删除成功");
|
||||||
|
}
|
||||||
|
return fail("删除失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String validateMessage(HouseMessage houseMessage) {
|
||||||
|
if (houseMessage == null || StrUtil.isBlank(houseMessage.getRealName())) {
|
||||||
|
return "请输入姓名";
|
||||||
|
}
|
||||||
|
if (houseMessage.getRealName().trim().length() > 30) {
|
||||||
|
return "姓名不能超过30个字符";
|
||||||
|
}
|
||||||
|
boolean hasPhone = StrUtil.isNotBlank(houseMessage.getPhone());
|
||||||
|
boolean hasWechat = StrUtil.isNotBlank(houseMessage.getWechat());
|
||||||
|
if (!hasPhone && !hasWechat) {
|
||||||
|
return "手机号和微信号请至少填写一项";
|
||||||
|
}
|
||||||
|
if (hasPhone && !PHONE_PATTERN.matcher(houseMessage.getPhone().trim()).matches()) {
|
||||||
|
return "手机号格式不正确";
|
||||||
|
}
|
||||||
|
if (hasWechat && !WECHAT_PATTERN.matcher(houseMessage.getWechat().trim()).matches()) {
|
||||||
|
return "微信号格式不正确";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.gxwebsoft.house.entity;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房提问请求
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "HouseAiChatRequest对象", description = "AI找房提问请求")
|
||||||
|
public class HouseAiChatRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "会话ID")
|
||||||
|
private String conversationId;
|
||||||
|
|
||||||
|
@Schema(description = "用户ID")
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
@Schema(description = "问题")
|
||||||
|
private String question;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.gxwebsoft.house.entity;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房应答
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "HouseAiChatResponse对象", description = "AI找房应答")
|
||||||
|
public class HouseAiChatResponse implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "消息类型")
|
||||||
|
private String type = "house_ai_result";
|
||||||
|
|
||||||
|
@Schema(description = "回答文本")
|
||||||
|
private String answer;
|
||||||
|
|
||||||
|
@Schema(description = "命中的常见问题")
|
||||||
|
private List<HouseFaq> faqs = new ArrayList<>();
|
||||||
|
|
||||||
|
@Schema(description = "推荐房源")
|
||||||
|
private List<HouseAiHouseCard> houses = new ArrayList<>();
|
||||||
|
|
||||||
|
@Schema(description = "语义解析结果")
|
||||||
|
private HouseAiIntent intent;
|
||||||
|
|
||||||
|
@Schema(description = "来源 faq/house/ai")
|
||||||
|
private String source;
|
||||||
|
}
|
||||||
53
src/main/java/com/gxwebsoft/house/entity/HouseAiConfig.java
Normal file
53
src/main/java/com/gxwebsoft/house/entity/HouseAiConfig.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package com.gxwebsoft.house.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Schema(name = "HouseAiConfig对象", description = "AI找房配置")
|
||||||
|
public class HouseAiConfig implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主键ID")
|
||||||
|
@TableId(value = "config_id", type = IdType.AUTO)
|
||||||
|
private Integer configId;
|
||||||
|
|
||||||
|
@Schema(description = "AI形象照")
|
||||||
|
private String aiAvatar;
|
||||||
|
|
||||||
|
@Schema(description = "首页AI入口图")
|
||||||
|
private String aiEntryImage;
|
||||||
|
|
||||||
|
@Schema(description = "首页AI悬浮图")
|
||||||
|
private String aiFloatImage;
|
||||||
|
|
||||||
|
@Schema(description = "欢迎词")
|
||||||
|
private String welcomeMessage;
|
||||||
|
|
||||||
|
@Schema(description = "状态 0正常 1禁用")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "是否删除, 0否, 1是")
|
||||||
|
@TableLogic
|
||||||
|
private Integer deleted;
|
||||||
|
|
||||||
|
@Schema(description = "租户ID")
|
||||||
|
private Integer tenantId;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
@Schema(description = "更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.gxwebsoft.house.entity;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房返回的轻量房源卡片
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "HouseAiHouseCard对象", description = "AI找房返回的轻量房源卡片")
|
||||||
|
public class HouseAiHouseCard implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "房源ID")
|
||||||
|
private Integer houseId;
|
||||||
|
|
||||||
|
@Schema(description = "房源标题")
|
||||||
|
private String houseTitle;
|
||||||
|
|
||||||
|
@Schema(description = "户型")
|
||||||
|
private String houseType;
|
||||||
|
|
||||||
|
@Schema(description = "面积")
|
||||||
|
private String extent;
|
||||||
|
|
||||||
|
@Schema(description = "楼层")
|
||||||
|
private String floor;
|
||||||
|
|
||||||
|
@Schema(description = "朝向")
|
||||||
|
private String toward;
|
||||||
|
|
||||||
|
@Schema(description = "月租金")
|
||||||
|
private String monthlyRent;
|
||||||
|
|
||||||
|
@Schema(description = "所在城市")
|
||||||
|
private String city;
|
||||||
|
|
||||||
|
@Schema(description = "所在辖区")
|
||||||
|
private String region;
|
||||||
|
|
||||||
|
@Schema(description = "详细地址")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
@Schema(description = "图片附件")
|
||||||
|
private String files;
|
||||||
|
|
||||||
|
@Schema(description = "办公室配套")
|
||||||
|
private String supporting;
|
||||||
|
}
|
||||||
87
src/main/java/com/gxwebsoft/house/entity/HouseAiIntent.java
Normal file
87
src/main/java/com/gxwebsoft/house/entity/HouseAiIntent.java
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package com.gxwebsoft.house.entity;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房语义解析结果
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "HouseAiIntent对象", description = "AI找房语义解析结果")
|
||||||
|
public class HouseAiIntent implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "原始问题")
|
||||||
|
private String originalQuestion;
|
||||||
|
|
||||||
|
@Schema(description = "意图类型 faq/house/mixed/unknown")
|
||||||
|
private String intentType;
|
||||||
|
|
||||||
|
@Schema(description = "归一化问题")
|
||||||
|
private String normalizedQuestion;
|
||||||
|
|
||||||
|
@Schema(description = "面积最小值")
|
||||||
|
private Integer extentMin;
|
||||||
|
|
||||||
|
@Schema(description = "面积最大值")
|
||||||
|
private Integer extentMax;
|
||||||
|
|
||||||
|
@Schema(description = "楼层最小值")
|
||||||
|
private Integer floorMin;
|
||||||
|
|
||||||
|
@Schema(description = "楼层最大值")
|
||||||
|
private Integer floorMax;
|
||||||
|
|
||||||
|
@Schema(description = "月租最小值")
|
||||||
|
private BigDecimal monthlyRentMin;
|
||||||
|
|
||||||
|
@Schema(description = "月租最大值")
|
||||||
|
private BigDecimal monthlyRentMax;
|
||||||
|
|
||||||
|
@Schema(description = "售价最小值")
|
||||||
|
private BigDecimal salePriceMin;
|
||||||
|
|
||||||
|
@Schema(description = "售价最大值")
|
||||||
|
private BigDecimal salePriceMax;
|
||||||
|
|
||||||
|
@Schema(description = "总价最小值")
|
||||||
|
private BigDecimal totalPriceMin;
|
||||||
|
|
||||||
|
@Schema(description = "总价最大值")
|
||||||
|
private BigDecimal totalPriceMax;
|
||||||
|
|
||||||
|
@Schema(description = "区域/地段")
|
||||||
|
private String regionKeyword;
|
||||||
|
|
||||||
|
@Schema(description = "城市")
|
||||||
|
private String cityKeyword;
|
||||||
|
|
||||||
|
@Schema(description = "租售类型 rent/sale")
|
||||||
|
private String tradeType;
|
||||||
|
|
||||||
|
@Schema(description = "装修类型")
|
||||||
|
private String decorationType;
|
||||||
|
|
||||||
|
@Schema(description = "配套要求")
|
||||||
|
private String supportingKeyword;
|
||||||
|
|
||||||
|
@Schema(description = "朝向")
|
||||||
|
private String toward;
|
||||||
|
|
||||||
|
@Schema(description = "房型")
|
||||||
|
private String houseType;
|
||||||
|
|
||||||
|
@Schema(description = "AI生成的SQL筛选条件片段")
|
||||||
|
private String whereSql;
|
||||||
|
|
||||||
|
@Schema(description = "AI生成的SQL排序片段")
|
||||||
|
private String orderSql;
|
||||||
|
|
||||||
|
@Schema(description = "其他关键词")
|
||||||
|
private List<String> tags = new ArrayList<>();
|
||||||
|
}
|
||||||
59
src/main/java/com/gxwebsoft/house/entity/HouseFaq.java
Normal file
59
src/main/java/com/gxwebsoft/house/entity/HouseFaq.java
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package com.gxwebsoft.house.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房常见问题
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Schema(name = "HouseFaq对象", description = "AI找房常见问题")
|
||||||
|
public class HouseFaq implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主键ID")
|
||||||
|
@TableId(value = "faq_id", type = IdType.AUTO)
|
||||||
|
private Integer faqId;
|
||||||
|
|
||||||
|
@Schema(description = "问题")
|
||||||
|
private String question;
|
||||||
|
|
||||||
|
@Schema(description = "关键词,多个用逗号分隔")
|
||||||
|
private String keywords;
|
||||||
|
|
||||||
|
@Schema(description = "标准回答")
|
||||||
|
private String answer;
|
||||||
|
|
||||||
|
@Schema(description = "分类")
|
||||||
|
private String category;
|
||||||
|
|
||||||
|
@Schema(description = "排序号")
|
||||||
|
private Integer sortNumber;
|
||||||
|
|
||||||
|
@Schema(description = "状态 0正常 1禁用")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "创建用户ID")
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
@Schema(description = "是否删除, 0否, 1是")
|
||||||
|
@TableLogic
|
||||||
|
private Integer deleted;
|
||||||
|
|
||||||
|
@Schema(description = "租户ID")
|
||||||
|
private Integer tenantId;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
@Schema(description = "更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
}
|
||||||
62
src/main/java/com/gxwebsoft/house/entity/HouseMessage.java
Normal file
62
src/main/java/com/gxwebsoft/house/entity/HouseMessage.java
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package com.gxwebsoft.house.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房留言
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Schema(name = "HouseMessage对象", description = "AI找房留言")
|
||||||
|
public class HouseMessage implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主键ID")
|
||||||
|
@TableId(value = "message_id", type = IdType.AUTO)
|
||||||
|
private Integer messageId;
|
||||||
|
|
||||||
|
@Schema(description = "用户ID")
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
@Schema(description = "姓名")
|
||||||
|
private String realName;
|
||||||
|
|
||||||
|
@Schema(description = "手机号")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@Schema(description = "微信号")
|
||||||
|
private String wechat;
|
||||||
|
|
||||||
|
@Schema(description = "来源")
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String comments;
|
||||||
|
|
||||||
|
@Schema(description = "状态 0未处理 1已处理")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "是否删除, 0否, 1是")
|
||||||
|
@TableLogic
|
||||||
|
private Integer deleted;
|
||||||
|
|
||||||
|
@Schema(description = "租户ID")
|
||||||
|
private Integer tenantId;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Schema(description = "更新时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.gxwebsoft.house.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.gxwebsoft.house.entity.HouseAiConfig;
|
||||||
|
import com.gxwebsoft.house.param.HouseAiConfigParam;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房配置Mapper
|
||||||
|
*/
|
||||||
|
public interface HouseAiConfigMapper extends BaseMapper<HouseAiConfig> {
|
||||||
|
|
||||||
|
List<HouseAiConfig> selectPageRel(@Param("page") IPage<HouseAiConfig> page, @Param("param") HouseAiConfigParam param);
|
||||||
|
|
||||||
|
List<HouseAiConfig> selectListRel(@Param("param") HouseAiConfigParam param);
|
||||||
|
}
|
||||||
19
src/main/java/com/gxwebsoft/house/mapper/HouseFaqMapper.java
Normal file
19
src/main/java/com/gxwebsoft/house/mapper/HouseFaqMapper.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package com.gxwebsoft.house.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.gxwebsoft.house.entity.HouseFaq;
|
||||||
|
import com.gxwebsoft.house.param.HouseFaqParam;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房常见问题Mapper
|
||||||
|
*/
|
||||||
|
public interface HouseFaqMapper extends BaseMapper<HouseFaq> {
|
||||||
|
|
||||||
|
List<HouseFaq> selectPageRel(@Param("page") IPage<HouseFaq> page, @Param("param") HouseFaqParam param);
|
||||||
|
|
||||||
|
List<HouseFaq> selectListRel(@Param("param") HouseFaqParam param);
|
||||||
|
}
|
||||||
@@ -34,4 +34,9 @@ public interface HouseInfoMapper extends BaseMapper<HouseInfo> {
|
|||||||
*/
|
*/
|
||||||
List<HouseInfo> selectListRel(@Param("param") HouseInfoParam param);
|
List<HouseInfo> selectListRel(@Param("param") HouseInfoParam param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行AI生成的受控查询条件
|
||||||
|
*/
|
||||||
|
List<HouseInfo> selectListByAiSql(@Param("whereSql") String whereSql, @Param("orderSql") String orderSql);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.gxwebsoft.house.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.gxwebsoft.house.entity.HouseMessage;
|
||||||
|
import com.gxwebsoft.house.param.HouseMessageParam;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房留言Mapper
|
||||||
|
*/
|
||||||
|
public interface HouseMessageMapper extends BaseMapper<HouseMessage> {
|
||||||
|
|
||||||
|
List<HouseMessage> selectPageRel(@Param("page") IPage<HouseMessage> page, @Param("param") HouseMessageParam param);
|
||||||
|
|
||||||
|
List<HouseMessage> selectListRel(@Param("param") HouseMessageParam param);
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.gxwebsoft.house.mapper.HouseAiConfigMapper">
|
||||||
|
|
||||||
|
<sql id="selectSql">
|
||||||
|
SELECT a.*
|
||||||
|
FROM house_ai_config a
|
||||||
|
<where>
|
||||||
|
<if test="param.configId != null">
|
||||||
|
AND a.config_id = #{param.configId}
|
||||||
|
</if>
|
||||||
|
<if test="param.aiAvatar != null and param.aiAvatar != ''">
|
||||||
|
AND a.ai_avatar LIKE CONCAT('%', #{param.aiAvatar}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.aiEntryImage != null and param.aiEntryImage != ''">
|
||||||
|
AND a.ai_entry_image LIKE CONCAT('%', #{param.aiEntryImage}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.aiFloatImage != null and param.aiFloatImage != ''">
|
||||||
|
AND a.ai_float_image LIKE CONCAT('%', #{param.aiFloatImage}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.welcomeMessage != null and param.welcomeMessage != ''">
|
||||||
|
AND a.welcome_message LIKE CONCAT('%', #{param.welcomeMessage}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.status != null">
|
||||||
|
AND a.status = #{param.status}
|
||||||
|
</if>
|
||||||
|
<if test="param.deleted != null">
|
||||||
|
AND a.deleted = #{param.deleted}
|
||||||
|
</if>
|
||||||
|
<if test="param.deleted == null">
|
||||||
|
AND a.deleted = 0
|
||||||
|
</if>
|
||||||
|
<if test="param.tenantId != null">
|
||||||
|
AND a.tenant_id = #{param.tenantId}
|
||||||
|
</if>
|
||||||
|
<if test="param.keywords != null and param.keywords != ''">
|
||||||
|
AND (
|
||||||
|
a.welcome_message LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR a.ai_avatar LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR a.ai_entry_image LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR a.ai_float_image LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
ORDER BY a.config_id DESC
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectPageRel" resultType="com.gxwebsoft.house.entity.HouseAiConfig">
|
||||||
|
<include refid="selectSql"></include>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectListRel" resultType="com.gxwebsoft.house.entity.HouseAiConfig">
|
||||||
|
<include refid="selectSql"></include>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.gxwebsoft.house.mapper.HouseFaqMapper">
|
||||||
|
|
||||||
|
<sql id="selectSql">
|
||||||
|
SELECT a.*
|
||||||
|
FROM house_faq a
|
||||||
|
<where>
|
||||||
|
<if test="param.faqId != null">
|
||||||
|
AND a.faq_id = #{param.faqId}
|
||||||
|
</if>
|
||||||
|
<if test="param.question != null and param.question != ''">
|
||||||
|
AND a.question LIKE CONCAT('%', #{param.question}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.keywordsText != null and param.keywordsText != ''">
|
||||||
|
AND a.keywords LIKE CONCAT('%', #{param.keywordsText}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.answer != null and param.answer != ''">
|
||||||
|
AND a.answer LIKE CONCAT('%', #{param.answer}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.category != null and param.category != ''">
|
||||||
|
AND a.category LIKE CONCAT('%', #{param.category}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.sortNumber != null">
|
||||||
|
AND a.sort_number = #{param.sortNumber}
|
||||||
|
</if>
|
||||||
|
<if test="param.status != null">
|
||||||
|
AND a.status = #{param.status}
|
||||||
|
</if>
|
||||||
|
<if test="param.userId != null">
|
||||||
|
AND a.user_id = #{param.userId}
|
||||||
|
</if>
|
||||||
|
<if test="param.deleted != null">
|
||||||
|
AND a.deleted = #{param.deleted}
|
||||||
|
</if>
|
||||||
|
<if test="param.deleted == null">
|
||||||
|
AND a.deleted = 0
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeStart != null">
|
||||||
|
AND a.create_time >= #{param.createTimeStart}
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeEnd != null">
|
||||||
|
AND a.create_time <= #{param.createTimeEnd}
|
||||||
|
</if>
|
||||||
|
<if test="param.keywords != null and param.keywords != ''">
|
||||||
|
AND (
|
||||||
|
a.question LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR a.keywords LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR a.answer LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR a.category LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
ORDER BY a.sort_number ASC, a.faq_id DESC
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectPageRel" resultType="com.gxwebsoft.house.entity.HouseFaq">
|
||||||
|
<include refid="selectSql"></include>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectListRel" resultType="com.gxwebsoft.house.entity.HouseFaq">
|
||||||
|
<include refid="selectSql"></include>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -172,4 +172,25 @@
|
|||||||
<include refid="selectSql"></include>
|
<include refid="selectSql"></include>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- AI受控查询 -->
|
||||||
|
<select id="selectListByAiSql" resultType="com.gxwebsoft.house.entity.HouseInfo">
|
||||||
|
SELECT a.*,
|
||||||
|
b.nickname,b.avatar,b.grade_id, b.phone as userPhone
|
||||||
|
FROM house_info a
|
||||||
|
LEFT JOIN gxwebsoft_core.sys_user b ON a.user_id = b.user_id
|
||||||
|
<where>
|
||||||
|
a.deleted = 0
|
||||||
|
AND a.status = 0
|
||||||
|
<if test="whereSql != null and whereSql != ''">
|
||||||
|
AND ${whereSql}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
<if test="orderSql != null and orderSql != ''">
|
||||||
|
ORDER BY ${orderSql}
|
||||||
|
</if>
|
||||||
|
<if test="orderSql == null or orderSql == ''">
|
||||||
|
ORDER BY a.sort_number asc, a.create_time desc
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.gxwebsoft.house.mapper.HouseMessageMapper">
|
||||||
|
|
||||||
|
<sql id="selectSql">
|
||||||
|
SELECT a.*
|
||||||
|
FROM house_message a
|
||||||
|
<where>
|
||||||
|
<if test="param.messageId != null">
|
||||||
|
AND a.message_id = #{param.messageId}
|
||||||
|
</if>
|
||||||
|
<if test="param.userId != null">
|
||||||
|
AND a.user_id = #{param.userId}
|
||||||
|
</if>
|
||||||
|
<if test="param.realName != null and param.realName != ''">
|
||||||
|
AND a.real_name LIKE CONCAT('%', #{param.realName}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.phone != null and param.phone != ''">
|
||||||
|
AND a.phone LIKE CONCAT('%', #{param.phone}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.wechat != null and param.wechat != ''">
|
||||||
|
AND a.wechat LIKE CONCAT('%', #{param.wechat}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.source != null and param.source != ''">
|
||||||
|
AND a.source = #{param.source}
|
||||||
|
</if>
|
||||||
|
<if test="param.comments != null and param.comments != ''">
|
||||||
|
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.status != null">
|
||||||
|
AND a.status = #{param.status}
|
||||||
|
</if>
|
||||||
|
<if test="param.deleted != null">
|
||||||
|
AND a.deleted = #{param.deleted}
|
||||||
|
</if>
|
||||||
|
<if test="param.deleted == null">
|
||||||
|
AND a.deleted = 0
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeStart != null">
|
||||||
|
AND a.create_time >= #{param.createTimeStart}
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeEnd != null">
|
||||||
|
AND a.create_time <= #{param.createTimeEnd}
|
||||||
|
</if>
|
||||||
|
<if test="param.keywords != null and param.keywords != ''">
|
||||||
|
AND (
|
||||||
|
a.real_name LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR a.phone LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR a.wechat LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectPageRel" resultType="com.gxwebsoft.house.entity.HouseMessage">
|
||||||
|
<include refid="selectSql"></include>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectListRel" resultType="com.gxwebsoft.house.entity.HouseMessage">
|
||||||
|
<include refid="selectSql"></include>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.gxwebsoft.house.param;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||||
|
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseParam;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房配置查询参数
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@Schema(name = "HouseAiConfigParam对象", description = "AI找房配置查询参数")
|
||||||
|
public class HouseAiConfigParam extends BaseParam {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主键ID")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer configId;
|
||||||
|
|
||||||
|
@Schema(description = "AI形象照")
|
||||||
|
private String aiAvatar;
|
||||||
|
|
||||||
|
@Schema(description = "首页AI入口图")
|
||||||
|
private String aiEntryImage;
|
||||||
|
|
||||||
|
@Schema(description = "首页AI悬浮图")
|
||||||
|
private String aiFloatImage;
|
||||||
|
|
||||||
|
@Schema(description = "欢迎词")
|
||||||
|
private String welcomeMessage;
|
||||||
|
|
||||||
|
@Schema(description = "状态 0正常 1禁用")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "是否删除, 0否, 1是")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer deleted;
|
||||||
|
}
|
||||||
57
src/main/java/com/gxwebsoft/house/param/HouseFaqParam.java
Normal file
57
src/main/java/com/gxwebsoft/house/param/HouseFaqParam.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package com.gxwebsoft.house.param;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||||
|
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseParam;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房常见问题查询参数
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@Schema(name = "HouseFaqParam对象", description = "AI找房常见问题查询参数")
|
||||||
|
public class HouseFaqParam extends BaseParam {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主键ID")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer faqId;
|
||||||
|
|
||||||
|
@Schema(description = "问题")
|
||||||
|
private String question;
|
||||||
|
|
||||||
|
@Schema(description = "关键词")
|
||||||
|
private String keywordsText;
|
||||||
|
|
||||||
|
@Schema(description = "回答")
|
||||||
|
private String answer;
|
||||||
|
|
||||||
|
@Schema(description = "分类")
|
||||||
|
private String category;
|
||||||
|
|
||||||
|
@Schema(description = "排序号")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer sortNumber;
|
||||||
|
|
||||||
|
@Schema(description = "状态 0正常 1禁用")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "创建用户ID")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
@Schema(description = "是否删除, 0否, 1是")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer deleted;
|
||||||
|
|
||||||
|
@Schema(description = "语义搜索原句")
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String queryText;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.gxwebsoft.house.param;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||||
|
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseParam;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房留言查询参数
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@Schema(name = "HouseMessageParam对象", description = "AI找房留言查询参数")
|
||||||
|
public class HouseMessageParam extends BaseParam {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主键ID")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer messageId;
|
||||||
|
|
||||||
|
@Schema(description = "用户ID")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
@Schema(description = "姓名")
|
||||||
|
private String realName;
|
||||||
|
|
||||||
|
@Schema(description = "手机号")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@Schema(description = "微信号")
|
||||||
|
private String wechat;
|
||||||
|
|
||||||
|
@Schema(description = "来源")
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String comments;
|
||||||
|
|
||||||
|
@Schema(description = "状态 0未处理 1已处理")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "是否删除, 0否, 1是")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer deleted;
|
||||||
|
|
||||||
|
@Schema(description = "关键词")
|
||||||
|
private String keywords;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.gxwebsoft.house.service;
|
||||||
|
|
||||||
|
import com.gxwebsoft.house.entity.HouseAiChatRequest;
|
||||||
|
import com.gxwebsoft.house.entity.HouseAiChatResponse;
|
||||||
|
import com.gxwebsoft.house.entity.HouseAiIntent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房问答Service
|
||||||
|
*/
|
||||||
|
public interface HouseAiChatService {
|
||||||
|
|
||||||
|
HouseAiIntent analyzeIntent(String question);
|
||||||
|
|
||||||
|
HouseAiChatResponse answer(HouseAiChatRequest request);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.gxwebsoft.house.service;
|
||||||
|
|
||||||
|
import com.github.yulichang.base.MPJBaseService;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.house.entity.HouseAiConfig;
|
||||||
|
import com.gxwebsoft.house.param.HouseAiConfigParam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房配置Service
|
||||||
|
*/
|
||||||
|
public interface HouseAiConfigService extends MPJBaseService<HouseAiConfig> {
|
||||||
|
|
||||||
|
PageResult<HouseAiConfig> pageRel(HouseAiConfigParam param);
|
||||||
|
|
||||||
|
List<HouseAiConfig> listRel(HouseAiConfigParam param);
|
||||||
|
|
||||||
|
HouseAiConfig getByIdRel(Integer configId);
|
||||||
|
|
||||||
|
HouseAiConfig getCurrentConfig(Integer tenantId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.gxwebsoft.house.service;
|
||||||
|
|
||||||
|
import com.github.yulichang.base.MPJBaseService;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.house.entity.HouseFaq;
|
||||||
|
import com.gxwebsoft.house.param.HouseFaqParam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房常见问题Service
|
||||||
|
*/
|
||||||
|
public interface HouseFaqService extends MPJBaseService<HouseFaq> {
|
||||||
|
|
||||||
|
PageResult<HouseFaq> pageRel(HouseFaqParam param);
|
||||||
|
|
||||||
|
List<HouseFaq> listRel(HouseFaqParam param);
|
||||||
|
|
||||||
|
HouseFaq getByIdRel(Integer faqId);
|
||||||
|
|
||||||
|
List<HouseFaq> findBestMatches(String queryText, int limit);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.gxwebsoft.house.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.house.entity.HouseMessage;
|
||||||
|
import com.gxwebsoft.house.param.HouseMessageParam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房留言Service
|
||||||
|
*/
|
||||||
|
public interface HouseMessageService extends IService<HouseMessage> {
|
||||||
|
|
||||||
|
PageResult<HouseMessage> pageRel(HouseMessageParam param);
|
||||||
|
|
||||||
|
List<HouseMessage> listRel(HouseMessageParam param);
|
||||||
|
|
||||||
|
HouseMessage getByIdRel(Integer messageId);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
|||||||
|
package com.gxwebsoft.house.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.gxwebsoft.common.core.web.PageParam;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.house.entity.HouseAiConfig;
|
||||||
|
import com.gxwebsoft.house.mapper.HouseAiConfigMapper;
|
||||||
|
import com.gxwebsoft.house.param.HouseAiConfigParam;
|
||||||
|
import com.gxwebsoft.house.service.HouseAiConfigService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房配置Service实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class HouseAiConfigServiceImpl extends ServiceImpl<HouseAiConfigMapper, HouseAiConfig> implements HouseAiConfigService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<HouseAiConfig> pageRel(HouseAiConfigParam param) {
|
||||||
|
PageParam<HouseAiConfig, HouseAiConfigParam> page = new PageParam<>(param);
|
||||||
|
page.setDefaultOrder("config_id desc");
|
||||||
|
List<HouseAiConfig> list = baseMapper.selectPageRel(page, param);
|
||||||
|
return new PageResult<>(list, page.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HouseAiConfig> listRel(HouseAiConfigParam param) {
|
||||||
|
return baseMapper.selectListRel(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HouseAiConfig getByIdRel(Integer configId) {
|
||||||
|
HouseAiConfigParam param = new HouseAiConfigParam();
|
||||||
|
param.setConfigId(configId);
|
||||||
|
return param.getOne(baseMapper.selectListRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HouseAiConfig getCurrentConfig(Integer tenantId) {
|
||||||
|
HouseAiConfigParam param = new HouseAiConfigParam();
|
||||||
|
param.setStatus(0);
|
||||||
|
param.setTenantId(tenantId);
|
||||||
|
HouseAiConfig config = param.getOne(baseMapper.selectListRel(param));
|
||||||
|
if (config != null) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
param.setTenantId(null);
|
||||||
|
return param.getOne(baseMapper.selectListRel(param));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
package com.gxwebsoft.house.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.gxwebsoft.common.core.web.PageParam;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.house.entity.HouseFaq;
|
||||||
|
import com.gxwebsoft.house.mapper.HouseFaqMapper;
|
||||||
|
import com.gxwebsoft.house.param.HouseFaqParam;
|
||||||
|
import com.gxwebsoft.house.service.HouseFaqService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房常见问题Service实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class HouseFaqServiceImpl extends ServiceImpl<HouseFaqMapper, HouseFaq> implements HouseFaqService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<HouseFaq> pageRel(HouseFaqParam param) {
|
||||||
|
PageParam<HouseFaq, HouseFaqParam> page = new PageParam<>(param);
|
||||||
|
page.setDefaultOrder("sort_number asc, faq_id desc");
|
||||||
|
List<HouseFaq> list = baseMapper.selectPageRel(page, param);
|
||||||
|
return new PageResult<>(list, page.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HouseFaq> listRel(HouseFaqParam param) {
|
||||||
|
return baseMapper.selectListRel(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HouseFaq getByIdRel(Integer faqId) {
|
||||||
|
HouseFaqParam param = new HouseFaqParam();
|
||||||
|
param.setFaqId(faqId);
|
||||||
|
return param.getOne(baseMapper.selectListRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HouseFaq> findBestMatches(String queryText, int limit) {
|
||||||
|
HouseFaqParam param = new HouseFaqParam();
|
||||||
|
param.setStatus(0);
|
||||||
|
List<HouseFaq> all = baseMapper.selectListRel(param);
|
||||||
|
if (StrUtil.isBlank(queryText) || all == null || all.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
final String normalizedQuery = normalizeText(queryText);
|
||||||
|
return all.stream()
|
||||||
|
.map(item -> new ScoredFaq(item, score(item, normalizedQuery)))
|
||||||
|
.filter(item -> item.score > 0)
|
||||||
|
.sorted(Comparator.comparingInt(ScoredFaq::getScore).reversed()
|
||||||
|
.thenComparing(item -> item.faq.getSortNumber() == null ? Integer.MAX_VALUE : item.faq.getSortNumber()))
|
||||||
|
.limit(limit)
|
||||||
|
.map(ScoredFaq::getFaq)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private int score(HouseFaq faq, String normalizedQuery) {
|
||||||
|
int score = 0;
|
||||||
|
String question = normalizeText(faq.getQuestion());
|
||||||
|
String keywords = normalizeText(faq.getKeywords());
|
||||||
|
String answer = normalizeText(faq.getAnswer());
|
||||||
|
String category = normalizeText(faq.getCategory());
|
||||||
|
if (StrUtil.isBlank(normalizedQuery)) {
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
if (question.contains(normalizedQuery)) {
|
||||||
|
score += 120;
|
||||||
|
}
|
||||||
|
if (keywords.contains(normalizedQuery)) {
|
||||||
|
score += 100;
|
||||||
|
}
|
||||||
|
if (answer.contains(normalizedQuery)) {
|
||||||
|
score += 40;
|
||||||
|
}
|
||||||
|
if (category.contains(normalizedQuery)) {
|
||||||
|
score += 30;
|
||||||
|
}
|
||||||
|
for (String token : tokenize(normalizedQuery)) {
|
||||||
|
if (token.length() < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (question.contains(token)) {
|
||||||
|
score += 20;
|
||||||
|
}
|
||||||
|
if (keywords.contains(token)) {
|
||||||
|
score += 18;
|
||||||
|
}
|
||||||
|
if (answer.contains(token)) {
|
||||||
|
score += 8;
|
||||||
|
}
|
||||||
|
if (category.contains(token)) {
|
||||||
|
score += 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> tokenize(String text) {
|
||||||
|
String normalized = normalizeText(text);
|
||||||
|
List<String> tokens = new ArrayList<>();
|
||||||
|
for (String item : normalized.split("[,,\\s+/|]+")) {
|
||||||
|
if (StrUtil.isNotBlank(item)) {
|
||||||
|
tokens.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeText(String text) {
|
||||||
|
if (text == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return text.replace(" ", " ")
|
||||||
|
.replace(",", ",")
|
||||||
|
.replace("。", " ")
|
||||||
|
.replace(";", " ")
|
||||||
|
.replace(":", " ")
|
||||||
|
.replace("(", "(")
|
||||||
|
.replace(")", ")")
|
||||||
|
.replace("㎡", "平")
|
||||||
|
.replace("m²", "平")
|
||||||
|
.replace("M²", "平")
|
||||||
|
.toLowerCase(Locale.ROOT)
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ScoredFaq {
|
||||||
|
private final HouseFaq faq;
|
||||||
|
private final int score;
|
||||||
|
|
||||||
|
private ScoredFaq(HouseFaq faq, int score) {
|
||||||
|
this.faq = faq;
|
||||||
|
this.score = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HouseFaq getFaq() {
|
||||||
|
return faq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getScore() {
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.gxwebsoft.house.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.gxwebsoft.common.core.web.PageParam;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.house.entity.HouseMessage;
|
||||||
|
import com.gxwebsoft.house.mapper.HouseMessageMapper;
|
||||||
|
import com.gxwebsoft.house.param.HouseMessageParam;
|
||||||
|
import com.gxwebsoft.house.service.HouseMessageService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI找房留言Service实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class HouseMessageServiceImpl extends ServiceImpl<HouseMessageMapper, HouseMessage> implements HouseMessageService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<HouseMessage> pageRel(HouseMessageParam param) {
|
||||||
|
PageParam<HouseMessage, HouseMessageParam> page = new PageParam<>(param);
|
||||||
|
page.setDefaultOrder("create_time desc, message_id desc");
|
||||||
|
List<HouseMessage> list = baseMapper.selectPageRel(page, param);
|
||||||
|
return new PageResult<>(list, page.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HouseMessage> listRel(HouseMessageParam param) {
|
||||||
|
List<HouseMessage> list = baseMapper.selectListRel(param);
|
||||||
|
PageParam<HouseMessage, HouseMessageParam> page = new PageParam<>();
|
||||||
|
page.setDefaultOrder("create_time desc, message_id desc");
|
||||||
|
return page.sortRecords(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HouseMessage getByIdRel(Integer messageId) {
|
||||||
|
HouseMessageParam param = new HouseMessageParam();
|
||||||
|
param.setMessageId(messageId);
|
||||||
|
return param.getOne(baseMapper.selectListRel(param));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,7 +32,7 @@ socketio:
|
|||||||
# MQTT配置
|
# MQTT配置
|
||||||
mqtt:
|
mqtt:
|
||||||
enabled: false # 添加开关来禁用MQTT服务
|
enabled: false # 添加开关来禁用MQTT服务
|
||||||
host: tcp://132.232.214.96:1883
|
host: tcp://1.14.159.185:1883
|
||||||
username: swdev
|
username: swdev
|
||||||
password: Sw20250523
|
password: Sw20250523
|
||||||
client-id-prefix: hjm_car_
|
client-id-prefix: hjm_car_
|
||||||
@@ -46,7 +46,7 @@ mqtt:
|
|||||||
config:
|
config:
|
||||||
# 开发环境接口
|
# 开发环境接口
|
||||||
server-url: https://server.websoft.top/api
|
server-url: https://server.websoft.top/api
|
||||||
upload-path: /Users/gxwebsoft/Documents/uploads/ # window(D:\Temp)
|
upload-path: /Users/gxwebsoft/JAVA/mp-java/src/main/resources/ # window(D:\Temp)
|
||||||
|
|
||||||
# 开发环境证书配置
|
# 开发环境证书配置
|
||||||
certificate:
|
certificate:
|
||||||
@@ -56,10 +56,3 @@ certificate:
|
|||||||
private-key-file: "apiclient_key.pem"
|
private-key-file: "apiclient_key.pem"
|
||||||
apiclient-cert-file: "apiclient_cert.pem"
|
apiclient-cert-file: "apiclient_cert.pem"
|
||||||
wechatpay-cert-file: "wechatpay_cert.pem"
|
wechatpay-cert-file: "wechatpay_cert.pem"
|
||||||
|
|
||||||
# 阿里云翻译配置
|
|
||||||
aliyun:
|
|
||||||
translate:
|
|
||||||
access-key-id: LTAI5tEsyhW4GCKbds1qsopg
|
|
||||||
access-key-secret: zltFlQrYVAoq2KMFDWgLa3GhkMNeyO
|
|
||||||
endpoint: mt.cn-hangzhou.aliyuncs.com
|
|
||||||
|
|||||||
@@ -22,13 +22,6 @@ spring:
|
|||||||
jackson:
|
jackson:
|
||||||
time-zone: GMT+8
|
time-zone: GMT+8
|
||||||
date-format: yyyy-MM-dd HH:mm:ss
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
serialization:
|
|
||||||
write-dates-as-timestamps: false
|
|
||||||
deserialization:
|
|
||||||
fail-on-unknown-properties: false
|
|
||||||
# 确保启用Java 8时间支持
|
|
||||||
modules:
|
|
||||||
- com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
|
|
||||||
|
|
||||||
# 连接池配置
|
# 连接池配置
|
||||||
datasource:
|
datasource:
|
||||||
@@ -99,11 +92,10 @@ config:
|
|||||||
# 主服务器
|
# 主服务器
|
||||||
server-url: https://server.websoft.top/api
|
server-url: https://server.websoft.top/api
|
||||||
# 文件服务器
|
# 文件服务器
|
||||||
file-server: https://file.websoft.top
|
file-server: https://file.wsdns.cn
|
||||||
# 其他
|
upload-path: /Users/gxwebsoft/Documents/uploads/
|
||||||
api-url: https://server.websoft.top/api
|
local-upload-path: /Users/gxwebsoft/Documents/uploads/
|
||||||
upload-path: /Users/gxwebsoft/Documents/uploads
|
api-url: https://cms-api.websoft.top/api
|
||||||
local-upload-path: /Users/gxwebsoft/Documents/uploads
|
|
||||||
|
|
||||||
# 阿里云OSS云存储
|
# 阿里云OSS云存储
|
||||||
endpoint: https://oss-cn-shenzhen.aliyuncs.com
|
endpoint: https://oss-cn-shenzhen.aliyuncs.com
|
||||||
@@ -118,18 +110,18 @@ shop:
|
|||||||
order:
|
order:
|
||||||
# 测试账号配置
|
# 测试账号配置
|
||||||
test-account:
|
test-account:
|
||||||
enabled: true # 禁用测试账号功能
|
enabled: true
|
||||||
phone-numbers:
|
phone-numbers:
|
||||||
- "19163679581" # 改为其他测试手机号
|
- "13737128880"
|
||||||
test-pay-amount: 0.01
|
test-pay-amount: 0.01
|
||||||
|
|
||||||
# 租户特殊规则配置
|
# 租户特殊规则配置
|
||||||
# tenant-rules:
|
tenant-rules:
|
||||||
# - tenant-id: 10324
|
- tenant-id: 10324
|
||||||
# tenant-name: "百色中学"
|
tenant-name: "百色中学"
|
||||||
# min-amount: 10
|
min-amount: 10
|
||||||
# min-amount-message: "捐款金额最低不能少于10元,感谢您的爱心捐赠^_^"
|
min-amount-message: "捐款金额最低不能少于10元,感谢您的爱心捐赠^_^"
|
||||||
# enabled: true
|
enabled: true
|
||||||
|
|
||||||
# 默认配置
|
# 默认配置
|
||||||
default-config:
|
default-config:
|
||||||
@@ -138,32 +130,6 @@ shop:
|
|||||||
min-order-amount: 0
|
min-order-amount: 0
|
||||||
order-timeout-minutes: 30
|
order-timeout-minutes: 30
|
||||||
|
|
||||||
# 订单自动取消配置
|
|
||||||
auto-cancel:
|
|
||||||
# 是否启用自动取消功能
|
|
||||||
enabled: true
|
|
||||||
# 默认超时时间(分钟)
|
|
||||||
default-timeout-minutes: 30
|
|
||||||
# 定时任务检查间隔(分钟)
|
|
||||||
check-interval-minutes: 1
|
|
||||||
# 批量处理大小
|
|
||||||
batch-size: 100
|
|
||||||
# 定时任务执行时间(cron表达式)
|
|
||||||
# 生产环境:每5分钟执行一次
|
|
||||||
cron: "0 */5 * * * ?"
|
|
||||||
|
|
||||||
# 租户特殊配置
|
|
||||||
# tenant-configs:
|
|
||||||
# - tenant-id: 10324
|
|
||||||
# tenant-name: "百色中学"
|
|
||||||
# timeout-minutes: 120 # 捐款订单给更长的支付时间
|
|
||||||
# enabled: true
|
|
||||||
# 可以添加更多租户配置
|
|
||||||
# - tenant-id: 10550
|
|
||||||
# tenant-name: "其他租户"
|
|
||||||
# timeout-minutes: 15
|
|
||||||
# enabled: true
|
|
||||||
|
|
||||||
# 证书配置
|
# 证书配置
|
||||||
certificate:
|
certificate:
|
||||||
# 证书加载模式: CLASSPATH, FILESYSTEM, VOLUME
|
# 证书加载模式: CLASSPATH, FILESYSTEM, VOLUME
|
||||||
@@ -198,50 +164,6 @@ springdoc:
|
|||||||
swagger-ui:
|
swagger-ui:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
# LED - 排班接口(业务中台)对接配置
|
|
||||||
led:
|
|
||||||
bme:
|
|
||||||
base-url: ${LED_BME_BASE_URL:http://16.1.4.201:7979}
|
|
||||||
appid: ${LED_BME_APPID:BQ73n58Lf}
|
|
||||||
secret-key: ${LED_BME_SECRET_KEY:jk720-DCPnGq@5t8}
|
|
||||||
mechanism-id: ${LED_BME_MECHANISM_ID:10001}
|
|
||||||
default-ext-user-id: ${LED_BME_DEFAULT_EXT_USER_ID:txzhyy}
|
|
||||||
default-hospital-id: ${LED_BME_DEFAULT_HOSPITAL_ID:}
|
|
||||||
timeout-ms: ${LED_BME_TIMEOUT_MS:10000}
|
|
||||||
|
|
||||||
# 启用 Knife4j
|
# 启用 Knife4j
|
||||||
knife4j:
|
knife4j:
|
||||||
enable: true
|
enable: true
|
||||||
|
|
||||||
# 优惠券配置
|
|
||||||
coupon:
|
|
||||||
# 过期处理定时任务配置
|
|
||||||
expire:
|
|
||||||
# 定时任务执行时间(cron表达式)
|
|
||||||
# 生产环境:每天凌晨2点执行
|
|
||||||
# 开发环境:每10分钟执行一次
|
|
||||||
cron: "0 0 2 * * ?"
|
|
||||||
# 开发环境可以设置为: "0 */10 * * * ?"
|
|
||||||
|
|
||||||
# 状态管理配置
|
|
||||||
status:
|
|
||||||
# 是否启用自动状态更新
|
|
||||||
auto-update: true
|
|
||||||
# 批量处理大小
|
|
||||||
batch-size: 1000
|
|
||||||
|
|
||||||
# 支付配置
|
|
||||||
payment:
|
|
||||||
# 开发环境配置
|
|
||||||
dev:
|
|
||||||
# 开发环境回调地址(本地调试用)
|
|
||||||
notify-url: "http://frps-10550.s209.websoft.top/api/shop/shop-order/notify"
|
|
||||||
# 开发环境是否启用环境感知
|
|
||||||
environment-aware: true
|
|
||||||
|
|
||||||
# 生产环境配置
|
|
||||||
prod:
|
|
||||||
# 生产环境回调地址
|
|
||||||
notify-url: "https://cms-api.websoft.top/api/shop/shop-order/notify"
|
|
||||||
# 生产环境是否启用环境感知
|
|
||||||
environment-aware: false
|
|
||||||
|
|||||||
24
src/main/resources/sql/house_ai_config.sql
Normal file
24
src/main/resources/sql/house_ai_config.sql
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
CREATE TABLE `house_ai_config` (
|
||||||
|
`config_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||||
|
`ai_avatar` varchar(500) DEFAULT NULL COMMENT 'AI形象照',
|
||||||
|
`ai_entry_image` varchar(500) DEFAULT NULL COMMENT '首页AI入口图',
|
||||||
|
`ai_float_image` varchar(500) DEFAULT NULL COMMENT '首页AI悬浮图',
|
||||||
|
`welcome_message` varchar(500) DEFAULT NULL COMMENT '欢迎词',
|
||||||
|
`status` tinyint(1) DEFAULT 0 COMMENT '状态 0正常 1禁用',
|
||||||
|
`deleted` tinyint(1) DEFAULT 0 COMMENT '是否删除, 0否, 1是',
|
||||||
|
`tenant_id` int(11) DEFAULT NULL COMMENT '租户ID',
|
||||||
|
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`config_id`),
|
||||||
|
KEY `idx_house_ai_config_status` (`status`),
|
||||||
|
KEY `idx_house_ai_config_tenant` (`tenant_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI找房配置';
|
||||||
|
|
||||||
|
INSERT INTO `house_ai_config` (`ai_avatar`, `ai_entry_image`, `ai_float_image`, `welcome_message`, `status`)
|
||||||
|
VALUES
|
||||||
|
('https://oss.wsdns.cn/20260601/0d53634419a448919c90c99ab9779d8a.png?x-oss-process=image/resize,w_750/quality,Q_90', 'https://oss.wsdns.cn/20260626/f5f7d5996e4f45ce8bb24c7c455d07d4.png?x-oss-process=image/resize,m_fixed,w_750/quality,Q_90', 'https://oss.wsdns.cn/20260626/e666a52de6724578b6df007fcacbbe21.gif?x-oss-process=image/resize,m_fixed,w_750/quality,Q_90', '您好,我是AI找房助手,请告诉我面积、楼层、预算和地段,我来帮您筛选更合适的房源。', 0);
|
||||||
|
|
||||||
|
-- 已有表升级时执行:
|
||||||
|
-- ALTER TABLE `house_ai_config`
|
||||||
|
-- ADD COLUMN `ai_entry_image` varchar(500) DEFAULT NULL COMMENT '首页AI入口图' AFTER `ai_avatar`,
|
||||||
|
-- ADD COLUMN `ai_float_image` varchar(500) DEFAULT NULL COMMENT '首页AI悬浮图' AFTER `ai_entry_image`;
|
||||||
24
src/main/resources/sql/house_faq.sql
Normal file
24
src/main/resources/sql/house_faq.sql
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
CREATE TABLE `house_faq` (
|
||||||
|
`faq_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||||
|
`question` varchar(255) NOT NULL COMMENT '问题',
|
||||||
|
`keywords` varchar(500) DEFAULT NULL COMMENT '关键词,多个用逗号分隔',
|
||||||
|
`answer` text COMMENT '标准回答',
|
||||||
|
`category` varchar(100) DEFAULT NULL COMMENT '分类',
|
||||||
|
`sort_number` int(11) DEFAULT 0 COMMENT '排序号',
|
||||||
|
`status` tinyint(1) DEFAULT 0 COMMENT '状态 0正常 1禁用',
|
||||||
|
`user_id` int(11) DEFAULT NULL COMMENT '创建用户ID',
|
||||||
|
`deleted` tinyint(1) DEFAULT 0 COMMENT '是否删除, 0否, 1是',
|
||||||
|
`tenant_id` int(11) DEFAULT NULL COMMENT '租户ID',
|
||||||
|
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`faq_id`),
|
||||||
|
KEY `idx_house_faq_status` (`status`),
|
||||||
|
KEY `idx_house_faq_sort` (`sort_number`),
|
||||||
|
KEY `idx_house_faq_tenant` (`tenant_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI找房常见问题';
|
||||||
|
|
||||||
|
INSERT INTO `house_faq` (`question`, `keywords`, `answer`, `category`, `sort_number`, `status`)
|
||||||
|
VALUES
|
||||||
|
('怎么预约看房?', '预约看房,带看,流程', '在房源详情页点击预约看房,填写联系人和电话后提交即可,我们会尽快安排带看。', '看房流程', 1, 0),
|
||||||
|
('签约一般需要准备什么材料?', '签约,材料,合同', '通常需要准备身份证明、联系方式、企业主体资料(如为公司租赁)等,具体以顾问通知为准。', '签约流程', 2, 0),
|
||||||
|
('租房押金和佣金怎么收?', '押金,佣金,费用', '押金、佣金标准会根据具体房源和签约方式有所不同,您可以先告诉我目标房源或预算,我会优先帮您筛选合适房源,再由顾问说明费用细节。', '费用说明', 3, 0);
|
||||||
19
src/main/resources/sql/house_message.sql
Normal file
19
src/main/resources/sql/house_message.sql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
CREATE TABLE `house_message` (
|
||||||
|
`message_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||||
|
`user_id` int(11) DEFAULT NULL COMMENT '用户ID',
|
||||||
|
`real_name` varchar(100) NOT NULL COMMENT '姓名',
|
||||||
|
`phone` varchar(30) DEFAULT NULL COMMENT '手机号',
|
||||||
|
`wechat` varchar(100) DEFAULT NULL COMMENT '微信号',
|
||||||
|
`source` varchar(50) DEFAULT 'ai_house' COMMENT '来源',
|
||||||
|
`comments` varchar(500) DEFAULT NULL COMMENT '备注',
|
||||||
|
`status` tinyint(1) DEFAULT 0 COMMENT '状态 0未处理 1已处理',
|
||||||
|
`deleted` tinyint(1) DEFAULT 0 COMMENT '是否删除, 0否, 1是',
|
||||||
|
`tenant_id` int(11) DEFAULT NULL COMMENT '租户ID',
|
||||||
|
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`message_id`),
|
||||||
|
KEY `idx_house_message_user` (`user_id`),
|
||||||
|
KEY `idx_house_message_status` (`status`),
|
||||||
|
KEY `idx_house_message_tenant` (`tenant_id`),
|
||||||
|
KEY `idx_house_message_create_time` (`create_time`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI找房留言';
|
||||||
BIN
websoft-modules.log.2025-08-11.0.gz
Normal file
BIN
websoft-modules.log.2025-08-11.0.gz
Normal file
Binary file not shown.
Reference in New Issue
Block a user