修复人设接口国际化查询与未登录访问
This commit is contained in:
BIN
src/main/.DS_Store
vendored
BIN
src/main/.DS_Store
vendored
Binary file not shown.
@@ -87,6 +87,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
|||||||
"/ai-companion/report",
|
"/ai-companion/report",
|
||||||
"/apple/notification",
|
"/apple/notification",
|
||||||
"/appVersions/checkUpdate",
|
"/appVersions/checkUpdate",
|
||||||
|
"/character/detailWithNotLogin"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
@@ -1,30 +1,19 @@
|
|||||||
package com.yolo.keyborad.controller;
|
package com.yolo.keyborad.controller;
|
||||||
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
|
||||||
import com.yolo.keyborad.common.BaseResponse;
|
import com.yolo.keyborad.common.BaseResponse;
|
||||||
import com.yolo.keyborad.common.ErrorCode;
|
|
||||||
import com.yolo.keyborad.common.ResultUtils;
|
import com.yolo.keyborad.common.ResultUtils;
|
||||||
import com.yolo.keyborad.exception.BusinessException;
|
|
||||||
import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterAddDTO;
|
import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterAddDTO;
|
||||||
import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterDTO;
|
|
||||||
import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterSortUpdateDTO;
|
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;
|
|
||||||
import com.yolo.keyborad.model.vo.character.KeyboardCharacterRespVO;
|
import com.yolo.keyborad.model.vo.character.KeyboardCharacterRespVO;
|
||||||
import com.yolo.keyborad.model.vo.character.KeyboardUserCharacterVO;
|
import com.yolo.keyborad.model.vo.character.KeyboardUserCharacterVO;
|
||||||
import com.yolo.keyborad.model.vo.tags.TagsRespVO;
|
|
||||||
import com.yolo.keyborad.service.KeyboardCharacterService;
|
import com.yolo.keyborad.service.KeyboardCharacterService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.ai.chat.model.ChatModel;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -42,26 +31,36 @@ public class CharacterController {
|
|||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "人设列表", description = "人设列表接口按 rank 排名")
|
@Operation(summary = "人设列表", description = "人设列表接口按 rank 排名")
|
||||||
public BaseResponse<List<KeyboardCharacterRespVO>> list() {
|
public BaseResponse<List<KeyboardCharacterRespVO>> list(
|
||||||
return ResultUtils.success(characterService.selectListWithRank());
|
@RequestHeader(value = "Accept-Language", required = false) String acceptLanguage
|
||||||
|
) {
|
||||||
|
return ResultUtils.success(characterService.selectListWithRank(acceptLanguage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/detail")
|
@GetMapping("/detail")
|
||||||
@Operation(summary = "人设详情", description = "人设详情接口")
|
@Operation(summary = "人设详情", description = "人设详情接口")
|
||||||
public BaseResponse<KeyboardCharacterRespVO> detail(@RequestParam("id") Long id) {
|
public BaseResponse<KeyboardCharacterRespVO> detail(
|
||||||
return ResultUtils.success(characterService.getDetailById(id));
|
@RequestParam("id") Long id,
|
||||||
|
@RequestHeader(value = "Accept-Language", required = false) String acceptLanguage
|
||||||
|
) {
|
||||||
|
return ResultUtils.success(characterService.getDetailById(id, acceptLanguage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/listByTag")
|
@GetMapping("/listByTag")
|
||||||
@Operation(summary = "按标签查询人设列表", description = "按标签查询人设列表接口")
|
@Operation(summary = "按标签查询人设列表", description = "按标签查询人设列表接口")
|
||||||
public BaseResponse<List<KeyboardCharacterRespVO>> listByTag(@RequestParam("tagId") Long tagId) {
|
public BaseResponse<List<KeyboardCharacterRespVO>> listByTag(
|
||||||
return ResultUtils.success(characterService.selectListByTag(tagId));
|
@RequestParam("tagId") Long tagId,
|
||||||
|
@RequestHeader(value = "Accept-Language", required = false) String acceptLanguage
|
||||||
|
) {
|
||||||
|
return ResultUtils.success(characterService.selectListByTag(tagId, acceptLanguage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/listByUser")
|
@GetMapping("/listByUser")
|
||||||
@Operation(summary = "用户人设列表", description = "用户人设列表接口")
|
@Operation(summary = "用户人设列表", description = "用户人设列表接口")
|
||||||
public BaseResponse<List<KeyboardUserCharacterVO>> userList() {
|
public BaseResponse<List<KeyboardUserCharacterVO>> userList(
|
||||||
return ResultUtils.success(characterService.selectListByUserId());
|
@RequestHeader(value = "Accept-Language", required = false) String acceptLanguage
|
||||||
|
) {
|
||||||
|
return ResultUtils.success(characterService.selectListByUserId(acceptLanguage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -89,20 +88,27 @@ public class CharacterController {
|
|||||||
|
|
||||||
@GetMapping("/listWithNotLogin")
|
@GetMapping("/listWithNotLogin")
|
||||||
@Operation(summary = "未登录用户人设列表", description = "未登录用户人设列表接口按 rank 排名")
|
@Operation(summary = "未登录用户人设列表", description = "未登录用户人设列表接口按 rank 排名")
|
||||||
public BaseResponse<List<KeyboardCharacterRespVO>> listWithNotLogin() {
|
public BaseResponse<List<KeyboardCharacterRespVO>> listWithNotLogin(
|
||||||
return ResultUtils.success(characterService.selectListWithNotLoginRank());
|
@RequestHeader(value = "Accept-Language", required = false) String acceptLanguage
|
||||||
|
) {
|
||||||
|
return ResultUtils.success(characterService.selectListWithNotLoginRank(acceptLanguage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/detailWithNotLogin")
|
@GetMapping("/detailWithNotLogin")
|
||||||
@Operation(summary = "未登录用户人设详情", description = "未登录用户人设详情接口")
|
@Operation(summary = "未登录用户人设详情", description = "未登录用户人设详情接口")
|
||||||
public BaseResponse<KeyboardCharacterRespVO> detailWithNotLogin(@RequestParam("id") Long id) {
|
public BaseResponse<KeyboardCharacterRespVO> detailWithNotLogin(
|
||||||
KeyboardCharacter character = characterService.getById(id);
|
@RequestParam("id") Long id,
|
||||||
return ResultUtils.success(BeanUtil.copyProperties(character, KeyboardCharacterRespVO.class));
|
@RequestHeader(value = "Accept-Language", required = false) String acceptLanguage
|
||||||
|
) {
|
||||||
|
return ResultUtils.success(characterService.getDetailById(id, acceptLanguage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/listByTagWithNotLogin")
|
@GetMapping("/listByTagWithNotLogin")
|
||||||
@Operation(summary = "未登录用户按标签查询人设列表", description = "未登录用户按标签查询人设列表接口")
|
@Operation(summary = "未登录用户按标签查询人设列表", description = "未登录用户按标签查询人设列表接口")
|
||||||
public BaseResponse<List<KeyboardCharacterRespVO>> listByTagWithNotLogin(@RequestParam("tagId") Long tagId) {
|
public BaseResponse<List<KeyboardCharacterRespVO>> listByTagWithNotLogin(
|
||||||
return ResultUtils.success(characterService.selectListByTagWithNotLogin(tagId));
|
@RequestParam("tagId") Long tagId,
|
||||||
|
@RequestHeader(value = "Accept-Language", required = false) String acceptLanguage
|
||||||
|
) {
|
||||||
|
return ResultUtils.success(characterService.selectListByTagWithNotLogin(tagId, acceptLanguage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class CharacterCacheInitializer implements ApplicationRunner {
|
public class CharacterCacheInitializer implements ApplicationRunner {
|
||||||
|
|
||||||
private static final String CHARACTER_CACHE_KEY = "character:";
|
private static final String CHARACTER_CACHE_KEY_PREFIX = "character:";
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private KeyboardCharacterService characterService;
|
private KeyboardCharacterService characterService;
|
||||||
@@ -34,7 +34,7 @@ public class CharacterCacheInitializer implements ApplicationRunner {
|
|||||||
log.info("开始缓存人设列表到Redis...");
|
log.info("开始缓存人设列表到Redis...");
|
||||||
List<KeyboardCharacter> characters = characterService.list();
|
List<KeyboardCharacter> characters = characterService.list();
|
||||||
for (KeyboardCharacter character : characters) {
|
for (KeyboardCharacter character : characters) {
|
||||||
String key = CHARACTER_CACHE_KEY + character.getId();
|
String key = CHARACTER_CACHE_KEY_PREFIX + character.getId();
|
||||||
redisTemplate.opsForValue().set(key, character, 5, TimeUnit.MINUTES);
|
redisTemplate.opsForValue().set(key, character, 5, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
log.info("人设列表缓存完成,共缓存 {} 条记录", characters.size());
|
log.info("人设列表缓存完成,共缓存 {} 条记录", characters.size());
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.yolo.keyborad.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.yolo.keyborad.model.entity.KeyboardCharacterI18n;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @author: ziin
|
||||||
|
* @date: 2026/4/1 14:13
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface KeyboardCharacterI18nMapper extends BaseMapper<KeyboardCharacterI18n> {
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public interface KeyboardUserCharacterMapper extends BaseMapper<KeyboardUserCharacter> {
|
public interface KeyboardUserCharacterMapper extends BaseMapper<KeyboardUserCharacter> {
|
||||||
|
|
||||||
List<KeyboardUserCharacterVO> selectByUserId(@Param("loginId") long loginId);
|
List<KeyboardUserCharacterVO> selectByUserId(@Param("loginId") long loginId, @Param("locale") String locale);
|
||||||
|
|
||||||
void updateSortByIdAndUserId(@Param("sort") Integer[] sort,@Param("userId") long userId);
|
void updateSortByIdAndUserId(@Param("sort") Integer[] sort,@Param("userId") long userId);
|
||||||
|
|
||||||
|
|||||||
@@ -21,14 +21,6 @@ public class KeyboardCharacter {
|
|||||||
@Schema(description="主键 Id")
|
@Schema(description="主键 Id")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@TableField(value = "character_name")
|
|
||||||
@Schema(description="标题")
|
|
||||||
private String characterName;
|
|
||||||
|
|
||||||
@TableField(value = "\"character_background\"")
|
|
||||||
@Schema(description="背景描述")
|
|
||||||
private String characterBackground;
|
|
||||||
|
|
||||||
@TableField(value = "avatar_url")
|
@TableField(value = "avatar_url")
|
||||||
@Schema(description="角色头像")
|
@Schema(description="角色头像")
|
||||||
private String avatarUrl;
|
private String avatarUrl;
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.yolo.keyborad.model.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
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 lombok.Data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @author: ziin
|
||||||
|
* @date: 2026/4/1 14:13
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 键盘人设国际化内容表
|
||||||
|
*/
|
||||||
|
@Schema(description="键盘人设国际化内容表")
|
||||||
|
@Data
|
||||||
|
@TableName(value = "keyboard_character_i18n")
|
||||||
|
public class KeyboardCharacterI18n {
|
||||||
|
/**
|
||||||
|
* 主键 Id
|
||||||
|
*/
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
@Schema(description="主键 Id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色主表id
|
||||||
|
*/
|
||||||
|
@TableField(value = "character_id")
|
||||||
|
@Schema(description="角色主表id")
|
||||||
|
private Long characterId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 语言标识,如 zh-CN/en-US/ja-JP
|
||||||
|
*/
|
||||||
|
@TableField(value = "\"locale\"")
|
||||||
|
@Schema(description="语言标识,如 zh-CN/en-US/ja-JP")
|
||||||
|
private String locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标题
|
||||||
|
*/
|
||||||
|
@TableField(value = "character_name")
|
||||||
|
@Schema(description="标题")
|
||||||
|
private String characterName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 背景描述
|
||||||
|
*/
|
||||||
|
@TableField(value = "character_background")
|
||||||
|
@Schema(description="背景描述")
|
||||||
|
private String characterBackground;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(value = "created_at")
|
||||||
|
@Schema(description="创建时间")
|
||||||
|
private Date createdAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@TableField(value = "updated_at")
|
||||||
|
@Schema(description="更新时间")
|
||||||
|
private Date updatedAt;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.yolo.keyborad.service;
|
||||||
|
|
||||||
|
import com.yolo.keyborad.model.entity.KeyboardCharacterI18n;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
/*
|
||||||
|
* @author: ziin
|
||||||
|
* @date: 2026/4/1 14:13
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface KeyboardCharacterI18nService extends IService<KeyboardCharacterI18n>{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -18,11 +18,11 @@ import java.util.List;
|
|||||||
public interface KeyboardCharacterService extends IService<KeyboardCharacter>{
|
public interface KeyboardCharacterService extends IService<KeyboardCharacter>{
|
||||||
|
|
||||||
|
|
||||||
List<KeyboardCharacterRespVO> selectListWithRank();
|
List<KeyboardCharacterRespVO> selectListWithRank(String acceptLanguage);
|
||||||
|
|
||||||
List<KeyboardCharacterRespVO> selectListByTag(Long tagId);
|
List<KeyboardCharacterRespVO> selectListByTag(Long tagId, String acceptLanguage);
|
||||||
|
|
||||||
List<KeyboardUserCharacterVO> selectListByUserId();
|
List<KeyboardUserCharacterVO> selectListByUserId(String acceptLanguage);
|
||||||
|
|
||||||
void updateSort(KeyboardUserCharacterSortUpdateDTO sortUpdateDTO);
|
void updateSort(KeyboardUserCharacterSortUpdateDTO sortUpdateDTO);
|
||||||
|
|
||||||
@@ -30,11 +30,11 @@ public interface KeyboardCharacterService extends IService<KeyboardCharacter>{
|
|||||||
|
|
||||||
void removeUserCharacter(Long id);
|
void removeUserCharacter(Long id);
|
||||||
|
|
||||||
List<KeyboardCharacterRespVO> selectListWithNotLoginRank();
|
List<KeyboardCharacterRespVO> selectListWithNotLoginRank(String acceptLanguage);
|
||||||
|
|
||||||
List<KeyboardCharacterRespVO> selectListByTagWithNotLogin(Long tagId);
|
List<KeyboardCharacterRespVO> selectListByTagWithNotLogin(Long tagId, String acceptLanguage);
|
||||||
|
|
||||||
void addDefaultUserCharacter(Long userId);
|
void addDefaultUserCharacter(Long userId);
|
||||||
|
|
||||||
KeyboardCharacterRespVO getDetailById(Long id);
|
KeyboardCharacterRespVO getDetailById(Long id, String acceptLanguage);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.yolo.keyborad.service.impl;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import java.util.List;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.yolo.keyborad.model.entity.KeyboardCharacterI18n;
|
||||||
|
import com.yolo.keyborad.mapper.KeyboardCharacterI18nMapper;
|
||||||
|
import com.yolo.keyborad.service.KeyboardCharacterI18nService;
|
||||||
|
/*
|
||||||
|
* @author: ziin
|
||||||
|
* @date: 2026/4/1 14:13
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class KeyboardCharacterI18nServiceImpl extends ServiceImpl<KeyboardCharacterI18nMapper, KeyboardCharacterI18n> implements KeyboardCharacterI18nService{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,31 +2,35 @@ package com.yolo.keyborad.service.impl;
|
|||||||
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
|
||||||
import com.yolo.keyborad.common.ErrorCode;
|
import com.yolo.keyborad.common.ErrorCode;
|
||||||
import com.yolo.keyborad.exception.BusinessException;
|
import com.yolo.keyborad.exception.BusinessException;
|
||||||
import com.yolo.keyborad.mapper.KeyboardCharacterMapper;
|
import com.yolo.keyborad.mapper.KeyboardCharacterMapper;
|
||||||
|
import com.yolo.keyborad.mapper.KeyboardCharacterI18nMapper;
|
||||||
import com.yolo.keyborad.mapper.KeyboardUserCharacterMapper;
|
import com.yolo.keyborad.mapper.KeyboardUserCharacterMapper;
|
||||||
import com.yolo.keyborad.mapper.KeyboardUserSortMapper;
|
import com.yolo.keyborad.mapper.KeyboardUserSortMapper;
|
||||||
import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterAddDTO;
|
import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterAddDTO;
|
||||||
import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterSortUpdateDTO;
|
import com.yolo.keyborad.model.dto.userCharacter.KeyboardUserCharacterSortUpdateDTO;
|
||||||
import com.yolo.keyborad.model.entity.KeyboardUser;
|
|
||||||
import com.yolo.keyborad.model.entity.KeyboardUserCharacter;
|
import com.yolo.keyborad.model.entity.KeyboardUserCharacter;
|
||||||
|
import com.yolo.keyborad.model.entity.KeyboardCharacterI18n;
|
||||||
import com.yolo.keyborad.model.vo.character.KeyboardCharacterRespVO;
|
import com.yolo.keyborad.model.vo.character.KeyboardCharacterRespVO;
|
||||||
import com.yolo.keyborad.model.vo.character.KeyboardUserCharacterVO;
|
import com.yolo.keyborad.model.vo.character.KeyboardUserCharacterVO;
|
||||||
|
import com.yolo.keyborad.utils.RequestLocaleUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.yolo.keyborad.model.entity.KeyboardCharacter;
|
import com.yolo.keyborad.model.entity.KeyboardCharacter;
|
||||||
import com.yolo.keyborad.service.KeyboardCharacterService;
|
import com.yolo.keyborad.service.KeyboardCharacterService;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -38,7 +42,9 @@ import java.util.stream.Stream;
|
|||||||
@Service
|
@Service
|
||||||
public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterMapper, KeyboardCharacter> implements KeyboardCharacterService{
|
public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterMapper, KeyboardCharacter> implements KeyboardCharacterService{
|
||||||
|
|
||||||
private static final String CHARACTER_CACHE_KEY = "character:";
|
private static final String CHARACTER_CACHE_KEY_PREFIX = "character:";
|
||||||
|
private static final String CHARACTER_LIST_CACHE_KEY = "character:list:all";
|
||||||
|
private static final String CHARACTER_TAG_CACHE_KEY_PREFIX = "character:list:tag:";
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private KeyboardCharacterMapper keyboardCharacterMapper;
|
private KeyboardCharacterMapper keyboardCharacterMapper;
|
||||||
@@ -49,12 +55,15 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterM
|
|||||||
@Resource
|
@Resource
|
||||||
private KeyboardUserSortMapper keyboardUserSortMapper;
|
private KeyboardUserSortMapper keyboardUserSortMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private KeyboardCharacterI18nMapper keyboardCharacterI18nMapper;
|
||||||
|
|
||||||
@Resource(name = "objectRedisTemplate")
|
@Resource(name = "objectRedisTemplate")
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyboardCharacter getById(java.io.Serializable id) {
|
public KeyboardCharacter getById(java.io.Serializable id) {
|
||||||
String key = CHARACTER_CACHE_KEY + id;
|
String key = CHARACTER_CACHE_KEY_PREFIX + id;
|
||||||
KeyboardCharacter character = (KeyboardCharacter) redisTemplate.opsForValue().get(key);
|
KeyboardCharacter character = (KeyboardCharacter) redisTemplate.opsForValue().get(key);
|
||||||
if (character == null) {
|
if (character == null) {
|
||||||
character = super.getById(id);
|
character = super.getById(id);
|
||||||
@@ -72,12 +81,11 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterM
|
|||||||
* @return 人设响应列表,包含是否已添加的标记
|
* @return 人设响应列表,包含是否已添加的标记
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<KeyboardCharacterRespVO> selectListWithRank() {
|
public List<KeyboardCharacterRespVO> selectListWithRank(String acceptLanguage) {
|
||||||
// 获取当前登录用户ID
|
// 获取当前登录用户ID
|
||||||
long userId = StpUtil.getLoginIdAsLong();
|
long userId = StpUtil.getLoginIdAsLong();
|
||||||
|
|
||||||
// 定义缓存key,用于存储所有人设列表
|
String cacheKey = CHARACTER_LIST_CACHE_KEY;
|
||||||
String cacheKey = "character:list:all";
|
|
||||||
// 尝试从Redis缓存中获取人设列表
|
// 尝试从Redis缓存中获取人设列表
|
||||||
List<KeyboardCharacter> keyboardCharacters = (List<KeyboardCharacter>) redisTemplate.opsForValue().get(cacheKey);
|
List<KeyboardCharacter> keyboardCharacters = (List<KeyboardCharacter>) redisTemplate.opsForValue().get(cacheKey);
|
||||||
|
|
||||||
@@ -95,17 +103,12 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterM
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查询当前用户已添加的人设列表
|
// 查询当前用户已添加的人设列表
|
||||||
List<KeyboardUserCharacterVO> userCharacterVOList = keyboardUserCharacterMapper.selectByUserId(userId);
|
List<KeyboardUserCharacterVO> userCharacterVOList = keyboardUserCharacterMapper.selectByUserId(userId, null);
|
||||||
|
|
||||||
// 将KeyboardCharacter实体列表转换为KeyboardCharacterRespVO响应对象列表
|
// 将KeyboardCharacter实体列表转换为KeyboardCharacterRespVO响应对象列表
|
||||||
List<KeyboardCharacterRespVO> keyboardCharacterRespVOS = BeanUtil.copyToList(keyboardCharacters, KeyboardCharacterRespVO.class);
|
List<KeyboardCharacterRespVO> keyboardCharacterRespVOS = buildCharacterRespList(keyboardCharacters, acceptLanguage);
|
||||||
|
|
||||||
// 遍历人设列表,标记每个人设是否已被当前用户添加
|
markAddedCharacters(keyboardCharacterRespVOS, userCharacterVOList);
|
||||||
keyboardCharacterRespVOS.forEach(character -> {
|
|
||||||
// 检查用户已添加列表中是否存在该人设ID
|
|
||||||
character.setAdded(userCharacterVOList.stream().anyMatch(userCharacter ->
|
|
||||||
userCharacter.getCharacterId().equals(character.getId())));
|
|
||||||
});
|
|
||||||
|
|
||||||
return keyboardCharacterRespVOS;
|
return keyboardCharacterRespVOS;
|
||||||
}
|
}
|
||||||
@@ -118,9 +121,8 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterM
|
|||||||
* @return 人设响应列表,包含是否已添加的标记
|
* @return 人设响应列表,包含是否已添加的标记
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<KeyboardCharacterRespVO> selectListByTag(Long tagId) {
|
public List<KeyboardCharacterRespVO> selectListByTag(Long tagId, String acceptLanguage) {
|
||||||
// 构建缓存key,用于存储指定标签的人设列表
|
String cacheKey = CHARACTER_TAG_CACHE_KEY_PREFIX + tagId;
|
||||||
String cacheKey = "character:list:tag:" + tagId;
|
|
||||||
// 尝试从Redis缓存中获取指定标签的人设列表
|
// 尝试从Redis缓存中获取指定标签的人设列表
|
||||||
List<KeyboardCharacter> keyboardCharacters = (List<KeyboardCharacter>) redisTemplate.opsForValue().get(cacheKey);
|
List<KeyboardCharacter> keyboardCharacters = (List<KeyboardCharacter>) redisTemplate.opsForValue().get(cacheKey);
|
||||||
|
|
||||||
@@ -142,25 +144,21 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterM
|
|||||||
long userId = StpUtil.getLoginIdAsLong();
|
long userId = StpUtil.getLoginIdAsLong();
|
||||||
|
|
||||||
// 查询当前用户已添加的人设列表
|
// 查询当前用户已添加的人设列表
|
||||||
List<KeyboardUserCharacterVO> userCharacterVOList = keyboardUserCharacterMapper.selectByUserId(userId);
|
List<KeyboardUserCharacterVO> userCharacterVOList = keyboardUserCharacterMapper.selectByUserId(userId, null);
|
||||||
|
|
||||||
// 将KeyboardCharacter实体列表转换为KeyboardCharacterRespVO响应对象列表
|
// 将KeyboardCharacter实体列表转换为KeyboardCharacterRespVO响应对象列表
|
||||||
List<KeyboardCharacterRespVO> keyboardCharacterRespVOS = BeanUtil.copyToList(keyboardCharacters, KeyboardCharacterRespVO.class);
|
List<KeyboardCharacterRespVO> keyboardCharacterRespVOS = buildCharacterRespList(keyboardCharacters, acceptLanguage);
|
||||||
|
|
||||||
// 遍历人设列表,标记每个人设是否已被当前用户添加
|
markAddedCharacters(keyboardCharacterRespVOS, userCharacterVOList);
|
||||||
keyboardCharacterRespVOS.forEach(character -> {
|
|
||||||
// 检查用户已添加列表中是否存在该人设ID
|
|
||||||
character.setAdded(userCharacterVOList.stream().anyMatch(userCharacter ->
|
|
||||||
userCharacter.getCharacterId().equals(character.getId())));
|
|
||||||
});
|
|
||||||
|
|
||||||
return keyboardCharacterRespVOS;
|
return keyboardCharacterRespVOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<KeyboardUserCharacterVO> selectListByUserId() {
|
public List<KeyboardUserCharacterVO> selectListByUserId(String acceptLanguage) {
|
||||||
long loginId = StpUtil.getLoginIdAsLong();
|
long loginId = StpUtil.getLoginIdAsLong();
|
||||||
return keyboardUserCharacterMapper.selectByUserId(loginId);
|
String locale = RequestLocaleUtils.resolveLanguage(acceptLanguage);
|
||||||
|
return keyboardUserCharacterMapper.selectByUserId(loginId, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -225,9 +223,8 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterM
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<KeyboardCharacterRespVO> selectListWithNotLoginRank() {
|
public List<KeyboardCharacterRespVO> selectListWithNotLoginRank(String acceptLanguage) {
|
||||||
// 先从缓存获取所有人设列表
|
String cacheKey = CHARACTER_LIST_CACHE_KEY;
|
||||||
String cacheKey = "character:list:all";
|
|
||||||
List<KeyboardCharacter> keyboardCharacters = (List<KeyboardCharacter>) redisTemplate.opsForValue().get(cacheKey);
|
List<KeyboardCharacter> keyboardCharacters = (List<KeyboardCharacter>) redisTemplate.opsForValue().get(cacheKey);
|
||||||
|
|
||||||
if (keyboardCharacters == null) {
|
if (keyboardCharacters == null) {
|
||||||
@@ -240,13 +237,12 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterM
|
|||||||
redisTemplate.opsForValue().set(cacheKey, keyboardCharacters, 7, TimeUnit.DAYS);
|
redisTemplate.opsForValue().set(cacheKey, keyboardCharacters, 7, TimeUnit.DAYS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return BeanUtil.copyToList(keyboardCharacters, KeyboardCharacterRespVO.class);
|
return buildCharacterRespList(keyboardCharacters, acceptLanguage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<KeyboardCharacterRespVO> selectListByTagWithNotLogin(Long tagId) {
|
public List<KeyboardCharacterRespVO> selectListByTagWithNotLogin(Long tagId, String acceptLanguage) {
|
||||||
// 先从缓存获取指定标签的人设列表
|
String cacheKey = CHARACTER_TAG_CACHE_KEY_PREFIX + tagId;
|
||||||
String cacheKey = "character:list:tag:" + tagId;
|
|
||||||
List<KeyboardCharacter> keyboardCharacters = (List<KeyboardCharacter>) redisTemplate.opsForValue().get(cacheKey);
|
List<KeyboardCharacter> keyboardCharacters = (List<KeyboardCharacter>) redisTemplate.opsForValue().get(cacheKey);
|
||||||
|
|
||||||
if (keyboardCharacters == null) {
|
if (keyboardCharacters == null) {
|
||||||
@@ -260,7 +256,7 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterM
|
|||||||
redisTemplate.opsForValue().set(cacheKey, keyboardCharacters, 7, TimeUnit.DAYS);
|
redisTemplate.opsForValue().set(cacheKey, keyboardCharacters, 7, TimeUnit.DAYS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return BeanUtil.copyToList(keyboardCharacters, KeyboardCharacterRespVO.class);
|
return buildCharacterRespList(keyboardCharacters, acceptLanguage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -276,7 +272,7 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterM
|
|||||||
KeyboardUserCharacterAddDTO keyboardUserCharacterAddDTO = new KeyboardUserCharacterAddDTO();
|
KeyboardUserCharacterAddDTO keyboardUserCharacterAddDTO = new KeyboardUserCharacterAddDTO();
|
||||||
|
|
||||||
// 获取所有人设列表(未登录状态),并限制取前5个
|
// 获取所有人设列表(未登录状态),并限制取前5个
|
||||||
Stream<KeyboardCharacterRespVO> limit = selectListWithNotLoginRank().stream().limit(5);
|
Stream<KeyboardCharacterRespVO> limit = selectListWithNotLoginRank(null).stream().limit(5);
|
||||||
|
|
||||||
// 遍历前5个人设,为用户添加默认人设
|
// 遍历前5个人设,为用户添加默认人设
|
||||||
limit.forEach(character -> {
|
limit.forEach(character -> {
|
||||||
@@ -290,20 +286,83 @@ public class KeyboardCharacterServiceImpl extends ServiceImpl<KeyboardCharacterM
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyboardCharacterRespVO getDetailById(Long id) {
|
public KeyboardCharacterRespVO getDetailById(Long id, String acceptLanguage) {
|
||||||
// 根据ID获取人设信息,优先从缓存获取
|
// 根据ID获取人设信息,优先从缓存获取
|
||||||
KeyboardCharacter character = this.getById(id);
|
KeyboardCharacter character = this.getById(id);
|
||||||
// 将实体对象转换为响应对象
|
// 将实体对象转换为响应对象
|
||||||
KeyboardCharacterRespVO respVO = BeanUtil.copyProperties(character, KeyboardCharacterRespVO.class);
|
KeyboardCharacterRespVO respVO = BeanUtil.copyProperties(character, KeyboardCharacterRespVO.class);
|
||||||
// 判断当前用户是否已添加该人设
|
applyI18n(List.of(respVO), acceptLanguage);
|
||||||
|
if (!StpUtil.isLogin()) {
|
||||||
|
respVO.setAdded(false);
|
||||||
|
return respVO;
|
||||||
|
}
|
||||||
|
|
||||||
long userId = StpUtil.getLoginIdAsLong();
|
long userId = StpUtil.getLoginIdAsLong();
|
||||||
// 查询用户人设关联表,判断当前用户是否已添加该人设
|
|
||||||
KeyboardUserCharacter userCharacter = keyboardUserCharacterMapper.selectOne(
|
KeyboardUserCharacter userCharacter = keyboardUserCharacterMapper.selectOne(
|
||||||
new LambdaQueryWrapper<KeyboardUserCharacter>()
|
new LambdaQueryWrapper<KeyboardUserCharacter>()
|
||||||
.eq(KeyboardUserCharacter::getCharacterId, id)
|
.eq(KeyboardUserCharacter::getCharacterId, id)
|
||||||
.eq(KeyboardUserCharacter::getUserId, userId));
|
.eq(KeyboardUserCharacter::getUserId, userId));
|
||||||
// 设置是否已添加的标记
|
|
||||||
respVO.setAdded(userCharacter != null);
|
respVO.setAdded(userCharacter != null);
|
||||||
return respVO;
|
return respVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<KeyboardCharacterRespVO> buildCharacterRespList(List<KeyboardCharacter> keyboardCharacters, String acceptLanguage) {
|
||||||
|
if (keyboardCharacters == null || keyboardCharacters.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
List<KeyboardCharacterRespVO> respVOS = BeanUtil.copyToList(keyboardCharacters, KeyboardCharacterRespVO.class);
|
||||||
|
applyI18n(respVOS, acceptLanguage);
|
||||||
|
return respVOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyI18n(List<KeyboardCharacterRespVO> respVOS, String acceptLanguage) {
|
||||||
|
if (respVOS == null || respVOS.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String locale = RequestLocaleUtils.resolveLanguage(acceptLanguage);
|
||||||
|
if (!StringUtils.hasText(locale)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Long> characterIds = respVOS.stream()
|
||||||
|
.map(KeyboardCharacterRespVO::getId)
|
||||||
|
.toList();
|
||||||
|
Map<Long, KeyboardCharacterI18n> i18nMap = loadI18nMap(characterIds, locale);
|
||||||
|
respVOS.forEach(respVO -> {
|
||||||
|
KeyboardCharacterI18n i18n = i18nMap.get(respVO.getId());
|
||||||
|
if (i18n == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
respVO.setCharacterName(i18n.getCharacterName());
|
||||||
|
respVO.setCharacterBackground(i18n.getCharacterBackground());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markAddedCharacters(List<KeyboardCharacterRespVO> respVOS, List<KeyboardUserCharacterVO> userCharacterVOList) {
|
||||||
|
if (respVOS == null || respVOS.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Long> addedCharacterIds = new HashSet<>();
|
||||||
|
if (userCharacterVOList != null && !userCharacterVOList.isEmpty()) {
|
||||||
|
userCharacterVOList.forEach(userCharacter -> addedCharacterIds.add(userCharacter.getCharacterId()));
|
||||||
|
}
|
||||||
|
respVOS.forEach(character -> character.setAdded(addedCharacterIds.contains(character.getId())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Long, KeyboardCharacterI18n> loadI18nMap(List<Long> characterIds, String locale) {
|
||||||
|
if (characterIds == null || characterIds.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
List<KeyboardCharacterI18n> i18nList = keyboardCharacterI18nMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<KeyboardCharacterI18n>()
|
||||||
|
.eq(KeyboardCharacterI18n::getLocale, locale)
|
||||||
|
.in(KeyboardCharacterI18n::getCharacterId, characterIds)
|
||||||
|
);
|
||||||
|
if (i18nList == null || i18nList.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
Map<Long, KeyboardCharacterI18n> i18nMap = new LinkedHashMap<>();
|
||||||
|
i18nList.forEach(item -> i18nMap.put(item.getCharacterId(), item));
|
||||||
|
return i18nMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/main/resources/mapper/KeyboardCharacterI18nMapper.xml
Normal file
19
src/main/resources/mapper/KeyboardCharacterI18nMapper.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.yolo.keyborad.mapper.KeyboardCharacterI18nMapper">
|
||||||
|
<resultMap id="BaseResultMap" type="com.yolo.keyborad.model.entity.KeyboardCharacterI18n">
|
||||||
|
<!--@mbg.generated-->
|
||||||
|
<!--@Table keyboard_character_i18n-->
|
||||||
|
<id column="id" jdbcType="BIGINT" property="id" />
|
||||||
|
<result column="character_id" jdbcType="BIGINT" property="characterId" />
|
||||||
|
<result column="locale" jdbcType="VARCHAR" property="locale" />
|
||||||
|
<result column="character_name" jdbcType="VARCHAR" property="characterName" />
|
||||||
|
<result column="character_background" jdbcType="VARCHAR" property="characterBackground" />
|
||||||
|
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt" />
|
||||||
|
<result column="updated_at" jdbcType="TIMESTAMP" property="updatedAt" />
|
||||||
|
</resultMap>
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
<!--@mbg.generated-->
|
||||||
|
id, character_id, "locale", character_name, character_background, created_at, updated_at
|
||||||
|
</sql>
|
||||||
|
</mapper>
|
||||||
@@ -4,8 +4,6 @@
|
|||||||
<resultMap id="BaseResultMap" type="com.yolo.keyborad.model.entity.KeyboardCharacter">
|
<resultMap id="BaseResultMap" type="com.yolo.keyborad.model.entity.KeyboardCharacter">
|
||||||
<!--@Table keyboard_character-->
|
<!--@Table keyboard_character-->
|
||||||
<id column="id" jdbcType="BIGINT" property="id" />
|
<id column="id" jdbcType="BIGINT" property="id" />
|
||||||
<result column="character_name" jdbcType="VARCHAR" property="characterName" />
|
|
||||||
<result column="character_background" jdbcType="VARCHAR" property="characterBackground" />
|
|
||||||
<result column="avatar_url" jdbcType="VARCHAR" property="avatarUrl" />
|
<result column="avatar_url" jdbcType="VARCHAR" property="avatarUrl" />
|
||||||
<result column="download" jdbcType="VARCHAR" property="download" />
|
<result column="download" jdbcType="VARCHAR" property="download" />
|
||||||
<result column="tag" jdbcType="BIGINT" property="tag" />
|
<result column="tag" jdbcType="BIGINT" property="tag" />
|
||||||
@@ -17,7 +15,6 @@
|
|||||||
<result column="emoji" jdbcType="VARCHAR" property="emoji" />
|
<result column="emoji" jdbcType="VARCHAR" property="emoji" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, character_name, "character_background", avatar_url, download, tag, deleted, created_at,
|
id, avatar_url, download, tag, deleted, created_at, updated_at, prompt, "rank", emoji
|
||||||
updated_at, prompt, "rank",emoji
|
|
||||||
</sql>
|
</sql>
|
||||||
</mapper>
|
</mapper>
|
||||||
@@ -9,13 +9,14 @@
|
|||||||
SELECT
|
SELECT
|
||||||
kuc.id,
|
kuc.id,
|
||||||
kuc.character_id,
|
kuc.character_id,
|
||||||
kc.character_name,
|
kci.character_name,
|
||||||
kuc.emoji
|
kuc.emoji
|
||||||
FROM keyboard_user_character kuc
|
FROM keyboard_user_character kuc
|
||||||
JOIN keyboard_user_sort kus
|
JOIN keyboard_user_sort kus
|
||||||
ON kus.user_id = kuc.user_id
|
ON kus.user_id = kuc.user_id
|
||||||
LEFT JOIN keyboard_character kc
|
LEFT JOIN keyboard_character_i18n kci
|
||||||
ON kuc.character_id = kc.id
|
ON kuc.character_id = kci.character_id
|
||||||
|
AND kci."locale" = #{locale}
|
||||||
WHERE kuc.user_id = #{loginId}
|
WHERE kuc.user_id = #{loginId}
|
||||||
AND kuc.deleted = FALSE
|
AND kuc.deleted = FALSE
|
||||||
ORDER BY array_position(kus.user_characteu_id_sort, kuc.id) NULLS LAST;
|
ORDER BY array_position(kus.user_characteu_id_sort, kuc.id) NULLS LAST;
|
||||||
|
|||||||
Reference in New Issue
Block a user