diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e048019 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,33 @@ +# Repository Guidelines + +## Project Structure & Module Organization +- Entrypoint `src/main/java/com/yolo/keyborad/MyApplication.java`; feature code organized by layer: `controller` (REST), `service` (business), `mapper` (MyBatis mappers), `model`/`common`/`constant` for DTOs, responses, and constants, plus `config`, `aop`, `annotation`, `Interceptor`, and `utils` for cross-cutting concerns. +- Resource configs live in `src/main/resources`: `application.yml` with `application-dev.yml`/`application-prod.yml` profiles, mapper XML files under `mapper/`, and platform keys/certs (Apple, mail, storage). Keep secrets out of commits. +- Tests belong in `src/test/java/com/yolo/keyborad/...` mirroring package names; add fixtures alongside tests when needed. + +## Build, Test, and Development Commands +- `./mvnw clean install` — full build with tests; requires JDK 17. +- `./mvnw test` — run test suite only. +- `./mvnw spring-boot:run -Dspring-boot.run.profiles=dev` — start the API with the dev profile (loads `application-dev.yml`). +- `./mvnw clean package -DskipTests` — create an artifact when tests are already covered elsewhere. + +## Coding Style & Naming Conventions +- Java 17, Spring Boot 3.5, MyBatis/MyBatis-Plus; prefer Lombok for boilerplate (`@Data`, `@Builder`) and constructor injection for services. +- Use 4-space indentation, lowercase package names, `UpperCamelCase` for classes, `lowerCamelCase` for fields/params. +- Controllers end with `*Controller`, services with `*Service`, mapper interfaces with `*Mapper`, and request/response DTOs under `model` or `common` with clear suffixes like `Request`/`Response`. +- Keep configuration isolated in `config`; shared constants in `constant`; AOP/logging in `aop`; custom annotations in `annotation`. + +## Testing Guidelines +- Use Spring Boot Test + JUnit (via `spring-boot-starter-test`, JUnit 4/5 support) and MockMvc/WebTestClient for HTTP layers when practical. +- Name classes `*Test` and align packages with the code under test. Cover service logic, mappers, and controller contracts (status + payload shape). +- For data-access tests, use in-memory setups or dedicated test containers and clean up test data. + +## Commit & Pull Request Guidelines +- Follow the existing conventional style seen in history (e.g., `feat(user): add email registration`); keep scope lowercase and concise. +- PRs should describe the change, list validation steps/commands run, call out config/profile impacts, and link issues/tasks. Add screenshots or sample requests/responses for API-facing changes when helpful. +- Ensure secrets (p8 certificates, Mailgun keys, AWS creds) are never committed; rely on environment variables or local config overrides. + +## Security & Configuration Tips +- Activate the intended profile via `SPRING_PROFILES_ACTIVE` or `-Dspring-boot.run.profiles`. Keep `application-dev.yml` local-only; never hardcode production endpoints or credentials. +- Validate signing/encryption helpers (`SignInterceptor`, JWT, Apple receipt validation) with representative non-production keys before merging. +- Log only necessary context; avoid logging tokens, receipts, or PII. diff --git a/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java b/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java index b2fa793..aa88be3 100644 --- a/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java +++ b/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java @@ -75,7 +75,8 @@ public class SaTokenConfigure implements WebMvcConfigurer { "/character/listByUser", "/user/updateInfo", "/user/detail", - "/user/register" + "/user/register", + "/character/updateUserCharacterSort" }; } @Bean diff --git a/src/main/java/com/yolo/keyborad/controller/CharacterController.java b/src/main/java/com/yolo/keyborad/controller/CharacterController.java index c6835fe..a462840 100644 --- a/src/main/java/com/yolo/keyborad/controller/CharacterController.java +++ b/src/main/java/com/yolo/keyborad/controller/CharacterController.java @@ -4,6 +4,8 @@ import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import com.yolo.keyborad.common.BaseResponse; import com.yolo.keyborad.common.ResultUtils; +import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterDTO; +import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterSortUpdateDTO; import com.yolo.keyborad.model.entity.KeyboardCharacter; import com.yolo.keyborad.model.entity.KeyboardTag; import com.yolo.keyborad.model.entity.KeyboardUserCharacter; @@ -15,10 +17,9 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.ai.chat.model.ChatModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -34,6 +35,8 @@ public class CharacterController { @Resource private KeyboardCharacterService characterService; + @Autowired + private ChatModel chatModel; @GetMapping("/list") @Operation(summary = "人设列表", description = "人设列表接口按 rank 排名") @@ -59,7 +62,15 @@ public class CharacterController { @GetMapping("/listByUser") @Operation(summary = "用户人设列表", description = "用户人设列表接口") public BaseResponse> userList() { - List keyboardCharacters = characterService.selectListByUserId(); - return ResultUtils.success(BeanUtil.copyToList(keyboardCharacters, KeyboardUserCharacterVO.class)); + return ResultUtils.success(characterService.selectListByUserId()); } + + + @PostMapping("/updateUserCharacterSort") + @Operation(summary = "更新用户人设排序",description = "更新用户人设排序接口") + public BaseResponse updateUserCharacterSort(@RequestBody KeyboardUserCharacterSortUpdateDTO sortUpdateDTO) { + characterService.updateSort(sortUpdateDTO); + return ResultUtils.success(true); + } + } diff --git a/src/main/java/com/yolo/keyborad/mapper/KeyboardUserCharacterMapper.java b/src/main/java/com/yolo/keyborad/mapper/KeyboardUserCharacterMapper.java index 2f6d18d..5ffc16a 100644 --- a/src/main/java/com/yolo/keyborad/mapper/KeyboardUserCharacterMapper.java +++ b/src/main/java/com/yolo/keyborad/mapper/KeyboardUserCharacterMapper.java @@ -2,6 +2,10 @@ package com.yolo.keyborad.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.yolo.keyborad.model.entity.KeyboardUserCharacter; +import com.yolo.keyborad.model.vo.character.KeyboardUserCharacterVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; /* * @author: ziin @@ -9,4 +13,9 @@ import com.yolo.keyborad.model.entity.KeyboardUserCharacter; */ public interface KeyboardUserCharacterMapper extends BaseMapper { + + List selectByUserId(@Param("loginId") long loginId); + + void updateSortByIdAndUserId(@Param("sort") Integer[] sort,@Param("userId") long userId); + } \ No newline at end of file diff --git a/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterDTO.java b/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterDTO.java new file mode 100644 index 0000000..1c5f101 --- /dev/null +++ b/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterDTO.java @@ -0,0 +1,28 @@ +package com.yolo.keyborad.model.dto.userCharacter; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/* +* @author: ziin +* @date: 2025/12/3 15:43 +*/ + +@Schema +@Data +public class KeyboardUserCharacterDTO { + @Schema(description="主键 Id") + private Long id; + + @Schema(description="键盘人设 id") + private Long characterId; + + @Schema(description = "用户展示界面排序") + private Long sort; + + @Schema(description="用户 id") + private Long userId; + + @Schema(description = "是否删除") + private Boolean deleted; +} \ No newline at end of file diff --git a/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterSortUpdateDTO.java b/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterSortUpdateDTO.java new file mode 100644 index 0000000..733ef18 --- /dev/null +++ b/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterSortUpdateDTO.java @@ -0,0 +1,15 @@ +package com.yolo.keyborad.model.dto.userCharacter; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(description = "用户键盘顺序更新 DTO") +@Data +public class KeyboardUserCharacterSortUpdateDTO { + + @Schema(description = "用户展示界面排序") + private List sort; + +} diff --git a/src/main/java/com/yolo/keyborad/model/entity/KeyboardUserCharacter.java b/src/main/java/com/yolo/keyborad/model/entity/KeyboardUserCharacter.java index 5e7fba9..2e95728 100644 --- a/src/main/java/com/yolo/keyborad/model/entity/KeyboardUserCharacter.java +++ b/src/main/java/com/yolo/keyborad/model/entity/KeyboardUserCharacter.java @@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import java.util.Date; +import java.util.List; + import lombok.Data; /* @@ -40,4 +42,12 @@ public class KeyboardUserCharacter { @TableField(value = "user_id") @Schema(description="用户 id") private Long userId; + + @TableField(value = "emoji") + @Schema(description = "emoji") + private String emoji; + + @TableField(value = "sort") + @Schema(description = "展示顺序") + private List sort; } \ No newline at end of file diff --git a/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardCharacterRespVO.java b/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardCharacterRespVO.java index 6174e6a..74eaba3 100644 --- a/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardCharacterRespVO.java +++ b/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardCharacterRespVO.java @@ -38,4 +38,5 @@ public class KeyboardCharacterRespVO { @Schema(description="排名顺序") private Integer rank; + } \ No newline at end of file diff --git a/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardUserCharacterVO.java b/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardUserCharacterVO.java index e9cb0bd..aa8db8c 100644 --- a/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardUserCharacterVO.java +++ b/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardUserCharacterVO.java @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.Date; +import java.util.List; /* * @author: ziin @@ -25,4 +26,6 @@ public class KeyboardUserCharacterVO { @Schema(description = "人设名") private String characterName; + @Schema(description = "emoji") + private String emoji; } \ No newline at end of file diff --git a/src/main/java/com/yolo/keyborad/service/KeyboardCharacterService.java b/src/main/java/com/yolo/keyborad/service/KeyboardCharacterService.java index 2f93337..61efc9f 100644 --- a/src/main/java/com/yolo/keyborad/service/KeyboardCharacterService.java +++ b/src/main/java/com/yolo/keyborad/service/KeyboardCharacterService.java @@ -1,9 +1,11 @@ package com.yolo.keyborad.service; +import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterSortUpdateDTO; import com.yolo.keyborad.model.entity.KeyboardCharacter; import com.baomidou.mybatisplus.extension.service.IService; import com.yolo.keyborad.model.entity.KeyboardTag; import com.yolo.keyborad.model.entity.KeyboardUserCharacter; +import com.yolo.keyborad.model.vo.character.KeyboardUserCharacterVO; import java.util.List; /* @@ -18,6 +20,7 @@ public interface KeyboardCharacterService extends IService{ List selectListByTag(Long tagId); - List selectListByUserId(); + List selectListByUserId(); + void updateSort(KeyboardUserCharacterSortUpdateDTO sortUpdateDTO); } diff --git a/src/main/java/com/yolo/keyborad/service/impl/KeyboardCharacterServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/KeyboardCharacterServiceImpl.java index 07d79fa..b067fbb 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/KeyboardCharacterServiceImpl.java +++ b/src/main/java/com/yolo/keyborad/service/impl/KeyboardCharacterServiceImpl.java @@ -6,13 +6,17 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.yolo.keyborad.mapper.KeyboardCharacterMapper; import com.yolo.keyborad.mapper.KeyboardUserCharacterMapper; +import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterSortUpdateDTO; import com.yolo.keyborad.model.entity.KeyboardUserCharacter; +import com.yolo.keyborad.model.vo.character.KeyboardUserCharacterVO; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yolo.keyborad.model.entity.KeyboardCharacter; import com.yolo.keyborad.service.KeyboardCharacterService; +import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; /* * @author: ziin @@ -44,23 +48,20 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl selectListByUserId() { + public List selectListByUserId() { long loginId = StpUtil.getLoginIdAsLong(); - List keyboardUserCharacters = keyboardUserCharacterMapper.selectList(new LambdaQueryWrapper() - .eq(KeyboardUserCharacter::getDeleted, false) - .eq(KeyboardUserCharacter::getUserId, loginId)); + return keyboardUserCharacterMapper.selectByUserId(loginId); + } - List characterIds = keyboardUserCharacters.stream() - .map(KeyboardUserCharacter::getCharacterId) - .toList(); - if (CollectionUtils.isEmpty(characterIds)) { - return null; + @Override + @Transactional + public void updateSort(KeyboardUserCharacterSortUpdateDTO sortUpdateDTO) { + if (sortUpdateDTO.getSort() == null || sortUpdateDTO.getSort().isEmpty()) { + return; } - - return keyboardCharacterMapper.selectList(new LambdaQueryWrapper() - .eq(KeyboardCharacter::getDeleted, false) - .in(KeyboardCharacter::getId, characterIds)); - + Integer[] sortArray = sortUpdateDTO.getSort().toArray(new Integer[0]); + long loginIdAsLong = StpUtil.getLoginIdAsLong(); + keyboardUserCharacterMapper.updateSortByIdAndUserId(sortArray, loginIdAsLong); } } diff --git a/src/main/resources/mapper/KeyboardUserCharacterMapper.xml b/src/main/resources/mapper/KeyboardUserCharacterMapper.xml index c57e9d0..d2dd47a 100644 --- a/src/main/resources/mapper/KeyboardUserCharacterMapper.xml +++ b/src/main/resources/mapper/KeyboardUserCharacterMapper.xml @@ -1,16 +1,40 @@ - - - - - - - - - - - id, character_id, deleted, created_at, updated_at, user_id - + + + + + + + + + + + + + + + UPDATE keyboard_user_character + SET sort = #{sort,jdbcType=ARRAY} + where user_id = #{userId} + AND deleted = FALSE + + + + \ No newline at end of file