Initial commit
This commit is contained in:
8
backend/.idea/.gitignore
generated
vendored
Normal file
8
backend/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
19
backend/.idea/compiler.xml
generated
Normal file
19
backend/.idea/compiler.xml
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="true" />
|
||||
<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="naming" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
<component name="JavacSettings">
|
||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||
<module name="naming" options="-parameters" />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
6
backend/.idea/encodings.xml
generated
Normal file
6
backend/.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
20
backend/.idea/jarRepositories.xml
generated
Normal file
20
backend/.idea/jarRepositories.xml
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/central" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
12
backend/.idea/misc.xml
generated
Normal file
12
backend/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
10
backend/.idea/runConfigurations.xml
generated
Normal file
10
backend/.idea/runConfigurations.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
67
backend/pom.xml
Normal file
67
backend/pom.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.7.18</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<groupId>com.jiansu</groupId>
|
||||
<artifactId>naming</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>jiansu-naming</name>
|
||||
<description>JianSu Naming AI Backend</description>
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.83</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.belerweb</groupId>
|
||||
<artifactId>pinyin4j</artifactId>
|
||||
<version>2.5.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.jiansu.naming;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class NamingApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(NamingApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.jiansu.naming.controller;
|
||||
|
||||
import com.jiansu.naming.model.NameCard;
|
||||
import com.jiansu.naming.service.MiniMaxService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/names")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class NamingController {
|
||||
|
||||
@Autowired
|
||||
private MiniMaxService miniMaxService;
|
||||
|
||||
@GetMapping("/generate")
|
||||
public List<NameCard> generate(@RequestParam(defaultValue = "清冷") String keyword) {
|
||||
return miniMaxService.generateNames(keyword);
|
||||
}
|
||||
}
|
||||
18
backend/src/main/java/com/jiansu/naming/model/NameCard.java
Normal file
18
backend/src/main/java/com/jiansu/naming/model/NameCard.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.jiansu.naming.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NameCard {
|
||||
private String name; // 名字
|
||||
private String origin; // 出处/诗句
|
||||
private String description; // “通感”叙事描述
|
||||
private Double score; // 声韵评分(后端计算)
|
||||
private String tone; // 平仄分析 (如:平仄)
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package com.jiansu.naming.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jiansu.naming.model.NameCard;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.*;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MiniMaxService {
|
||||
|
||||
@Value("${minimax.api-key}")
|
||||
private String apiKey;
|
||||
|
||||
@Value("${minimax.api-url}")
|
||||
private String apiUrl;
|
||||
|
||||
private final ToneAnalysisService toneAnalysisService;
|
||||
|
||||
public MiniMaxService(ToneAnalysisService toneAnalysisService) {
|
||||
this.toneAnalysisService = toneAnalysisService;
|
||||
}
|
||||
|
||||
private final OkHttpClient client = new OkHttpClient.Builder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.writeTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(60, TimeUnit.SECONDS)
|
||||
.build();
|
||||
|
||||
private static final String SYSTEM_PROMPT =
|
||||
"你是「见素」的灵魂导师。当用户输入期待或关键词时,请从《诗经》、《楚辞》或宋词中提取意象,生成3个极具美感的名字。" +
|
||||
"每个名字必须配有一段 50 字以内的'通感'描述,包含气味、光线或声音的描写,拒绝说教。" +
|
||||
"请直接以 JSON 数组格式返回,JSON 对象包含三个字段:name (名字), origin (诗词出处), description (通感描述)。不要包含任何 Markdown 格式。";
|
||||
|
||||
public List<NameCard> generateNames(String keyword) {
|
||||
// 后门:当关键词为 "test" 时,返回固定的测试数据
|
||||
if ("test".equalsIgnoreCase(keyword)) {
|
||||
log.info("Keyword is 'test', returning hardcoded test data.");
|
||||
return createTestData();
|
||||
}
|
||||
|
||||
// 构建 MiniMax Token Plan (OpenAI 兼容) 请求体
|
||||
JSONObject jsonBody = new JSONObject();
|
||||
jsonBody.put("model", "MiniMax-M2.7");
|
||||
|
||||
JSONArray messages = new JSONArray();
|
||||
|
||||
JSONObject systemMsg = new JSONObject();
|
||||
systemMsg.put("role", "system");
|
||||
systemMsg.put("content", SYSTEM_PROMPT);
|
||||
messages.add(systemMsg);
|
||||
|
||||
JSONObject userMsg = new JSONObject();
|
||||
userMsg.put("role", "user");
|
||||
userMsg.put("content", "用户期待/关键词是:" + keyword);
|
||||
messages.add(userMsg);
|
||||
|
||||
jsonBody.put("messages", messages);
|
||||
|
||||
RequestBody body = RequestBody.create(
|
||||
jsonBody.toJSONString(),
|
||||
MediaType.parse("application/json; charset=utf-8")
|
||||
);
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(apiUrl)
|
||||
.post(body)
|
||||
.addHeader("Authorization", "Bearer " + apiKey)
|
||||
.addHeader("Content-Type", "application/json")
|
||||
.build();
|
||||
|
||||
try (Response response = client.newCall(request).execute()) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
String responseBody = response.body().string();
|
||||
log.info("MiniMax raw response: {}", responseBody);
|
||||
return parseMiniMaxResponse(responseBody);
|
||||
} else {
|
||||
String errorMsg = response.body() != null ? response.body().string() : response.message();
|
||||
log.error("MiniMax API Error: {} - {}", response.code(), errorMsg);
|
||||
throw new RuntimeException("MiniMax API 调用失败: " + errorMsg);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("API Error: ", e);
|
||||
throw new RuntimeException("网络请求失败");
|
||||
}
|
||||
}
|
||||
|
||||
private List<NameCard> parseMiniMaxResponse(String responseBody) {
|
||||
List<NameCard> nameCards = new ArrayList<>();
|
||||
try {
|
||||
JSONObject root = JSON.parseObject(responseBody);
|
||||
|
||||
// 检查 API 错误
|
||||
JSONObject baseResp = root.getJSONObject("base_resp");
|
||||
if (baseResp != null) {
|
||||
int statusCode = baseResp.getIntValue("status_code");
|
||||
if (statusCode != 0) {
|
||||
String statusMsg = baseResp.getString("status_msg");
|
||||
log.error("MiniMax API error: {} - {}", statusCode, statusMsg);
|
||||
throw new RuntimeException("MiniMax API 错误: " + statusMsg);
|
||||
}
|
||||
}
|
||||
|
||||
JSONArray choices = root.getJSONArray("choices");
|
||||
if (choices == null || choices.isEmpty()) {
|
||||
throw new RuntimeException("MiniMax 返回内容为空");
|
||||
}
|
||||
|
||||
JSONObject firstChoice = choices.getJSONObject(0);
|
||||
JSONObject message = firstChoice.getJSONObject("message");
|
||||
String aiText = message.getString("content");
|
||||
|
||||
if (aiText == null || aiText.isEmpty()) {
|
||||
throw new RuntimeException("MiniMax 返回内容为空");
|
||||
}
|
||||
|
||||
// 清理可能存在的 Markdown 代码块标记
|
||||
aiText = aiText.replaceAll("```json", "").replaceAll("```", "").trim();
|
||||
|
||||
JSONArray jsonArray = JSON.parseArray(aiText);
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JSONObject obj = jsonArray.getJSONObject(i);
|
||||
String name = obj.getString("name");
|
||||
|
||||
// 进行声韵分析
|
||||
ToneAnalysisService.ToneResult tr = toneAnalysisService.analyze(name);
|
||||
|
||||
NameCard card = NameCard.builder()
|
||||
.name(name)
|
||||
.origin(obj.getString("origin"))
|
||||
.description(obj.getString("description"))
|
||||
.score(tr.score)
|
||||
.tone(tr.tonePattern)
|
||||
.build();
|
||||
nameCards.add(card);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("Parse Error: ", e);
|
||||
throw new RuntimeException("数据解析失败");
|
||||
}
|
||||
return nameCards;
|
||||
}
|
||||
|
||||
private List<NameCard> createTestData() {
|
||||
List<NameCard> testData = new ArrayList<>();
|
||||
|
||||
testData.add(NameCard.builder()
|
||||
.name("月白")
|
||||
.origin("《月出》:月出皎兮,佼人僚兮。")
|
||||
.description("像月光洒在雪地,清冷又干净,带着一丝不易察觉的、风吹过竹林的微响。")
|
||||
.score(9.8)
|
||||
.tone("仄仄")
|
||||
.build());
|
||||
|
||||
testData.add(NameCard.builder()
|
||||
.name("南絮")
|
||||
.origin("晏几道《御街行》:街南绿树春饶絮。")
|
||||
.description("春天街巷里柔软的柳絮,随风飘浮,带着南方阳光的暖意和青草的气息。")
|
||||
.score(9.5)
|
||||
.tone("平仄")
|
||||
.build());
|
||||
|
||||
testData.add(NameCard.builder()
|
||||
.name("疏影")
|
||||
.origin("林逋《山园小梅》:疏影横斜水清浅,暗香浮动月黄昏。")
|
||||
.description("黄昏月下,梅枝稀疏的影子落在清浅的水面,空气中浮动着若有似无的冷香。")
|
||||
.score(9.7)
|
||||
.tone("平仄")
|
||||
.build());
|
||||
|
||||
return testData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.jiansu.naming.service;
|
||||
|
||||
import net.sourceforge.pinyin4j.PinyinHelper;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 见素声韵分析逻辑
|
||||
* 1. 平仄匹配:1,2声为平,3,4声为仄
|
||||
* 2. 优选模式:平仄平、仄平仄、平平仄、仄仄平
|
||||
* 3. 连读检查:避免连续闭口音
|
||||
*/
|
||||
@Service
|
||||
public class ToneAnalysisService {
|
||||
|
||||
private final HanyuPinyinOutputFormat format;
|
||||
|
||||
public ToneAnalysisService() {
|
||||
format = new HanyuPinyinOutputFormat();
|
||||
format.setToneType(HanyuPinyinToneType.WITH_TONE_NUMBER);
|
||||
}
|
||||
|
||||
public static class ToneResult {
|
||||
public double score;
|
||||
public String tonePattern;
|
||||
public String msg;
|
||||
}
|
||||
|
||||
public ToneResult analyze(String name) {
|
||||
ToneResult result = new ToneResult();
|
||||
if (name == null || name.isEmpty()) {
|
||||
result.score = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
List<Integer> tones = new ArrayList<>();
|
||||
List<String> pinyins = new ArrayList<>();
|
||||
|
||||
for (char c : name.toCharArray()) {
|
||||
try {
|
||||
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, format);
|
||||
if (pinyinArray != null && pinyinArray.length > 0) {
|
||||
String p = pinyinArray[0];
|
||||
pinyins.add(p);
|
||||
// 取最后一位数字作为声调
|
||||
int tone = Character.getNumericValue(p.charAt(p.length() - 1));
|
||||
tones.add(tone);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略无法识别的字符
|
||||
}
|
||||
}
|
||||
|
||||
// 构建平仄模式
|
||||
StringBuilder pattern = new StringBuilder();
|
||||
for (int tone : tones) {
|
||||
if (tone == 1 || tone == 2) pattern.append("平");
|
||||
else if (tone == 3 || tone == 4) pattern.append("仄");
|
||||
}
|
||||
result.tonePattern = pattern.toString();
|
||||
|
||||
// 基础分 8.0
|
||||
double score = 8.0;
|
||||
|
||||
// 1. 平仄起伏检查
|
||||
if (pattern.length() >= 2) {
|
||||
boolean hasChange = false;
|
||||
for (int i = 0; i < pattern.length() - 1; i++) {
|
||||
if (pattern.charAt(i) != pattern.charAt(i + 1)) {
|
||||
hasChange = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasChange) score += 1.0; // 有起伏感 +1
|
||||
else score -= 0.5; // 全平或全仄 -0.5
|
||||
}
|
||||
|
||||
// 2. 优选模式加分
|
||||
String pStr = pattern.toString();
|
||||
if (pStr.equals("平仄平") || pStr.equals("仄平仄") || pStr.equals("平平仄") || pStr.equals("仄仄平")) {
|
||||
score += 0.5;
|
||||
}
|
||||
|
||||
// 3. 开口度简单检查 (韵母 a, e, o 结尾通常更响亮)
|
||||
int openCount = 0;
|
||||
for (String p : pinyins) {
|
||||
String yumu = p.substring(0, p.length() - 1);
|
||||
if (yumu.endsWith("a") || yumu.endsWith("e") || yumu.endsWith("o") || yumu.endsWith("ang") || yumu.endsWith("ong")) {
|
||||
openCount++;
|
||||
}
|
||||
}
|
||||
if (openCount >= 1) score += 0.3;
|
||||
|
||||
// 限制最高分 9.9
|
||||
result.score = Math.min(score, 9.9);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
11
backend/src/main/resources/application.yml
Normal file
11
backend/src/main/resources/application.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: jiansu-naming
|
||||
|
||||
# MiniMax API 配置
|
||||
minimax:
|
||||
api-key: sk-cp-n0eCZgH5s-NpduAVPo8rpWM9eUBsMOBnIroISIaH6y8eFIpT0VSrCMttzE4bVDbQ-loiMR1b8ZpIsgotQ_yqQRk8_fcUxKHsbhtLfN70oCVaV6-94ZC9Wjk
|
||||
api-url: https://api.minimax.chat/v1/text/chatcompletion_v2
|
||||
11
backend/target/classes/application.yml
Normal file
11
backend/target/classes/application.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: jiansu-naming
|
||||
|
||||
# MiniMax API 配置
|
||||
minimax:
|
||||
api-key: sk-cp-n0eCZgH5s-NpduAVPo8rpWM9eUBsMOBnIroISIaH6y8eFIpT0VSrCMttzE4bVDbQ-loiMR1b8ZpIsgotQ_yqQRk8_fcUxKHsbhtLfN70oCVaV6-94ZC9Wjk
|
||||
api-url: https://api.minimax.chat/v1/text/chatcompletion_v2
|
||||
BIN
backend/target/classes/com/jiansu/naming/NamingApplication.class
Normal file
BIN
backend/target/classes/com/jiansu/naming/NamingApplication.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
backend/target/classes/com/jiansu/naming/model/NameCard.class
Normal file
BIN
backend/target/classes/com/jiansu/naming/model/NameCard.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
com\jiansu\naming\model\NameCard$NameCardBuilder.class
|
||||
com\jiansu\naming\model\NameCard.class
|
||||
com\jiansu\naming\controller\NamingController.class
|
||||
com\jiansu\naming\service\MiniMaxService.class
|
||||
com\jiansu\naming\NamingApplication.class
|
||||
@@ -0,0 +1,4 @@
|
||||
C:\Users\<5C><><EFBFBD><EFBFBD>\Desktop\JianSu-Naming\backend\src\main\java\com\jiansu\naming\controller\NamingController.java
|
||||
C:\Users\<5C><><EFBFBD><EFBFBD>\Desktop\JianSu-Naming\backend\src\main\java\com\jiansu\naming\model\NameCard.java
|
||||
C:\Users\<5C><><EFBFBD><EFBFBD>\Desktop\JianSu-Naming\backend\src\main\java\com\jiansu\naming\service\GeminiService.java
|
||||
C:\Users\<5C><><EFBFBD><EFBFBD>\Desktop\JianSu-Naming\backend\src\main\java\com\jiansu\naming\NamingApplication.java
|
||||
Reference in New Issue
Block a user