Browse Source

Merge remote-tracking branch 'origin/zy1' into lzy

# Conflicts:
#	.idea/dataSources.xml
#	.idea/jarRepositories.xml
#	.idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_11.xml
#	.idea/libraries/Maven__ch_qos_logback_logback_core_1_2_11.xml
#	.idea/libraries/Maven__com_alibaba_fastjson_1_2_83.xml
#	.idea/libraries/Maven__com_aliyun_aliyun_java_sdk_core_4_5_10.xml
#	.idea/libraries/Maven__com_aliyun_aliyun_java_sdk_kms_2_11_0.xml
#	.idea/libraries/Maven__com_aliyun_aliyun_java_sdk_ram_3_1_0.xml
#	.idea/libraries/Maven__com_aliyun_oss_aliyun_sdk_oss_3_15_1.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_3_5_4.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_annotation_3_5_4.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_boot_starter_3_5_4.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_core_3_5_4.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_extension_3_5_4.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_spring_boot_autoconfigure_3_5_4.xml
#	.idea/libraries/Maven__com_fasterxml_classmate_1_5_1.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_13_4.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_13_4.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_13_4_2.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_13_4.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_13_4.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_13_4.xml
#	.idea/libraries/Maven__com_github_jsqlparser_jsqlparser_4_6.xml
#	.idea/libraries/Maven__com_google_code_gson_gson_2_9_1.xml
#	.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_7_0.xml
#	.idea/libraries/Maven__com_mysql_mysql_connector_j_8_0_31.xml
#	.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml
#	.idea/libraries/Maven__com_zaxxer_HikariCP_4_0_3.xml
#	.idea/libraries/Maven__commons_codec_commons_codec_1_15.xml
#	.idea/libraries/Maven__commons_logging_commons_logging_1_2.xml
#	.idea/libraries/Maven__io_jsonwebtoken_jjwt_0_9_0.xml
#	.idea/libraries/Maven__io_lettuce_lettuce_core_6_1_10_RELEASE.xml
#	.idea/libraries/Maven__io_netty_netty_buffer_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_codec_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_common_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_handler_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_resolver_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_transport_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_transport_native_unix_common_4_1_85_Final.xml
#	.idea/libraries/Maven__io_opentracing_opentracing_api_0_33_0.xml
#	.idea/libraries/Maven__io_opentracing_opentracing_noop_0_33_0.xml
#	.idea/libraries/Maven__io_opentracing_opentracing_util_0_33_0.xml
#	.idea/libraries/Maven__io_projectreactor_reactor_core_3_4_25.xml
#	.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml
#	.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml
#	.idea/libraries/Maven__jakarta_validation_jakarta_validation_api_2_0_2.xml
#	.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml
#	.idea/libraries/Maven__javax_activation_javax_activation_api_1_2_0.xml
#	.idea/libraries/Maven__javax_validation_validation_api_2_0_1_Final.xml
#	.idea/libraries/Maven__javax_xml_bind_jaxb_api_2_3_1.xml
#	.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_12_19.xml
#	.idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_12_19.xml
#	.idea/libraries/Maven__net_minidev_accessors_smart_2_4_8.xml
#	.idea/libraries/Maven__net_minidev_json_smart_2_4_8.xml
#	.idea/libraries/Maven__org_apache_httpcomponents_httpclient_4_5_13.xml
#	.idea/libraries/Maven__org_apache_httpcomponents_httpcore_4_4_15.xml
#	.idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_17_2.xml
#	.idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_17_2.xml
#	.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_69.xml
#	.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_el_9_0_69.xml
#	.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_69.xml
#	.idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_2.xml
#	.idea/libraries/Maven__org_assertj_assertj_core_3_22_0.xml
#	.idea/libraries/Maven__org_codehaus_jettison_jettison_1_1.xml
#	.idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml
#	.idea/libraries/Maven__org_hibernate_validator_hibernate_validator_6_2_0_Final.xml
#	.idea/libraries/Maven__org_ini4j_ini4j_0_5_4.xml
#	.idea/libraries/Maven__org_jacoco_org_jacoco_agent_runtime_0_8_5.xml
#	.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_4_3_Final.xml
#	.idea/libraries/Maven__org_jdom_jdom2_2_0_6_1.xml
#	.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_8_2.xml
#	.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_8_2.xml
#	.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_8_2.xml
#	.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_8_2.xml
#	.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_8_2.xml
#	.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_8_2.xml
#	.idea/libraries/Maven__org_mockito_mockito_core_4_5_1.xml
#	.idea/libraries/Maven__org_mockito_mockito_junit_jupiter_4_5_1.xml
#	.idea/libraries/Maven__org_mybatis_mybatis_3_5_11.xml
#	.idea/libraries/Maven__org_mybatis_mybatis_spring_2_1_1.xml
#	.idea/libraries/Maven__org_mybatis_spring_boot_mybatis_spring_boot_autoconfigure_2_3_0.xml
#	.idea/libraries/Maven__org_mybatis_spring_boot_mybatis_spring_boot_starter_2_3_0.xml
#	.idea/libraries/Maven__org_objenesis_objenesis_3_2.xml
#	.idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml
#	.idea/libraries/Maven__org_ow2_asm_asm_9_1.xml
#	.idea/libraries/Maven__org_projectlombok_lombok_1_18_24.xml
#	.idea/libraries/Maven__org_reactivestreams_reactive_streams_1_0_4.xml
#	.idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_1.xml
#	.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_36.xml
#	.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_36.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_data_redis_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_jdbc_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_data_spring_data_commons_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_data_spring_data_keyvalue_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_data_spring_data_redis_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_security_spring_security_crypto_5_7_6.xml
#	.idea/libraries/Maven__org_springframework_spring_aop_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_beans_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_context_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_context_support_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_core_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_expression_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_jcl_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_jdbc_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_oxm_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_test_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_tx_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_web_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_webmvc_5_3_24.xml
#	.idea/libraries/Maven__org_xmlunit_xmlunit_core_2_9_0.xml
#	.idea/libraries/Maven__org_yaml_snakeyaml_1_30.xml
#	.idea/libraries/Maven__stax_stax_api_1_0_1.xml
#	.idea/misc.xml
#	.idea/mybatisx/templates.xml
#	Marketplace/pom.xml
#	Marketplace/src/main/java/com/dt/MarketplaceApplication.java
#	Marketplace/src/main/java/com/dt/user/pojo/User.java
lzy 2 months ago
parent
commit
ffaef53ecd

+ 0 - 8
.idea/.gitignore

@@ -1,8 +0,0 @@
-# 默认忽略的文件
-/shelf/
-/workspace.xml
-# 基于编辑器的 HTTP 客户端请求
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml

+ 0 - 16
.idea/compiler.xml

@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="CompilerConfiguration">
-    <annotationProcessing>
-      <profile name="Maven default annotation processors profile" enabled="true">
-        <sourceOutputDir name="target/generated-sources/annotations" />
-        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
-        <outputRelativeToContentRoot value="true" />
-        <module name="Marketplace" />
-      </profile>
-    </annotationProcessing>
-    <bytecodeTargetLevel>
-      <module name="Marketplace" target="1.8" />
-    </bytecodeTargetLevel>
-  </component>
-</project>

+ 0 - 7
.idea/encodings.xml

@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="Encoding">
-    <file url="file://$PROJECT_DIR$/Marketplace/src/main/java" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/Marketplace/src/main/resources" charset="UTF-8" />
-  </component>
-</project>

+ 0 - 8
.idea/modules.xml

@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectModuleManager">
-    <modules>
-      <module fileurl="file://$PROJECT_DIR$/Marketplace/Marketplace.iml" filepath="$PROJECT_DIR$/Marketplace/Marketplace.iml" />
-    </modules>
-  </component>
-</project>

+ 0 - 6
.idea/vcs.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="VcsDirectoryMappings">
-    <mapping directory="" vcs="Git" />
-  </component>
-</project>

BIN
Marketplace/audio/record/record.wav


BIN
Marketplace/audio/synthesis/synthesis.mp3


+ 35 - 3
Marketplace/pom.xml

@@ -30,13 +30,11 @@
             <version>3.5.4</version>
             <version>3.5.4</version>
         </dependency>
         </dependency>
 
 
-
         <dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-redis</artifactId>
             <artifactId>spring-boot-starter-data-redis</artifactId>
         </dependency>
         </dependency>
 
 
-
         <dependency>
         <dependency>
             <groupId>io.jsonwebtoken</groupId>
             <groupId>io.jsonwebtoken</groupId>
             <artifactId>jjwt</artifactId>
             <artifactId>jjwt</artifactId>
@@ -104,7 +102,11 @@
             <artifactId>validation-api</artifactId>
             <artifactId>validation-api</artifactId>
             <version>2.0.1.Final</version>
             <version>2.0.1.Final</version>
         </dependency>
         </dependency>
-
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+            <version>4.12.0</version>
+        </dependency>
         <dependency>
         <dependency>
             <groupId>com.aliyun.oss</groupId>
             <groupId>com.aliyun.oss</groupId>
             <artifactId>aliyun-sdk-oss</artifactId>
             <artifactId>aliyun-sdk-oss</artifactId>
@@ -143,6 +145,36 @@
             <artifactId>spring-security-crypto</artifactId>
             <artifactId>spring-security-crypto</artifactId>
             <version>5.7.6</version>
             <version>5.7.6</version>
         </dependency>
         </dependency>
+        <!-- 百度AI SDK -->
+        <dependency>
+            <groupId>com.baidu.aip</groupId>
+            <artifactId>java-sdk</artifactId>
+            <version>4.16.1</version>
+        </dependency>
+        <!-- Jackson 依赖 -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.13.4</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.21</version> <!-- 可根据实际情况选择最新版本 -->
+        </dependency>
+        <!-- Spring Boot Configuration Processor -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- MP3播放支持 -->
+        <dependency>
+            <groupId>javazoom</groupId>
+            <artifactId>jlayer</artifactId>
+            <version>1.0.1</version>
+        </dependency>
 <!--        yzz-->
 <!--        yzz-->
         <dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <groupId>org.springframework.boot</groupId>

+ 21 - 0
Marketplace/src/main/java/com/dt/ai/controller/ChatController.java

@@ -0,0 +1,21 @@
+package com.dt.ai.controller;
+
+import com.dt.ai.service.ChatService;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+
+@RestController
+@RequestMapping("/chat")
+public class ChatController {
+    private final ChatService chatService;
+
+    public ChatController(ChatService chatService) {
+        this.chatService = chatService;
+    }
+
+    @PostMapping("AI")
+    public String chat(@RequestBody String message) throws IOException {
+        return chatService.chat(message);
+    }
+} 

+ 44 - 0
Marketplace/src/main/java/com/dt/ai/controller/VoiceCallController.java

@@ -0,0 +1,44 @@
+package com.dt.ai.controller;
+
+
+import com.dt.ai.service.VoiceCallService;
+import com.dt.config.NonLoginRequired;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+
+@RestController
+@RequestMapping("/api")
+@CrossOrigin(origins = "*")
+public class VoiceCallController {
+
+    @Autowired
+    private VoiceCallService voiceCallService;
+
+    // 语音识别接口
+    @PostMapping("/speech-to-text")
+    @NonLoginRequired
+    public String speechToText(@RequestParam("audio") MultipartFile audioFile) throws IOException {
+        File tempFile = File.createTempFile("audio", ".wav");
+        audioFile.transferTo(tempFile);
+        return voiceCallService.speechToText(tempFile.getAbsolutePath());
+    }
+
+    // 获取AI回复接口
+    @PostMapping("/get-ai-response")
+    @NonLoginRequired
+    public String getAiResponse(@RequestBody String userText) {
+        return voiceCallService.getAiResponse(userText);
+    }
+
+    // 语音合成接口
+    @PostMapping("/text-to-speech")
+    @NonLoginRequired
+    public String textToSpeech(@RequestBody String text) {
+        String synthesisFile = "audio/synthesis/synthesis.mp3";
+        return voiceCallService.textToSpeech(text, synthesisFile);
+    }
+}

+ 58 - 0
Marketplace/src/main/java/com/dt/ai/model/ChatRequest.java

@@ -0,0 +1,58 @@
+package com.dt.ai.model;
+
+public class ChatRequest {
+    private String model = "ernie-4.5-turbo-128k";
+    private Message[] messages;
+
+    public ChatRequest() {
+    }
+
+    public ChatRequest(Message[] messages) {
+        this.messages = messages;
+    }
+
+    public String getModel() {
+        return model;
+    }
+
+    public void setModel(String model) {
+        this.model = model;
+    }
+
+    public Message[] getMessages() {
+        return messages;
+    }
+
+    public void setMessages(Message[] messages) {
+        this.messages = messages;
+    }
+
+    public static class Message {
+        private String role;
+        private String content="你是个婴儿护理的医生";
+
+        public Message() {
+        }
+
+        public Message(String role, String content) {
+            this.role = role;
+            this.content = content;
+        }
+
+        public String getRole() {
+            return role;
+        }
+
+        public void setRole(String role) {
+            this.role = role;
+        }
+
+        public String getContent() {
+            return content;
+        }
+
+        public void setContent(String content) {
+            this.content = content;
+        }
+    }
+} 

+ 51 - 0
Marketplace/src/main/java/com/dt/ai/model/ChatResponse.java

@@ -0,0 +1,51 @@
+package com.dt.ai.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ChatResponse {
+    private Choice[] choices;
+
+    public Choice[] getChoices() {
+        return choices;
+    }
+
+    public void setChoices(Choice[] choices) {
+        this.choices = choices;
+    }
+
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    public static class Choice {
+        private Message message;
+
+        public Message getMessage() {
+            return message;
+        }
+
+        public void setMessage(Message message) {
+            this.message = message;
+        }
+    }
+
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    public static class Message {
+        private String role;
+        private String content;
+
+        public String getRole() {
+            return role;
+        }
+
+        public void setRole(String role) {
+            this.role = role;
+        }
+
+        public String getContent() {
+            return content;
+        }
+
+        public void setContent(String content) {
+            this.content = content;
+        }
+    }
+} 

+ 51 - 0
Marketplace/src/main/java/com/dt/ai/service/ChatService.java

@@ -0,0 +1,51 @@
+package com.dt.ai.service;
+
+import com.dt.ai.model.ChatRequest;
+import com.dt.ai.model.ChatRequest.Message;
+import com.dt.ai.model.ChatResponse;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.*;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+@Service
+public class ChatService {
+    private static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder()
+            .readTimeout(300, TimeUnit.SECONDS)
+            .build();
+    
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+    public String chat(String message) throws IOException {
+        // 创建系统消息和用户消息
+        Message systemMessage = new Message("system", "你是个婴儿护理的医生");
+        Message userMessage = new Message("user", message);
+        
+        // 将系统消息和用户消息组合成一个数组
+        ChatRequest chatRequest = new ChatRequest(new Message[]{systemMessage, userMessage});
+        String requestJson = objectMapper.writeValueAsString(chatRequest);
+        
+        MediaType mediaType = MediaType.parse("application/json");
+        RequestBody body = RequestBody.create(mediaType, requestJson);
+        
+        Request request = new Request.Builder()
+                .url("https://qianfan.baidubce.com/v2/chat/completions")
+                .post(body)
+                .addHeader("Content-Type", "application/json")
+                .addHeader("appid", "")
+                .addHeader("Authorization", "Bearer bce-v3/ALTAK-TUpAcVUc23264iv606UkH/feac26b64b72c99e3548f304bfe59067b9c9d47a")
+                .build();
+                
+        try (Response response = HTTP_CLIENT.newCall(request).execute()) {
+            String responseBody = response.body().string();
+            ChatResponse chatResponse = objectMapper.readValue(responseBody, ChatResponse.class);
+            
+            if (chatResponse.getChoices() != null && chatResponse.getChoices().length > 0) {
+                return chatResponse.getChoices()[0].getMessage().getContent();
+            }
+            return "No response content available";
+        }
+    }
+} 

+ 408 - 0
Marketplace/src/main/java/com/dt/ai/service/VoiceCallService.java

@@ -0,0 +1,408 @@
+package com.dt.ai.service;
+
+import cn.hutool.core.util.StrUtil;
+import com.baidu.aip.speech.AipSpeech;
+import com.baidu.aip.speech.TtsResponse;
+import com.baidu.aip.util.Util;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.*;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.sound.sampled.*;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class VoiceCallService {
+    private final AipSpeech aipSpeech;
+    private final ObjectMapper objectMapper = new ObjectMapper();
+    private static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder()
+            .readTimeout(300, TimeUnit.SECONDS)
+            .build();
+
+    @Value("${baidu.asr.format}")
+    private String asrFormat;
+    @Value("${baidu.asr.rate}")
+    private int asrRate;
+    @Value("${baidu.tts.lang}")
+    private String ttsLang;
+    @Value("${baidu.tts.per}")
+    private int ttsPer;
+    @Value("${baidu.wenxin.api-key}")
+    private String wenxinApiKey;
+
+    private static final double SILENCE_THRESHOLD = 100.0; // 静音阈值
+    private static final int SILENCE_DURATION = 3000; // 静音持续时间阈值(毫秒)
+    private volatile boolean isListening = false; // 是否正在监听
+    private volatile boolean isSpeaking = false; // 是否正在播放
+
+    /**
+     * 检查播放是否正常完成(未被打断)
+     */
+    public boolean isPlaybackCompleted() {
+        return !isSpeaking;
+    }
+
+    /**
+     * 检测音频数据中是否有声音
+     */
+    private boolean hasSound(byte[] buffer, int bytesRead) {
+        if (bytesRead <= 0) return false;
+        
+        // 计算音频能量
+        double sum = 0;
+        for (int i = 0; i < bytesRead; i += 2) {
+            if (i + 1 < bytesRead) {
+                // 将两个字节转换为16位整数
+                short sample = (short) ((buffer[i + 1] << 8) | (buffer[i] & 0xFF));
+                sum += Math.abs(sample);
+            }
+        }
+        double average = sum / (bytesRead / 2);
+        return average > SILENCE_THRESHOLD;
+    }
+
+    public VoiceCallService(AipSpeech aipSpeech) {
+        this.aipSpeech = aipSpeech;
+    }
+
+    /**
+     * 1. 录音功能 - 支持动态检测说话停止
+     */
+    public String recordVoice(String savePath, int maxRecordSeconds) {
+        try {
+            // 设置音频格式为16kHz, 16bit, 单声道,符合百度语音识别要求
+            AudioFormat format = new AudioFormat(16000, 16, 1, true, false);
+            DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
+
+            if (!AudioSystem.isLineSupported(info)) {
+                System.err.println("不支持该音频格式!");
+                return null;
+            }
+
+            // 获取并打开录音设备
+            TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info);
+            line.open(format);
+            line.start();
+
+            System.out.println("\n=== 开始录音 ===");
+            System.out.println("请说话...(静音3秒后自动停止)");
+
+            // 创建临时缓冲区
+            int bufferSize = 4096;
+            byte[] buffer = new byte[bufferSize];
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+            // 录音
+            long startTime = System.currentTimeMillis();
+            long lastSoundTime = startTime;
+            isListening = true;
+
+            while (isListening && (System.currentTimeMillis() - startTime < maxRecordSeconds * 1000)) {
+                int count = line.read(buffer, 0, buffer.length);
+                if (count > 0) {
+                    if (hasSound(buffer, count)) {
+                        lastSoundTime = System.currentTimeMillis();
+                    } else if (System.currentTimeMillis() - lastSoundTime > SILENCE_DURATION) {
+                        // 检测到持续静音,停止录音
+                        System.out.println("检测到停止说话");
+                        break;
+                    }
+                    out.write(buffer, 0, count);
+                }
+            }
+
+            isListening = false;
+            
+            // 停止录音
+            line.stop();
+            line.close();
+
+            // 保存录音文件
+            byte[] audioData = out.toByteArray();
+            if (audioData.length == 0) {
+                System.out.println("未检测到声音");
+                return null;
+            }
+
+            File audioFile = new File(savePath);
+            if (!audioFile.getParentFile().exists()) {
+                audioFile.getParentFile().mkdirs();
+            }
+
+            // 创建音频输入流
+            AudioInputStream ais = new AudioInputStream(
+                new java.io.ByteArrayInputStream(audioData),
+                format,
+                audioData.length / format.getFrameSize()
+            );
+
+            // 写入WAV文件
+            AudioSystem.write(ais, AudioFileFormat.Type.WAVE, audioFile);
+
+            System.out.println("录音完成!");
+            System.out.println("文件已保存:" + audioFile.getAbsolutePath());
+            System.out.println("文件大小:" + audioFile.length() + " bytes");
+
+            return savePath;
+
+        } catch (Exception e) {
+            System.err.println("录音过程出错:" + e.getMessage());
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 2. 语音识别
+     */
+    public String speechToText(String audioPath) {
+        try {
+            // 读取音频文件
+            byte[] data = Util.readFileByBytes(audioPath);
+            if (data == null || data.length == 0) {
+                return "错误:音频文件为空";
+            }
+            
+            // 调用语音识别
+            JSONObject result = aipSpeech.asr(data, asrFormat, asrRate, new HashMap<>());
+            System.out.println("语音识别结果:" + result.toString());
+            
+            // 检查错误码
+            if (!result.has("err_no")) {
+                return "识别失败:返回结果缺少错误码";
+            }
+
+            int errorCode = result.getInt("err_no");
+            if (errorCode != 0) {
+                return "识别失败:" + result.getString("err_msg");
+            }
+
+            // 检查识别结果
+            if (!result.has("result") || result.getJSONArray("result").length() == 0) {
+                return "识别失败:未返回识别结果";
+            }
+
+            // 返回第一个识别结果
+            return result.getJSONArray("result").getString(0);
+            
+        } catch (Exception e) {
+            System.err.println("语音识别异常:" + e.getMessage());
+            e.printStackTrace();
+            return "识别异常:" + e.getMessage();
+        }
+    }
+
+    /**
+     * 3. AI回复生成
+     */
+    public String getAiResponse(String userText) {
+        if (StrUtil.isEmpty(userText)) {
+            return "请再说一遍,我没听清。";
+        }
+
+        try {
+            // 构建请求体
+            HashMap<String, Object> requestMap = new HashMap<>();
+            requestMap.put("model", "ernie-4.5-turbo-128k");
+            
+            // 构建消息数组
+            HashMap<String, String> systemMessage = new HashMap<>();
+            systemMessage.put("role", "system");
+            systemMessage.put("content", "你是一位专业的婴儿护理医生,拥有丰富的婴儿护理经验。你只回答与婴儿护理相关的问题,包括新生儿护理、婴儿喂养、婴儿健康、生长发育、疫苗接种、常见疾病预防等方面的咨询。如果遇到其他领域的问题,你会礼貌地表示:'抱歉,这个问题不在我的专业范围内。我是一名婴儿护理医生,只能为您解答婴儿护理相关的问题。'");
+            
+            HashMap<String, String> userMessage = new HashMap<>();
+            userMessage.put("role", "user");
+            userMessage.put("content", userText);
+            
+            requestMap.put("messages", new Object[]{systemMessage, userMessage});
+            
+            // 转换为JSON
+            String requestJson = objectMapper.writeValueAsString(requestMap);
+            
+            // 构建HTTP请求
+            MediaType mediaType = MediaType.parse("application/json");
+            RequestBody body = RequestBody.create(mediaType, requestJson);
+            
+            Request request = new Request.Builder()
+                    .url("https://qianfan.baidubce.com/v2/chat/completions")
+                    .post(body)
+                    .addHeader("Content-Type", "application/json")
+                    .addHeader("Authorization", "Bearer " + wenxinApiKey)
+                    .build();
+            
+            // 发送请求并处理响应
+            try (Response response = HTTP_CLIENT.newCall(request).execute()) {
+                if (!response.isSuccessful()) {
+                    System.err.println("API调用失败: " + response.code());
+                    return "抱歉,我现在无法回答,请稍后再试。";
+                }
+                
+                String responseBody = response.body().string();
+                JSONObject jsonResponse = new JSONObject(responseBody);
+                
+                if (jsonResponse.has("choices") && jsonResponse.getJSONArray("choices").length() > 0) {
+                    return jsonResponse.getJSONArray("choices")
+                            .getJSONObject(0)
+                            .getJSONObject("message")
+                            .getString("content");
+                }
+                
+                return "抱歉,我没有得到有效的回答。";
+            }
+        } catch (Exception e) {
+            System.err.println("调用文心一言API异常: " + e.getMessage());
+            e.printStackTrace();
+            return "系统出现了一点小问题,请稍后再试。";
+        }
+    }
+
+    /**
+     * 4. 语音合成
+     */
+    public String textToSpeech(String text, String savePath) {
+        try {
+            if (text == null || text.trim().isEmpty()) {
+                throw new IllegalArgumentException("合成文本不能为空");
+            }
+
+            // 调用语音合成
+            HashMap<String, Object> options = new HashMap<>();
+            options.put("per", ttsPer);
+            options.put("spd", 5);
+            options.put("pit", 5);
+            options.put("vol", 5);
+            
+            TtsResponse response = aipSpeech.synthesis(text, ttsLang, 1, options);
+            
+            // 检查合成结果
+            if (response == null) {
+                throw new RuntimeException("合成响应为空");
+            }
+            
+            byte[] data = response.getData();
+            if (data == null || data.length == 0) {
+                JSONObject error = response.getResult();
+                if (error != null) {
+                    throw new RuntimeException("合成失败:" + error.toString());
+                } else {
+                    throw new RuntimeException("合成失败:返回数据为空");
+                }
+            }
+            
+            // 保存音频文件
+            File file = new File(savePath);
+            if (!file.getParentFile().exists()) {
+                file.getParentFile().mkdirs();
+            }
+            
+            Util.writeBytesToFileSystem(data, savePath);
+            return savePath;
+            
+        } catch (Exception e) {
+            System.err.println("语音合成异常:" + e.getMessage());
+            e.printStackTrace();
+            return "合成失败:" + e.getMessage();
+        }
+    }
+
+    /**
+     * 5. 播放语音 - 支持动态打断
+     */
+    public void playVoice(String audioPath) {
+        if (audioPath == null || audioPath.startsWith("合成失败")) {
+            System.err.println(audioPath);
+            return;
+        }
+        
+        File audioFile = new File(audioPath);
+        if (!audioFile.exists()) {
+            System.err.println("播放失败:文件不存在 - " + audioPath);
+            return;
+        }
+
+        try {
+            isSpeaking = true;
+
+            // 启动监听线程
+            Thread monitorThread = new Thread(() -> {
+                try {
+                    // 设置音频格式
+                    AudioFormat format = new AudioFormat(16000, 16, 1, true, false);
+                    DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
+                    TargetDataLine monitorLine = (TargetDataLine) AudioSystem.getLine(info);
+                    monitorLine.open(format);
+                    monitorLine.start();
+
+                    byte[] buffer = new byte[4096];
+                    while (isSpeaking) {
+                        int count = monitorLine.read(buffer, 0, buffer.length);
+                        if (hasSound(buffer, count)) {
+                            System.out.println("\n检测到用户说话,停止播放...");
+                            isSpeaking = false;
+                            break;
+                        }
+                    }
+                    monitorLine.stop();
+                    monitorLine.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            });
+            monitorThread.start();
+
+            // 尝试使用JavaZoom库播放MP3
+            try {
+                javazoom.jl.player.Player player = new javazoom.jl.player.Player(new FileInputStream(audioFile));
+                System.out.println("开始播放...");
+                while (!player.isComplete() && isSpeaking) {
+                    player.play(1); // 每次播放一帧,以便能够及时响应中断
+                }
+                System.out.println(isSpeaking ? "播放结束" : "播放被打断");
+                return;
+            } catch (Exception e) {
+                // 如果不是MP3格式,尝试用普通方式播放WAV
+                System.out.println("尝试作为WAV文件播放...");
+            }
+
+            // WAV文件播放逻辑
+            AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
+            AudioFormat format = audioStream.getFormat();
+            DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
+
+            if (!AudioSystem.isLineSupported(info)) {
+                throw new LineUnavailableException("不支持的音频格式");
+            }
+
+            SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
+            line.open(format);
+            line.start();
+
+            System.out.println("开始播放...");
+            byte[] buffer = new byte[4096];
+            int bytesRead = 0;
+
+            while ((bytesRead = audioStream.read(buffer)) != -1 && isSpeaking) {
+                line.write(buffer, 0, bytesRead);
+            }
+
+            line.drain();
+            line.stop();
+            line.close();
+            audioStream.close();
+            
+            System.out.println(isSpeaking ? "播放结束" : "播放被打断");
+            
+        } catch (Exception e) {
+            System.err.println("播放失败:" + e.getMessage());
+            e.printStackTrace();
+        } finally {
+            isSpeaking = false;
+        }
+    }
+}

+ 72 - 0
Marketplace/src/main/java/com/dt/config/BaiduAIConfig.java

@@ -0,0 +1,72 @@
+package com.dt.config;
+
+import com.baidu.aip.speech.AipSpeech;
+import com.baidu.aip.speech.TtsResponse;
+import lombok.Data;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.HashMap;
+
+@Configuration
+@ConfigurationProperties(prefix = "baidu.ai")
+@Data
+public class BaiduAIConfig {
+    private static final Logger logger = LoggerFactory.getLogger(BaiduAIConfig.class);
+    
+    private String appId;
+    private String apiKey;
+    private String secretKey;
+
+    @Bean
+    public AipSpeech aipSpeech() {
+        logger.info("========== 百度AI配置信息 ==========");
+        logger.info("AppID: {}", appId);
+        logger.info("ApiKey: {}", apiKey);
+        logger.info("SecretKey: {}", secretKey != null ? "已配置" : "未配置");
+        
+        if (appId == null || appId.trim().isEmpty() ||
+            apiKey == null || apiKey.trim().isEmpty() ||
+            secretKey == null || secretKey.trim().isEmpty()) {
+            logger.error("百度AI配置信息不完整,请检查配置!");
+            throw new IllegalStateException("百度AI配置信息不完整");
+        }
+
+        // 初始化对象
+        AipSpeech client = new AipSpeech(appId, apiKey, secretKey);
+        
+        // 设置网络连接参数
+        client.setConnectionTimeoutInMillis(5000);
+        client.setSocketTimeoutInMillis(60000);
+
+        try {
+            // 测试语音合成接口
+            logger.info("正在测试语音合成接口...");
+            TtsResponse synthResult = client.synthesis("测试", "zh", 1, new HashMap<>());
+            
+            // 检查响应中是否包含错误信息
+            if (synthResult.getData() == null) {
+                logger.error("语音合成测试失败");
+                logger.error("请检查密钥是否正确,以及服务是否已开通");
+            } else {
+                logger.info("语音合成测试成功!");
+            }
+
+            logger.info("百度AI客户端初始化成功!");
+            logger.info("================================");
+            
+        } catch (Exception e) {
+            logger.error("百度AI客户端初始化失败", e);
+            logger.error("请检查以下几点:");
+            logger.error("1. API密钥是否正确");
+            logger.error("2. 是否已开通语音技术服务");
+            logger.error("3. 应用是否已上线");
+            logger.error("4. 服务是否在有效期内");
+            throw new IllegalStateException("百度AI客户端初始化失败", e);
+        }
+        return client;
+    }
+}

+ 0 - 2
Marketplace/src/main/java/com/dt/oss/controller/OSSController.java

@@ -31,6 +31,4 @@ public class OSSController {
             return "上传失败: ";
             return "上传失败: ";
         }
         }
     }
     }
-
-
 }
 }

+ 25 - 0
Marketplace/src/main/java/com/dt/user/controller/UserController.java

@@ -4,6 +4,7 @@ import com.dt.config.NonLoginRequired;
 import com.dt.user.dto.UserLoginDTO;
 import com.dt.user.dto.UserLoginDTO;
 import com.dt.user.dto.UserRegisterDTO;
 import com.dt.user.dto.UserRegisterDTO;
 import com.dt.user.dto.FaceLoginEnableDTO;
 import com.dt.user.dto.FaceLoginEnableDTO;
+import com.dt.user.dto.UserUpdateDTO;
 import com.dt.user.service.UserService;
 import com.dt.user.service.UserService;
 import com.dt.user.vo.UserLoginVO;
 import com.dt.user.vo.UserLoginVO;
 import com.dt.util.Result;
 import com.dt.util.Result;
@@ -69,4 +70,28 @@ public class UserController {
     public Result uploadFaceImage(@RequestParam("faceImage") MultipartFile faceImage) {
     public Result uploadFaceImage(@RequestParam("faceImage") MultipartFile faceImage) {
         return userService.uploadFaceImage(faceImage, request);
         return userService.uploadFaceImage(faceImage, request);
     }
     }
+    /**
+     * 获取用户个人信息
+     */
+    @GetMapping("getUserInfo")
+    public Result getUserInfo() {
+        return userService.getUserInfo(request);
+    }
+    /**
+     * 修改个人用户信息
+     */
+    @PostMapping("/updateUserInfo")
+    public Result updateUserInfo(@Validated @RequestBody UserUpdateDTO updateDTO) {
+        return userService.updateUser(updateDTO, request);
+    }
+
+    /**
+     * 用户签到
+     * @param
+     * @return
+     */
+    @PostMapping("/signIn")
+    public Result signIn() {
+        return userService.signIn(request);
+    }
 }
 }

+ 20 - 0
Marketplace/src/main/java/com/dt/user/dto/UserUpdateDTO.java

@@ -0,0 +1,20 @@
+package com.dt.user.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+@Data
+public class UserUpdateDTO {
+    private Integer gender; // 0-未知, 1-男, 2-女
+
+    @Size(max = 50, message = "真实姓名长度不能超过50个字符")
+    private String realName;
+
+    @Size(max = 20, message = "手机号长度不能超过20个字符")
+    private String phone;
+
+    @Size(max = 50, message = "邮箱长度不能超过50个字符")
+    private String email;
+} 

+ 3 - 100
Marketplace/src/main/java/com/dt/user/pojo/User.java

@@ -111,7 +111,6 @@ public class User implements Serializable {
      */
      */
     private Integer deleted;
     private Integer deleted;
 
 
-
     /**
     /**
      * 上次签到时间
      * 上次签到时间
      */
      */
@@ -131,6 +130,8 @@ public class User implements Serializable {
      * 豆豆数量
      * 豆豆数量
      */
      */
     private Integer beans;
     private Integer beans;
+
+
     @TableField(exist = false)
     @TableField(exist = false)
     private String bio;
     private String bio;
     @TableField(exist = false)
     @TableField(exist = false)
@@ -147,102 +148,4 @@ public class User implements Serializable {
     private String avatares;
     private String avatares;
     @TableField(exist = false)
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
-
-
-//    @Override
-//    public boolean equals(Object that) {
-//        if (this == that) {
-//            return true;
-//        }
-//        if (that == null) {
-//            return false;
-//        }
-//        if (getClass() != that.getClass()) {
-//            return false;
-//        }
-//        com.dt.user other = (com.dt.common.domain.User) that;
-//        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
-//                && (this.getUsername() == null ? other.getUsername() == null : this.getUsername().equals(other.getUsername()))
-//                && (this.getPassword() == null ? other.getPassword() == null : this.getPassword().equals(other.getPassword()))
-//                && (this.getRealName() == null ? other.getRealName() == null : this.getRealName().equals(other.getRealName()))
-//                && (this.getPhone() == null ? other.getPhone() == null : this.getPhone().equals(other.getPhone()))
-//                && (this.getEmail() == null ? other.getEmail() == null : this.getEmail().equals(other.getEmail()))
-//                && (this.getAvatar() == null ? other.getAvatar() == null : this.getAvatar().equals(other.getAvatar()))
-//                && (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
-//                && (this.getBirthDate() == null ? other.getBirthDate() == null : this.getBirthDate().equals(other.getBirthDate()))
-//                && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
-//                && (this.getLastLoginTime() == null ? other.getLastLoginTime() == null : this.getLastLoginTime().equals(other.getLastLoginTime()))
-//                && (this.getLastLoginIp() == null ? other.getLastLoginIp() == null : this.getLastLoginIp().equals(other.getLastLoginIp()))
-//                && (this.getLastLoginDevice() == null ? other.getLastLoginDevice() == null : this.getLastLoginDevice().equals(other.getLastLoginDevice()))
-//                && (this.getFaceImageUrl() == null ? other.getFaceImageUrl() == null : this.getFaceImageUrl().equals(other.getFaceImageUrl()))
-//                && (this.getFaceLoginEnabled() == null ? other.getFaceLoginEnabled() == null : this.getFaceLoginEnabled().equals(other.getFaceLoginEnabled()))
-//                && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt()))
-//                && (this.getUpdatedAt() == null ? other.getUpdatedAt() == null : this.getUpdatedAt().equals(other.getUpdatedAt()))
-//                && (this.getDeleted() == null ? other.getDeleted() == null : this.getDeleted().equals(other.getDeleted()))
-//                && (this.getLastSignInTime() == null ? other.getLastSignInTime() == null : this.getLastSignInTime().equals(other.getLastSignInTime()))
-//                && (this.getContinuousSignInDays() == null ? other.getContinuousSignInDays() == null : this.getContinuousSignInDays().equals(other.getContinuousSignInDays()))
-//                && (this.getTotalSignInDays() == null ? other.getTotalSignInDays() == null : this.getTotalSignInDays().equals(other.getTotalSignInDays()))
-//                && (this.getBeans() == null ? other.getBeans() == null : this.getBeans().equals(other.getBeans()));
-//    }
-//
-//    @Override
-//    public int hashCode() {
-//        final int prime = 31;
-//        int result = 1;
-//        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
-//        result = prime * result + ((getUsername() == null) ? 0 : getUsername().hashCode());
-//        result = prime * result + ((getPassword() == null) ? 0 : getPassword().hashCode());
-//        result = prime * result + ((getRealName() == null) ? 0 : getRealName().hashCode());
-//        result = prime * result + ((getPhone() == null) ? 0 : getPhone().hashCode());
-//        result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode());
-//        result = prime * result + ((getAvatar() == null) ? 0 : getAvatar().hashCode());
-//        result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
-//        result = prime * result + ((getBirthDate() == null) ? 0 : getBirthDate().hashCode());
-//        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
-//        result = prime * result + ((getLastLoginTime() == null) ? 0 : getLastLoginTime().hashCode());
-//        result = prime * result + ((getLastLoginIp() == null) ? 0 : getLastLoginIp().hashCode());
-//        result = prime * result + ((getLastLoginDevice() == null) ? 0 : getLastLoginDevice().hashCode());
-//        result = prime * result + ((getFaceImageUrl() == null) ? 0 : getFaceImageUrl().hashCode());
-//        result = prime * result + ((getFaceLoginEnabled() == null) ? 0 : getFaceLoginEnabled().hashCode());
-//        result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode());
-//        result = prime * result + ((getUpdatedAt() == null) ? 0 : getUpdatedAt().hashCode());
-//        result = prime * result + ((getDeleted() == null) ? 0 : getDeleted().hashCode());
-//        result = prime * result + ((getLastSignInTime() == null) ? 0 : getLastSignInTime().hashCode());
-//        result = prime * result + ((getContinuousSignInDays() == null) ? 0 : getContinuousSignInDays().hashCode());
-//        result = prime * result + ((getTotalSignInDays() == null) ? 0 : getTotalSignInDays().hashCode());
-//        result = prime * result + ((getBeans() == null) ? 0 : getBeans().hashCode());
-//        return result;
-//    }
-//
-//    @Override
-//    public String toString() {
-//        StringBuilder sb = new StringBuilder();
-//        sb.append(getClass().getSimpleName());
-//        sb.append(" [");
-//        sb.append("Hash = ").append(hashCode());
-//        sb.append(", id=").append(id);
-//        sb.append(", username=").append(username);
-//        sb.append(", password=").append(password);
-//        sb.append(", realName=").append(realName);
-//        sb.append(", phone=").append(phone);
-//        sb.append(", email=").append(email);
-//        sb.append(", avatar=").append(avatar);
-//        sb.append(", gender=").append(gender);
-//        sb.append(", birthDate=").append(birthDate);
-//        sb.append(", status=").append(status);
-//        sb.append(", lastLoginTime=").append(lastLoginTime);
-//        sb.append(", lastLoginIp=").append(lastLoginIp);
-//        sb.append(", lastLoginDevice=").append(lastLoginDevice);
-//        sb.append(", faceImageUrl=").append(faceImageUrl);
-//        sb.append(", faceLoginEnabled=").append(faceLoginEnabled);
-//        sb.append(", createdAt=").append(createdAt);
-//        sb.append(", updatedAt=").append(updatedAt);
-//        sb.append(", deleted=").append(deleted);
-//        sb.append(", lastSignInTime=").append(lastSignInTime);
-//        sb.append(", continuousSignInDays=").append(continuousSignInDays);
-//        sb.append(", totalSignInDays=").append(totalSignInDays);
-//        sb.append(", beans=").append(beans);
-//        sb.append("]");
-//        return sb.toString();
-//    }
-}
+}

+ 16 - 0
Marketplace/src/main/java/com/dt/user/service/UserService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.dt.user.dto.UserLoginDTO;
 import com.dt.user.dto.UserLoginDTO;
 import com.dt.user.dto.UserRegisterDTO;
 import com.dt.user.dto.UserRegisterDTO;
 import com.dt.user.dto.FaceLoginEnableDTO;
 import com.dt.user.dto.FaceLoginEnableDTO;
+import com.dt.user.dto.UserUpdateDTO;
 import com.dt.user.vo.UserLoginVO;
 import com.dt.user.vo.UserLoginVO;
 import com.dt.util.Result;
 import com.dt.util.Result;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartFile;
@@ -51,4 +52,19 @@ public interface UserService extends IService<User> {
      * @return 操作结果
      * @return 操作结果
      */
      */
     Result uploadFaceImage(MultipartFile faceImage, HttpServletRequest request);
     Result uploadFaceImage(MultipartFile faceImage, HttpServletRequest request);
+    /**
+     * 获取用户信息
+     * @param request
+     * @return
+     */
+    Result getUserInfo(HttpServletRequest request);
+
+    Result updateUser(UserUpdateDTO userUpdateDTO, HttpServletRequest request);
+
+    /**
+     * 用户签到
+     * @param request
+     * @return
+     */
+    Result signIn(HttpServletRequest request);
 }
 }

+ 125 - 3
Marketplace/src/main/java/com/dt/user/service/impl/UserServiceImpl.java

@@ -7,6 +7,7 @@ import com.dt.oss.OSSService;
 import com.dt.user.dto.UserLoginDTO;
 import com.dt.user.dto.UserLoginDTO;
 import com.dt.user.dto.UserRegisterDTO;
 import com.dt.user.dto.UserRegisterDTO;
 import com.dt.user.dto.FaceLoginEnableDTO;
 import com.dt.user.dto.FaceLoginEnableDTO;
+import com.dt.user.dto.UserUpdateDTO;
 import com.dt.user.mapper.UserMapper;
 import com.dt.user.mapper.UserMapper;
 import com.dt.user.pojo.User;
 import com.dt.user.pojo.User;
 import com.dt.user.service.UserService;
 import com.dt.user.service.UserService;
@@ -25,6 +26,8 @@ import javax.servlet.http.HttpServletRequest;
 import java.util.Date;
 import java.util.Date;
 import java.util.List;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
+import java.time.LocalDate;
+import java.time.ZoneId;
 
 
 /**
 /**
 * @author 张大宇
 * @author 张大宇
@@ -96,10 +99,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
         // 3. 设置默认值
         // 3. 设置默认值
         user.setStatus(1); // 正常状态
         user.setStatus(1); // 正常状态
         user.setGender(0); // 性别未知
         user.setGender(0); // 性别未知
+        user.setRealName(registerDTO.getUsername());
         user.setCreatedAt(new Date());
         user.setCreatedAt(new Date());
         user.setUpdatedAt(new Date());
         user.setUpdatedAt(new Date());
-        user.setDeleted(0); // 未删除
-
         // 4. 保存用户
         // 4. 保存用户
         this.save(user);
         this.save(user);
     }
     }
@@ -138,7 +140,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
     }
     }
 
 
     @Override
     @Override
-    public Result uploadFaceImage(MultipartFile faceImage, HttpServletRequest request) {
+    public Result   uploadFaceImage(MultipartFile faceImage, HttpServletRequest request) {
         try {
         try {
             // 获取当前登录用户ID
             // 获取当前登录用户ID
             String token = request.getHeader("token");
             String token = request.getHeader("token");
@@ -166,6 +168,20 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
     }
     }
 
 
     @Override
     @Override
+    public Result getUserInfo(HttpServletRequest request) {
+        String token = request.getHeader("token");
+        Long userId = TokenUtils.getUserId(token);
+        if (userId == null){
+            return new Result(false, "用户未登录");
+        }
+        User user = this.getById(userId);
+        if (user == null){
+            return new Result(false, "用户不存在");
+        }
+        return new Result(true, "获取用户信息成功", user);
+    }
+
+    @Override
     public Result faceLogin(MultipartFile imageUrl2) {
     public Result faceLogin(MultipartFile imageUrl2) {
         try {
         try {
             // 查询所有启用了人脸登录的用户
             // 查询所有启用了人脸登录的用户
@@ -216,6 +232,112 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
             return new Result(false, "人脸识别失败:" + e.getMessage());
             return new Result(false, "人脸识别失败:" + e.getMessage());
         }
         }
     }
     }
+
+    @Override
+    public Result updateUser(UserUpdateDTO userUpdateDTO, HttpServletRequest request) {
+        try {
+            String token = request.getHeader("token");
+            Long userId = TokenUtils.getUserId(token);
+            if (userId == null) {
+                return new Result(false, "用户未登录");
+            }
+
+            User user = this.getById(userId);
+            if (user == null) {
+                return new Result(false, "用户不存在");
+            }
+
+            // 更新用户信息
+            if (userUpdateDTO.getGender() != null) {
+                user.setGender(userUpdateDTO.getGender());
+            }
+            if (userUpdateDTO.getRealName() != null && !userUpdateDTO.getRealName().isEmpty()) {
+                user.setRealName(userUpdateDTO.getRealName());
+            }
+            if (userUpdateDTO.getPhone() != null && !userUpdateDTO.getPhone().isEmpty()) {
+                user.setPhone(userUpdateDTO.getPhone());
+            }
+            if (userUpdateDTO.getEmail() != null && !userUpdateDTO.getEmail().isEmpty()) {
+                user.setEmail(userUpdateDTO.getEmail());
+            }
+
+            user.setUpdatedAt(new Date());
+            this.updateById(user);
+            return new Result(true, "用户信息更新成功");
+
+        } catch (ApiException e) {
+            return new Result(false, e.getMessage());
+        } catch (Exception e) {
+            e.printStackTrace();
+            return new Result(false, "更新用户信息失败:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public Result signIn(HttpServletRequest request) {
+        try {
+            String token = request.getHeader("token");
+            Long userId = TokenUtils.getUserId(token);
+            if (userId == null) {
+                return new Result(false, "用户未登录");
+            }
+
+            User user = this.getById(userId);
+            if (user == null) {
+                return new Result(false, "用户不存在");
+            }
+
+            LocalDate today = LocalDate.now();
+            LocalDate lastSignInDate = null;
+            if (user.getLastSignInTime() != null) {
+                lastSignInDate = user.getLastSignInTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+            }
+
+            if (lastSignInDate != null && lastSignInDate.isEqual(today)) {
+                return new Result(false, "您今天已经签到过了");
+            }
+
+            // 初始化签到数据 (如果为null)
+            if (user.getContinuousSignInDays() == null) {
+                user.setContinuousSignInDays(0);
+            }
+            if (user.getTotalSignInDays() == null) {
+                user.setTotalSignInDays(0);
+            }
+            if (user.getBeans() == null) {
+                user.setBeans(0);
+            }
+
+            // 更新连续签到天数
+            if (lastSignInDate != null && lastSignInDate.isEqual(today.minusDays(1))) {
+                user.setContinuousSignInDays(user.getContinuousSignInDays() + 1);
+            } else {
+                user.setContinuousSignInDays(1);
+            }
+
+            // 根据连续签到天数计算本次获得的豆豆数量
+            int gainedBeans;
+            int continuousDays = user.getContinuousSignInDays();
+            if (continuousDays >= 7) {
+                gainedBeans = 70;
+            } else {
+                gainedBeans = continuousDays * 10;
+            }
+
+            // 更新累计签到天数和豆豆
+            user.setTotalSignInDays(user.getTotalSignInDays() + 1);
+            user.setLastSignInTime(new Date());
+            user.setBeans(user.getBeans() + gainedBeans);
+
+            this.updateById(user);
+
+            return new Result(true, "签到成功!获得" + gainedBeans + "豆豆,您已连续签到 " + user.getContinuousSignInDays() + " 天,累计签到 " + user.getTotalSignInDays() + " 天。");
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return new Result(false, "签到失败:" + e.getMessage());
+        }
+    }
 }
 }
 
 
 
 

+ 27 - 1
Marketplace/src/main/resources/application.yml

@@ -18,6 +18,7 @@ spring:
   redis:
   redis:
     host: 101.200.59.170
     host: 101.200.59.170
     port: 6379
     port: 6379
+    password: yrhl666
     database: 0
     database: 0
     template:
     template:
       default-type: java.lang.String
       default-type: java.lang.String
@@ -41,7 +42,32 @@ logging:
   level:
   level:
     cn:
     cn:
       zhentao: debug
       zhentao: debug
-
+baidu:
+  ai:
+    # 请替换为您在百度AI平台新建应用后获取的密钥信息
+    appId: 119456819  # 示例:12345678
+    apiKey: NlOEw3RS4nSGhxsb4ojWmZVr  # 在应用详情页面获取
+    secretKey: EVMXrVlJoUEfVkqfk1F69zKqB9VRalUk  # 在应用详情页面获取
+  asr:  # 语音识别参数
+    lang: zh
+    format: wav
+    rate: 16000
+  tts:  # 语音合成参数
+    lang: zh  # 语言,使用zh而不是zh-CN
+    per: 4    # 发音人:0-女声,1-男声,3-情感男声,4-情感女声
+    spd: 5    # 语速,取值0-15,默认为5中语速
+    pit: 5    # 音调,取值0-15,默认为5中语调
+    vol: 5    # 音量,取值0-15,默认为5中音量
+  wenxin:  # 文心一言参数
+    api-key: "bce-v3/ALTAK-TUpAcVUc23264iv606UkH/feac26b64b72c99e3548f304bfe59067b9c9d47a"  # 您的文心一言API密钥
+audio:
+  record:
+    path: audio/record  # 录音文件保存目录
+  synthesis:
+    path: audio/synthesis  # 合成语音保存目录
+  web:
+    resources:
+      static-locations: classpath:/static/, file:${audio.synthesis.path}/
 
 
 
 
 
 

+ 0 - 13
Marketplace/src/test/java/com/dt/MarketplaceApplicationTests.java

@@ -1,13 +0,0 @@
-package com.dt;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-@SpringBootTest
-class MarketplaceApplicationTests {
-
-    @Test
-    void contextLoads() {
-    }
-
-}

+ 0 - 45
Marketplace/src/test/java/com/dt/util/FaceEngineUtilTest.java

@@ -1,45 +0,0 @@
-package com.dt.util;
-
-import com.arcsoft.face.EngineConfiguration;
-import com.arcsoft.face.FaceEngine;
-import com.arcsoft.face.enums.DetectMode;
-import com.arcsoft.face.enums.DetectOrient;
-import com.arcsoft.face.enums.ErrorInfo;
-import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.io.File;
-
-public class FaceEngineUtilTest {
-
-    @Test
-    public void testFaceEngineInitialization() {
-        String projectRoot = new File("").getAbsolutePath();
-        String enginePath = new File(projectRoot, "libs/WIN64").getAbsolutePath();
-        
-        System.out.println("Engine path: " + enginePath);
-        System.out.println("Files in directory:");
-        File dir = new File(enginePath);
-        if (dir.exists() && dir.isDirectory()) {
-            for (File file : dir.listFiles()) {
-                System.out.println(" - " + file.getName() + " (exists: " + file.exists() + ", readable: " + file.canRead() + ")");
-            }
-        }
-
-        FaceEngine faceEngine = new FaceEngine(enginePath);
-        
-        // Try to initialize the engine
-        EngineConfiguration engineConfiguration = new EngineConfiguration();
-        engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
-        engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
-        engineConfiguration.setDetectFaceMaxNum(10);
-        engineConfiguration.setDetectFaceScaleVal(16);
-        
-        int errorCode = faceEngine.init(engineConfiguration);
-        assertEquals(ErrorInfo.MOK.getValue(), errorCode, "Face engine initialization failed");
-        
-        // Clean up
-        errorCode = faceEngine.unInit();
-        assertEquals(ErrorInfo.MOK.getValue(), errorCode, "Face engine uninitialization failed");
-    }
-}