优化后台业务

This commit is contained in:
super
2026-04-30 11:36:58 +08:00
parent 9760d1171c
commit 172917ac41
48 changed files with 1211 additions and 2391 deletions

View File

@@ -649,7 +649,7 @@ public class AppearancePatentCozeClient {
}
private String normalize(String value) {
return value == null ? "" : value.replace("\ufeff", "").replace("\u3000", " ").trim();
return value == null ? "" : value.replace(String.valueOf((char) 0xFEFF), "").replace((char) 0x3000, ' ').trim();
}
private String rowKey(AppearancePatentResultRowDto row) {

View File

@@ -83,7 +83,10 @@ public class AppearancePatentController {
public ApiResponse<Void> result(
@Parameter(description = "外观专利检测任务 ID。任务必须处于 RUNNING 状态。", required = true, example = "3938")
@PathVariable Long taskId,
@Valid @RequestBody AppearancePatentSubmitResultRequest request) {
@Valid @RequestBody AppearancePatentSubmitResultRequest request,
jakarta.servlet.http.HttpServletResponse response) {
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setContentType("application/json;charset=UTF-8");
service.submitResult(taskId, request);
return ApiResponse.success(null);
}

View File

@@ -121,7 +121,7 @@ public class AppearancePatentTaskService {
.filter(Objects::nonNull)
.toList();
if (sourceFiles.isEmpty()) {
throw new BusinessException("璇峰厛涓婁紶 Excel 鏂囦欢");
throw new BusinessException("请先上传 Excel 文件");
}
List<AppearancePatentParsedRowVo> allRows = new ArrayList<>();
List<String> mergedHeaders = new ArrayList<>();
@@ -461,10 +461,10 @@ public class AppearancePatentTaskService {
private SubmitContext persistSubmittedChunk(Long taskId, AppearancePatentSubmitResultRequest request) {
FileTaskEntity task = fileTaskMapper.selectById(taskId);
if (task == null || !MODULE_TYPE.equals(task.getModuleType())) {
throw new BusinessException("浠诲姟涓嶅瓨鍦?");
throw new BusinessException("任务不存在");
}
if (!STATUS_RUNNING.equals(task.getStatus())) {
throw new BusinessException("浠诲姟涓嶆槸杩愯涓姸鎬?");
throw new BusinessException("任务不是运行中状态");
}
int chunkIndex = request.getChunkIndex() == null ? 0 : request.getChunkIndex();
@@ -482,7 +482,7 @@ public class AppearancePatentTaskService {
.last("limit 1"));
if (existing == null) {
List<AppearancePatentResultRowDto> rawRows = flattenSubmittedRows(request);
String payloadJson = writeJson(rawRows, "缁撴灉搴忓垪鍖栧け璐?");
String payloadJson = writeJson(rawRows, "结果序列化失败");
TaskChunkEntity chunk = new TaskChunkEntity();
chunk.setTaskId(taskId);
@@ -514,7 +514,7 @@ public class AppearancePatentTaskService {
private void completeSubmittedChunk(SubmitContext context) {
FileTaskEntity task = fileTaskMapper.selectById(context.task().getId());
if (task == null || !MODULE_TYPE.equals(task.getModuleType())) {
throw new BusinessException("浠诲姟涓嶅瓨鍦?");
throw new BusinessException("任务不存在");
}
if (!STATUS_RUNNING.equals(task.getStatus())) {
log.info("[appearance-patent] skip completion because task already finalized taskId={} status={}",
@@ -1379,7 +1379,7 @@ public class AppearancePatentTaskService {
}
private String normalize(String val) {
return val == null ? "" : val.replace("\ufeff", "").replace("\u3000", " ").trim().replaceAll("\\s+", " ");
return val == null ? "" : val.replace(String.valueOf((char) 0xFEFF), "").replace((char) 0x3000, ' ').trim().replaceAll("\\s+", " ");
}
private String buildParsedPayloadJson(String aiPrompt, List<AppearancePatentSourceFileDto> sourceFiles, List<String> headers, List<AppearancePatentParsedGroupVo> groups, List<AppearancePatentParsedRowVo> allRows) {

View File

@@ -881,8 +881,8 @@ public class BrandTaskService {
if (value == null) {
return "";
}
return value.replace("\ufeff", "")
.replace("\u3000", " ")
return value.replace(String.valueOf((char) 0xFEFF), "")
.replace((char) 0x3000, ' ')
.replace("\r\n", " ")
.replace("\r", " ")
.replace("\n", " ")

View File

@@ -475,8 +475,8 @@ public class ConvertRunService {
if (value == null) {
return "";
}
return value.replace("\ufeff", "")
.replace("\u3000", " ")
return value.replace(String.valueOf((char) 0xFEFF), "")
.replace((char) 0x3000, ' ')
.replace("\r\n", " ")
.replace("\r", " ")
.replace("\n", " ")

View File

@@ -47,8 +47,8 @@ import java.util.zip.ZipOutputStream;
@Slf4j
public class DedupeRunService {
private static final String HEADER_SPLIT_MARKER = "idASIN\u56fd\u5bb6\u72b6\u6001\u4ef7\u683c\u53d8\u4f53\u6570\u91cf";
private static final String HEADER_STOP_COLUMN = "\u7f29\u7565\u56fe\u5730\u57408";
private static final String HEADER_SPLIT_MARKER = "idASIN国家状态价格变体数量";
private static final String HEADER_STOP_COLUMN = "缩略图地址8";
private final FileTaskMapper fileTaskMapper;
private final FileResultMapper fileResultMapper;
@@ -59,7 +59,7 @@ public class DedupeRunService {
public DedupeRunVo run(DedupeRunRequest request) {
long runStartNs = System.nanoTime();
if (!request.isKeepIntegerIds() && !request.isKeepUnderscoreIds() && !request.isKeepIntegerMainIdsWhenNoSubIds()) {
throw new BusinessException("\u8bf7\u81f3\u5c11\u9009\u62e9\u4e00\u79cd ID \u4fdd\u7559\u89c4\u5219");
throw new BusinessException("请至少选择一种 ID 保留规则");
}
FileTaskEntity task = new FileTaskEntity();
@@ -90,7 +90,7 @@ public class DedupeRunService {
File inputFile = findLocalSourceFile(sourceFile.getFileKey());
long findFileNs = elapsedNs(fileStartNs);
if (inputFile == null || !inputFile.exists()) {
throw new BusinessException("\u4e0a\u4f20\u6587\u4ef6\u4e0d\u5b58\u5728\uff0c\u8bf7\u91cd\u65b0\u4e0a\u4f20");
throw new BusinessException("上传文件不存在,请重新上传");
}
String inputName = sourceFile.getOriginalFilename() == null ? inputFile.getName() : sourceFile.getOriginalFilename();
@@ -240,7 +240,7 @@ public class DedupeRunService {
public void deleteHistory(Long resultId, Long userId) {
FileResultEntity entity = fileResultMapper.selectById(resultId);
if (entity == null || !"DEDUPE".equals(entity.getModuleType()) || !userId.equals(entity.getUserId())) {
throw new BusinessException("\u8bb0\u5f55\u4e0d\u5b58\u5728");
throw new BusinessException("记录不存在");
}
fileResultMapper.deleteById(resultId);
}
@@ -248,11 +248,11 @@ public class DedupeRunService {
public Resource getResultFile(Long resultId, Long userId) {
FileResultEntity entity = fileResultMapper.selectById(resultId);
if (entity == null || entity.getResultFileUrl() == null || !"DEDUPE".equals(entity.getModuleType()) || !userId.equals(entity.getUserId())) {
throw new BusinessException("\u7ed3\u679c\u6587\u4ef6\u4e0d\u5b58\u5728");
throw new BusinessException("结果文件不存在");
}
File file = new File(entity.getResultFileUrl());
if (!file.exists()) {
throw new BusinessException("\u7ed3\u679c\u6587\u4ef6\u4e0d\u5b58\u5728");
throw new BusinessException("结果文件不存在");
}
return new FileSystemResource(file);
}
@@ -342,18 +342,18 @@ public class DedupeRunService {
Sheet sheet = workbook.getSheetAt(0);
Row headerRow = sheet.getRow(0);
if (headerRow == null) {
throw new BusinessException("Excel \u8868\u5934\u4e3a\u7a7a");
throw new BusinessException("Excel 表头为空");
}
Map<String, Integer> headerMap = buildHeaderMap(headerRow, formatter);
if (headerMap.isEmpty()) {
throw new BusinessException("Excel \u8868\u5934\u4e3a\u7a7a");
throw new BusinessException("Excel 表头为空");
}
List<String> missing = selectedColumns.stream()
.filter(column -> !headerMap.containsKey(column))
.toList();
if (!missing.isEmpty()) {
throw new BusinessException("\u7f3a\u5c11\u5217\uff1a" + String.join("\u3001", missing));
throw new BusinessException("缺少列:" + String.join("", missing));
}
List<Integer> selectedIndexes = new ArrayList<>(selectedColumns.size());
@@ -478,7 +478,7 @@ public class DedupeRunService {
zos.closeEntry();
}
} catch (Exception ex) {
throw new BusinessException("\u53bb\u91cd\u7ed3\u679c\u6253\u5305\u5931\u8d25\uff1a" + ex.getMessage());
throw new BusinessException("去重结果打包失败:" + ex.getMessage());
}
return zipFile;
}
@@ -602,7 +602,7 @@ public class DedupeRunService {
boolean previousWhitespace = false;
for (int i = start; i < end; i++) {
char ch = value.charAt(i);
if (ch == '\uFEFF') {
if (ch == 0xFEFF) {
if (builder == null) {
builder = new StringBuilder(value.length());
builder.append(value, start, i);
@@ -629,11 +629,11 @@ public class DedupeRunService {
}
private boolean isTrimmedWhitespace(char ch) {
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\u3000' || Character.isWhitespace(ch);
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == 0x3000 || Character.isWhitespace(ch);
}
private boolean isNormalizedWhitespace(char ch) {
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\u3000' || Character.isWhitespace(ch);
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == 0x3000 || Character.isWhitespace(ch);
}
private record DedupeArchiveEntry(String relativePath, String inputName, File outputFile) {

View File

@@ -109,8 +109,8 @@ public class LocalFileStorageService {
if (value == null) {
return "";
}
return value.replace("\ufeff", "")
.replace("\u3000", " ")
return value.replace(String.valueOf((char) 0xFEFF), "")
.replace((char) 0x3000, ' ')
.replace("\r\n", " ")
.replace("\r", " ")
.replace("\n", " ")

View File

@@ -281,7 +281,6 @@ public class PatrolDeleteTaskService {
return vo;
}
@Transactional
public void submitResult(Long taskId, PatrolDeleteSubmitResultRequest request) {
if (taskId == null || taskId <= 0) {
throw new BusinessException("taskId 不合法");
@@ -334,7 +333,6 @@ public class PatrolDeleteTaskService {
tryFinalizeTask(taskId, false);
}
@Transactional
public boolean tryFinalizeTask(Long taskId, boolean fromCompensation) {
if (taskId == null || taskId <= 0) {
return false;

View File

@@ -1,5 +1,6 @@
package com.nanri.aiimage.modules.pricetrack.model.dto;
import com.fasterxml.jackson.annotation.JsonAlias;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -88,6 +89,10 @@ public class PriceTrackSubmitResultRequest {
@Schema(description = "购物车店铺名", example = "店铺A")
private String cartShopName;
@JsonAlias({"changedPrice", "changePrice", "modifiedPrice", "newPrice", "targetPrice", "updatedPrice", "改价价格"})
@Schema(description = "改价价格", example = "18.99")
private String priceChangePrice;
@Schema(description = "改价情况", example = "UPDATED")
private String priceChangeStatus;

View File

@@ -29,6 +29,7 @@ public class PriceTrackExcelAssemblyService {
"第一名",
"第二名",
"购物车店铺名",
"改价价格",
"改价情况",
"修改次数",
"状态"
@@ -40,13 +41,14 @@ public class PriceTrackExcelAssemblyService {
workbook.setCompressTempFiles(true);
try (FileOutputStream fos = new FileOutputStream(outputXlsx)) {
for (ProductRiskCountryCode code : ProductRiskCountryCode.values()) {
String sheetName = code.name();
String countryCode = code.name();
String sheetName = sheetNameOf(code);
Sheet sheet = workbook.createSheet(sheetName);
Row headerRow = sheet.createRow(0);
for (int i = 0; i < RESULT_HEADER.length; i++) {
headerRow.createCell(i).setCellValue(RESULT_HEADER[i]);
}
List<PriceTrackSubmitResultRequest.AsinResult> rows = safe.getOrDefault(sheetName, List.of());
List<PriceTrackSubmitResultRequest.AsinResult> rows = safe.getOrDefault(countryCode, List.of());
int rowIdx = 1;
for (PriceTrackSubmitResultRequest.AsinResult item : rows) {
if (item == null) {
@@ -62,9 +64,10 @@ public class PriceTrackExcelAssemblyService {
row.createCell(6).setCellValue(valueOf(item.getFirstPlace()));
row.createCell(7).setCellValue(valueOf(item.getSecondPlace()));
row.createCell(8).setCellValue(valueOf(item.getCartShopName()));
row.createCell(9).setCellValue(valueOf(item.getPriceChangeStatus()));
row.createCell(10).setCellValue(valueOf(item.getModifyCount()));
row.createCell(11).setCellValue(valueOf(item.getStatus()));
row.createCell(9).setCellValue(valueOf(item.getPriceChangePrice()));
row.createCell(10).setCellValue(valueOf(item.getPriceChangeStatus()));
row.createCell(11).setCellValue(valueOf(item.getModifyCount()));
row.createCell(12).setCellValue(valueOf(item.getStatus()));
}
applyDefaultColumnWidths(sheet);
}
@@ -113,8 +116,18 @@ public class PriceTrackExcelAssemblyService {
return value == null ? "" : value;
}
private static String sheetNameOf(ProductRiskCountryCode code) {
return switch (code) {
case DE -> "德国";
case FR -> "法国";
case ES -> "西班牙";
case IT -> "意大利";
case UK -> "英国";
};
}
private void applyDefaultColumnWidths(Sheet sheet) {
int[] widths = {22, 18, 12, 12, 12, 12, 20, 20, 22, 18, 12, 12};
int[] widths = {22, 18, 12, 12, 12, 12, 20, 20, 22, 14, 18, 12, 12};
for (int i = 0; i < widths.length; i++) {
sheet.setColumnWidth(i, widths[i] * 256);
}

View File

@@ -127,6 +127,21 @@ public class PriceTrackTaskService {
return tasks;
}
private List<FileTaskEntity> selectTaskStatusesByIdsInBatches(List<Long> taskIds) {
List<FileTaskEntity> tasks = new ArrayList<>();
if (taskIds == null || taskIds.isEmpty()) {
return tasks;
}
int batchSize = Math.max(1, taskPressureProperties.getDbSelectBatchSize());
for (int start = 0; start < taskIds.size(); start += batchSize) {
int end = Math.min(start + batchSize, taskIds.size());
tasks.addAll(fileTaskMapper.selectList(new LambdaQueryWrapper<FileTaskEntity>()
.select(FileTaskEntity::getId, FileTaskEntity::getStatus)
.in(FileTaskEntity::getId, taskIds.subList(start, end))));
}
return tasks;
}
public PriceTrackDashboardVo dashboard(Long userId) {
if (userId == null || userId <= 0) throw new BusinessException("user_id 不合法");
PriceTrackDashboardVo vo = new PriceTrackDashboardVo();
@@ -166,7 +181,7 @@ public class PriceTrackTaskService {
.distinct()
.toList();
if (!taskIds.isEmpty()) {
List<FileTaskEntity> tasks = selectTasksByIdsInBatches(taskIds);
List<FileTaskEntity> tasks = selectTaskStatusesByIdsInBatches(taskIds);
for (FileTaskEntity t : tasks) {
if (t != null) statusByTaskId.put(t.getId(), t.getStatus());
}
@@ -383,7 +398,6 @@ public class PriceTrackTaskService {
return vo;
}
@Transactional
public void submitResult(Long taskId, PriceTrackSubmitResultRequest request) {
if (taskId == null || taskId <= 0) throw new BusinessException("taskId 不合法");
if (request == null || request.getShops() == null || request.getShops().isEmpty()) {
@@ -458,7 +472,6 @@ public class PriceTrackTaskService {
updateTaskStatusFromLatestRows(task, latest);
}
@Transactional
public boolean tryFinalizeTask(Long taskId, boolean fromCompensation) {
if (taskId == null || taskId <= 0) return false;
FileTaskEntity task = loadTaskForExecution(taskId);
@@ -1139,6 +1152,7 @@ public class PriceTrackTaskService {
merged.setFirstPlace(firstNonBlank(incoming.getFirstPlace(), merged.getFirstPlace()));
merged.setSecondPlace(firstNonBlank(incoming.getSecondPlace(), merged.getSecondPlace()));
merged.setCartShopName(firstNonBlank(incoming.getCartShopName(), merged.getCartShopName()));
merged.setPriceChangePrice(firstNonBlank(incoming.getPriceChangePrice(), merged.getPriceChangePrice()));
merged.setPriceChangeStatus(firstNonBlank(incoming.getPriceChangeStatus(), merged.getPriceChangeStatus()));
merged.setModifyCount(firstNonBlank(incoming.getModifyCount(), merged.getModifyCount()));
merged.setStatus(firstNonBlank(incoming.getStatus(), merged.getStatus()));
@@ -1163,6 +1177,7 @@ public class PriceTrackTaskService {
out.setFirstPlace(row.getFirstPlace());
out.setSecondPlace(row.getSecondPlace());
out.setCartShopName(row.getCartShopName());
out.setPriceChangePrice(row.getPriceChangePrice());
out.setPriceChangeStatus(row.getPriceChangeStatus());
out.setModifyCount(row.getModifyCount());
out.setStatus(row.getStatus());

View File

@@ -124,6 +124,21 @@ public class ProductRiskTaskService {
return tasks;
}
private List<FileTaskEntity> selectTaskStatusesByIdsInBatches(List<Long> taskIds) {
List<FileTaskEntity> tasks = new ArrayList<>();
if (taskIds == null || taskIds.isEmpty()) {
return tasks;
}
int batchSize = Math.max(1, taskPressureProperties.getDbSelectBatchSize());
for (int start = 0; start < taskIds.size(); start += batchSize) {
int end = Math.min(start + batchSize, taskIds.size());
tasks.addAll(fileTaskMapper.selectList(new LambdaQueryWrapper<FileTaskEntity>()
.select(FileTaskEntity::getId, FileTaskEntity::getStatus)
.in(FileTaskEntity::getId, taskIds.subList(start, end))));
}
return tasks;
}
public ProductRiskDashboardVo dashboard(Long userId) {
if (userId == null || userId <= 0) {
throw new BusinessException("user_id 不合法");
@@ -166,7 +181,7 @@ public class ProductRiskTaskService {
.distinct()
.toList();
if (!taskIds.isEmpty()) {
List<FileTaskEntity> tasks = selectTasksByIdsInBatches(taskIds);
List<FileTaskEntity> tasks = selectTaskStatusesByIdsInBatches(taskIds);
for (FileTaskEntity t : tasks) {
if (t != null) {
statusByTaskId.put(t.getId(), t.getStatus());
@@ -465,7 +480,6 @@ public class ProductRiskTaskService {
return vo;
}
@Transactional
public void submitResult(Long taskId, ProductRiskSubmitResultRequest request) {
if (taskId == null || taskId <= 0) {
throw new BusinessException("taskId 不合法");
@@ -630,7 +644,6 @@ public class ProductRiskTaskService {
cleanupTaskCacheIfTerminal(taskId, task.getStatus());
}
@Transactional
public boolean tryFinalizeTask(Long taskId, boolean fromCompensation) {
if (taskId == null || taskId <= 0) {
return false;

View File

@@ -287,7 +287,6 @@ public class QueryAsinTaskService {
return vo;
}
@Transactional
public void submitResult(Long taskId, QueryAsinSubmitResultRequest request) {
if (taskId == null || taskId <= 0) {
throw new BusinessException("taskId 不合法");
@@ -340,7 +339,6 @@ public class QueryAsinTaskService {
tryFinalizeTask(taskId, false);
}
@Transactional
public boolean tryFinalizeTask(Long taskId, boolean fromCompensation) {
if (taskId == null || taskId <= 0) {
return false;

View File

@@ -3,7 +3,68 @@ package com.nanri.aiimage.modules.shopkey.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface ShopManageGroupMapper extends BaseMapper<ShopManageGroupEntity> {
@Select("""
SELECT DISTINCT accessible_group_id
FROM (
SELECT g.id AS accessible_group_id
FROM biz_shop_manage_group g
WHERE g.created_by_id = #{operatorId}
OR g.user_id = #{operatorId}
UNION
SELECT gm.group_id AS accessible_group_id
FROM biz_shop_manage_group_member gm
WHERE gm.user_id = #{operatorId}
UNION
SELECT g2.id AS accessible_group_id
FROM biz_shop_manage_group_member gm
INNER JOIN biz_shop_manage_group g1 ON g1.id = gm.group_id
INNER JOIN biz_shop_manage_group g2
ON g2.created_by_id = COALESCE(g1.created_by_id, g1.user_id)
OR g2.user_id = COALESCE(g1.created_by_id, g1.user_id)
WHERE gm.user_id = #{operatorId}
AND COALESCE(g1.created_by_id, g1.user_id) IS NOT NULL
UNION
SELECT member_groups.id AS accessible_group_id
FROM biz_shop_manage_group leader_group
INNER JOIN biz_shop_manage_group_member direct_member ON direct_member.group_id = leader_group.id
INNER JOIN biz_shop_manage_group member_groups
ON member_groups.created_by_id = direct_member.user_id
OR member_groups.user_id = direct_member.user_id
WHERE leader_group.created_by_id = #{operatorId}
OR leader_group.user_id = #{operatorId}
) accessible_groups
WHERE accessible_group_id IS NOT NULL
ORDER BY accessible_group_id ASC
""")
List<Long> selectAccessibleGroupIds(@Param("operatorId") Long operatorId);
@Select("""
SELECT DISTINCT visible_user_id
FROM (
SELECT #{operatorId} AS visible_user_id
UNION
SELECT direct_member.user_id AS visible_user_id
FROM biz_shop_manage_group leader_group
INNER JOIN biz_shop_manage_group_member direct_member ON direct_member.group_id = leader_group.id
WHERE leader_group.created_by_id = #{operatorId}
OR leader_group.user_id = #{operatorId}
UNION
SELECT COALESCE(direct_group.created_by_id, direct_group.user_id) AS visible_user_id
FROM biz_shop_manage_group_member membership
INNER JOIN biz_shop_manage_group direct_group ON direct_group.id = membership.group_id
WHERE membership.user_id = #{operatorId}
AND COALESCE(direct_group.created_by_id, direct_group.user_id) IS NOT NULL
) visible_users
WHERE visible_user_id IS NOT NULL
ORDER BY visible_user_id ASC
""")
List<Long> selectAccessibleCreatorUserIds(@Param("operatorId") Long operatorId);
}

View File

@@ -40,7 +40,7 @@ public class QueryAsinService {
private static final List<String> SUPPORTED_COUNTRIES = List.of("DE", "UK", "FR", "IT", "ES");
private static final String KEY_SEPARATOR = Character.toString((char) 1);
private static final String UTF8_BOM = Character.toString(0xFEFF);
private static final String UTF8_BOM = String.valueOf((char) 0xFEFF);
private final QueryAsinMapper queryAsinMapper;
private final ShopManageGroupService shopManageGroupService;
@@ -79,7 +79,7 @@ public class QueryAsinService {
List<QueryAsinEntity> rows = queryAsinMapper
.selectList(query.last("LIMIT " + ((safePage - 1) * safePageSize) + ", " + safePageSize));
Map<Long, String> groupNameById = buildGroupNameMap(rows.stream()
Map<Long, String> groupNameById = shopManageGroupService.buildGroupNameMap(rows.stream()
.map(QueryAsinEntity::getGroupId)
.filter(id -> id != null && id > 0)
.distinct()
@@ -316,22 +316,6 @@ public class QueryAsinService {
return vo;
}
private Map<Long, String> buildGroupNameMap(List<Long> groupIds) {
if (groupIds == null || groupIds.isEmpty()) {
return Map.of();
}
LinkedHashMap<Long, String> map = new LinkedHashMap<>();
for (Long groupId : groupIds) {
try {
ShopManageGroupEntity group = shopManageGroupService.getById(groupId);
map.put(groupId, group.getGroupName());
} catch (Exception ignored) {
map.put(groupId, "");
}
}
return map;
}
private Set<String> normalizeCountries(List<String> countries) {
LinkedHashSet<String> normalized = new LinkedHashSet<>();
if (countries != null) {
@@ -384,11 +368,11 @@ public class QueryAsinService {
return upper;
}
return switch (normalizeHeaderKey(normalized)) {
case "\u5fb7\u56fd", "\u5fb7", "de", "germany", "german", "deutschland" -> "DE";
case "\u82f1\u56fd", "\u82f1", "uk", "gb", "greatbritain", "britain", "unitedkingdom" -> "UK";
case "\u6cd5\u56fd", "\u6cd5", "fr", "france", "french" -> "FR";
case "\u610f\u5927\u5229", "\u610f", "it", "italy", "italian" -> "IT";
case "\u897f\u73ed\u7259", "\u897f", "es", "spain", "spanish", "espana" -> "ES";
case "德国", "", "de", "germany", "german", "deutschland" -> "DE";
case "英国", "", "uk", "gb", "greatbritain", "britain", "unitedkingdom" -> "UK";
case "法国", "", "fr", "france", "french" -> "FR";
case "意大利", "", "it", "italy", "italian" -> "IT";
case "西班牙", "西", "es", "spain", "spanish", "espana" -> "ES";
default -> "";
};
}
@@ -860,11 +844,11 @@ public class QueryAsinService {
if (index != null) {
return index;
}
index = firstHeader("groupname", "\u5206\u7ec4id", "\u5206\u7ec4");
index = firstHeader("groupname", "分组id", "分组");
if (index != null) {
return index;
}
return findHeaderByPredicate(key -> key.contains("\u5206\u7ec4") || key.contains("group"));
return findHeaderByPredicate(key -> key.contains("分组") || key.contains("group"));
}
private Integer resolveShopHeaderIndex() {
@@ -873,13 +857,13 @@ public class QueryAsinService {
return index;
}
index = firstHeader(
"\u5e97\u94fa\u540d", "\u5e97\u94fa\u540d\u79f0", "\u5e97\u94fa\u8d26\u53f7", "\u8d26\u53f7",
"店铺名", "店铺名称", "店铺账号", "账号",
"account", "selleraccount", "storeaccount", "storename");
if (index != null) {
return index;
}
return findHeaderByPredicate(key ->
(key.contains("\u5e97\u94fa") && (key.contains("\u540d") || key.contains("\u8d26\u53f7")))
(key.contains("店铺") && (key.contains("") || key.contains("账号")))
|| (key.contains("shop") && (key.contains("name") || key.contains("account")))
|| key.contains("selleraccount")
|| key.contains("storeaccount"));
@@ -891,32 +875,32 @@ public class QueryAsinService {
return index;
}
return switch (country) {
case "DE" -> firstHeader("\u5fb7\u56fd", "\u5fb7", "\u5fb7\u56fdasin");
case "UK" -> firstHeader("\u82f1\u56fd", "\u82f1", "\u82f1\u56fdasin");
case "FR" -> firstHeader("\u6cd5\u56fd", "\u6cd5", "\u6cd5\u56fdasin");
case "IT" -> firstHeader("\u610f\u5927\u5229", "\u610f", "\u610f\u5927\u5229asin");
case "ES" -> firstHeader("\u897f\u73ed\u7259", "\u897f", "\u897f\u73ed\u7259asin");
case "DE" -> firstHeader("德国", "", "德国asin");
case "UK" -> firstHeader("英国", "", "英国asin");
case "FR" -> firstHeader("法国", "", "法国asin");
case "IT" -> firstHeader("意大利", "", "意大利asin");
case "ES" -> firstHeader("西班牙", "西", "西班牙asin");
default -> null;
};
}
private Integer findSingleCountryIndex() {
Integer index = firstHeader(
"\u4e2d\u6587\u56fd\u5bb6\u540d", "\u56fd\u5bb6", "\u56fd\u5bb6\u540d", "\u56fd\u5bb6\u7ad9\u70b9",
"\u7ad9\u70b9", "country", "countryname", "marketplace", "site");
"中文国家名", "国家", "国家名", "国家站点",
"站点", "country", "countryname", "marketplace", "site");
if (index != null) {
return index;
}
return findHeaderByPredicate(key ->
key.contains("\u56fd\u5bb6")
|| key.contains("\u7ad9\u70b9")
key.contains("国家")
|| key.contains("站点")
|| key.contains("country")
|| key.contains("marketplace")
|| key.equals("site"));
}
private Integer findSingleAsinIndex() {
return firstHeader("asin", "\u67e5\u8be2asin", "\u4ea7\u54c1asin", "\u94fe\u63a5asin");
return firstHeader("asin", "查询asin", "产品asin", "链接asin");
}
private boolean hasWideCountryColumns() {

View File

@@ -48,6 +48,7 @@ public class ShopManageGroupService {
public List<ShopManageGroupItemVo> list(Long createdById) {
return toVoList(groupMapper.selectList(new LambdaQueryWrapper<ShopManageGroupEntity>()
.eq(createdById != null && createdById > 0, ShopManageGroupEntity::getCreatedById, createdById)
.or(createdById != null && createdById > 0, wrapper -> wrapper.eq(ShopManageGroupEntity::getUserId, createdById))
.orderByAsc(ShopManageGroupEntity::getId)));
}
@@ -74,40 +75,44 @@ public class ShopManageGroupService {
.collect(Collectors.toCollection(LinkedHashSet::new));
}
Long normalizedOperatorId = normalizePositiveId(operatorId, "操作人不能为空");
LinkedHashSet<Long> groupIds = groupMapper.selectList(new LambdaQueryWrapper<ShopManageGroupEntity>()
.select(ShopManageGroupEntity::getId)
.eq(ShopManageGroupEntity::getCreatedById, normalizedOperatorId))
return groupMapper.selectAccessibleGroupIds(normalizedOperatorId)
.stream()
.map(ShopManageGroupEntity::getId)
.filter(id -> id != null && id > 0)
.collect(Collectors.toCollection(LinkedHashSet::new));
List<Long> memberGroupIds = groupMemberMapper.selectList(new LambdaQueryWrapper<ShopManageGroupMemberEntity>()
.select(ShopManageGroupMemberEntity::getGroupId)
.eq(ShopManageGroupMemberEntity::getUserId, normalizedOperatorId))
.stream()
.map(ShopManageGroupMemberEntity::getGroupId)
.filter(id -> id != null && id > 0)
.toList();
groupIds.addAll(memberGroupIds);
if (!memberGroupIds.isEmpty()) {
LinkedHashSet<Long> leaderIds = groupMapper.selectList(new LambdaQueryWrapper<ShopManageGroupEntity>()
.select(ShopManageGroupEntity::getCreatedById)
.in(ShopManageGroupEntity::getId, memberGroupIds))
.stream()
.map(ShopManageGroupEntity::getCreatedById)
.filter(id -> id != null && id > 0)
.collect(Collectors.toCollection(LinkedHashSet::new));
if (!leaderIds.isEmpty()) {
groupIds.addAll(groupMapper.selectList(new LambdaQueryWrapper<ShopManageGroupEntity>()
.select(ShopManageGroupEntity::getId)
.in(ShopManageGroupEntity::getCreatedById, leaderIds))
.stream()
.map(ShopManageGroupEntity::getId)
.filter(id -> id != null && id > 0)
.toList());
}
}
public Set<Long> listAccessibleCreatorUserIds(Long operatorId, boolean superAdmin) {
if (superAdmin) {
return Set.of();
}
return groupIds;
Long normalizedOperatorId = normalizePositiveId(operatorId, "操作人不能为空");
return groupMapper.selectAccessibleCreatorUserIds(normalizedOperatorId)
.stream()
.filter(id -> id != null && id > 0)
.collect(Collectors.toCollection(LinkedHashSet::new));
}
public Map<Long, String> buildGroupNameMap(List<Long> groupIds) {
if (groupIds == null || groupIds.isEmpty()) {
return Map.of();
}
List<Long> normalizedGroupIds = groupIds.stream()
.filter(id -> id != null && id > 0)
.distinct()
.toList();
if (normalizedGroupIds.isEmpty()) {
return Map.of();
}
return groupMapper.selectList(new LambdaQueryWrapper<ShopManageGroupEntity>()
.select(ShopManageGroupEntity::getId, ShopManageGroupEntity::getGroupName)
.in(ShopManageGroupEntity::getId, normalizedGroupIds))
.stream()
.filter(group -> group.getId() != null)
.collect(Collectors.toMap(
ShopManageGroupEntity::getId,
group -> normalizeBlank(group.getGroupName()),
(left, right) -> left,
LinkedHashMap::new));
}
@Transactional
@@ -207,8 +212,9 @@ public class ShopManageGroupService {
return;
}
Long normalizedOperatorId = normalizePositiveId(operatorId, "操作人不能为空");
boolean createdBySelf = entity.getCreatedById() != null && entity.getCreatedById().equals(normalizedOperatorId);
if (!createdBySelf) {
boolean leaderBySelf = entity.getCreatedById() != null && entity.getCreatedById().equals(normalizedOperatorId);
boolean legacyLeaderBySelf = entity.getUserId() != null && entity.getUserId().equals(normalizedOperatorId);
if (!leaderBySelf && !legacyLeaderBySelf) {
throw new BusinessException("只有组长才能维护分组");
}
}
@@ -332,8 +338,9 @@ public class ShopManageGroupService {
LinkedHashSet<Long> userIds = new LinkedHashSet<>();
for (ShopManageGroupEntity group : groups) {
if (group.getCreatedById() != null && group.getCreatedById() > 0) {
userIds.add(group.getCreatedById());
Long leaderUserId = resolveGroupLeaderUserId(group);
if (leaderUserId != null && leaderUserId > 0) {
userIds.add(leaderUserId);
}
}
for (List<ShopManageGroupMemberEntity> members : membersByGroupId.values()) {
@@ -355,8 +362,9 @@ public class ShopManageGroupService {
ShopManageGroupItemVo vo = new ShopManageGroupItemVo();
vo.setId(entity.getId());
vo.setGroupName(entity.getGroupName());
vo.setLeaderUserId(entity.getCreatedById());
AdminUserEntity leaderUser = entity.getCreatedById() == null ? null : userById.get(entity.getCreatedById());
Long leaderUserId = resolveGroupLeaderUserId(entity);
vo.setLeaderUserId(leaderUserId);
AdminUserEntity leaderUser = leaderUserId == null ? null : userById.get(leaderUserId);
vo.setLeaderUsername(leaderUser == null ? "" : normalizeBlank(leaderUser.getUsername()));
List<ShopManageGroupMemberEntity> memberEntities = membersByGroupId.getOrDefault(entity.getId(), Collections.emptyList());
@@ -380,4 +388,14 @@ public class ShopManageGroupService {
}
return result;
}
private Long resolveGroupLeaderUserId(ShopManageGroupEntity entity) {
if (entity == null) {
return null;
}
if (entity.getCreatedById() != null && entity.getCreatedById() > 0) {
return entity.getCreatedById();
}
return entity.getUserId();
}
}

View File

@@ -15,7 +15,6 @@ import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -33,6 +32,7 @@ public class ShopManageService {
long safePageSize = Math.min(Math.max(pageSize, 1), 100);
String safeShopName = shopName == null ? "" : shopName.trim();
Set<Long> accessibleGroupIds = superAdmin ? Set.of() : shopManageGroupService.listAccessibleGroupIds(operatorId, false);
Set<Long> accessibleCreatorUserIds = superAdmin ? Set.of() : shopManageGroupService.listAccessibleCreatorUserIds(operatorId, false);
LambdaQueryWrapper<ShopManageEntity> query = new LambdaQueryWrapper<ShopManageEntity>()
.eq(groupId != null && groupId > 0, ShopManageEntity::getGroupId, groupId)
@@ -40,20 +40,30 @@ public class ShopManageService {
.orderByDesc(ShopManageEntity::getId);
if (!superAdmin) {
Long normalizedOperatorId = normalizePositiveId(operatorId, "操作人不能为空");
query.and(wrapper -> {
wrapper.eq(ShopManageEntity::getCreatedById, normalizedOperatorId);
if (!accessibleGroupIds.isEmpty()) {
wrapper.or().in(ShopManageEntity::getGroupId, accessibleGroupIds);
}
});
normalizePositiveId(operatorId, "操作人不能为空");
if (accessibleGroupIds.isEmpty() && accessibleCreatorUserIds.isEmpty()) {
query.eq(ShopManageEntity::getId, -1L);
} else {
query.and(wrapper -> {
boolean hasCreatorFilter = !accessibleCreatorUserIds.isEmpty();
if (hasCreatorFilter) {
wrapper.in(ShopManageEntity::getCreatedById, accessibleCreatorUserIds);
}
if (!accessibleGroupIds.isEmpty()) {
if (hasCreatorFilter) {
wrapper.or();
}
wrapper.in(ShopManageEntity::getGroupId, accessibleGroupIds);
}
});
}
}
Long total = shopManageMapper.selectCount(query);
List<ShopManageEntity> rows = shopManageMapper
.selectList(query.last("LIMIT " + ((safePage - 1) * safePageSize) + ", " + safePageSize));
Map<Long, String> groupNameById = buildGroupNameMap(rows.stream()
Map<Long, String> groupNameById = shopManageGroupService.buildGroupNameMap(rows.stream()
.map(ShopManageEntity::getGroupId)
.filter(id -> id != null && id > 0)
.distinct()
@@ -190,22 +200,6 @@ public class ShopManageService {
}
}
private Map<Long, String> buildGroupNameMap(List<Long> groupIds) {
if (groupIds == null || groupIds.isEmpty()) {
return Map.of();
}
LinkedHashMap<Long, String> map = new LinkedHashMap<>();
for (Long groupId : groupIds) {
try {
ShopManageGroupEntity group = shopManageGroupService.getById(groupId);
map.put(groupId, group.getGroupName());
} catch (Exception ignored) {
map.put(groupId, "");
}
}
return map;
}
private ShopManageItemVo toItemVo(ShopManageEntity entity, String groupName) {
ShopManageItemVo vo = new ShopManageItemVo();
vo.setId(entity.getId());

View File

@@ -62,7 +62,7 @@ public class SkipPriceAsinService {
List<SkipPriceAsinEntity> rows = skipPriceAsinMapper
.selectList(query.last("LIMIT " + ((safePage - 1) * safePageSize) + ", " + safePageSize));
Map<Long, String> groupNameById = buildGroupNameMap(rows.stream()
Map<Long, String> groupNameById = shopManageGroupService.buildGroupNameMap(rows.stream()
.map(SkipPriceAsinEntity::getGroupId)
.filter(id -> id != null && id > 0)
.distinct()
@@ -174,22 +174,6 @@ public class SkipPriceAsinService {
return vo;
}
private Map<Long, String> buildGroupNameMap(List<Long> groupIds) {
if (groupIds == null || groupIds.isEmpty()) {
return Map.of();
}
LinkedHashMap<Long, String> map = new LinkedHashMap<>();
for (Long groupId : groupIds) {
try {
ShopManageGroupEntity group = shopManageGroupService.getById(groupId);
map.put(groupId, group.getGroupName());
} catch (Exception ignored) {
map.put(groupId, "");
}
}
return map;
}
private Set<String> normalizeCountries(List<String> countries) {
LinkedHashSet<String> normalized = new LinkedHashSet<>();
if (countries != null) {

View File

@@ -132,6 +132,21 @@ public class ShopMatchTaskService {
return tasks;
}
private List<FileTaskEntity> selectTaskStatusesByIdsInBatches(List<Long> taskIds) {
List<FileTaskEntity> tasks = new ArrayList<>();
if (taskIds == null || taskIds.isEmpty()) {
return tasks;
}
int batchSize = Math.max(1, taskPressureProperties.getDbSelectBatchSize());
for (int start = 0; start < taskIds.size(); start += batchSize) {
int end = Math.min(start + batchSize, taskIds.size());
tasks.addAll(fileTaskMapper.selectList(new LambdaQueryWrapper<FileTaskEntity>()
.select(FileTaskEntity::getId, FileTaskEntity::getStatus)
.in(FileTaskEntity::getId, taskIds.subList(start, end))));
}
return tasks;
}
public ProductRiskDashboardVo dashboard(Long userId) {
if (userId == null || userId <= 0) {
throw new BusinessException("user_id 不合法");
@@ -174,7 +189,7 @@ public class ShopMatchTaskService {
.distinct()
.toList();
if (!taskIds.isEmpty()) {
for (FileTaskEntity task : selectTasksByIdsInBatches(taskIds)) {
for (FileTaskEntity task : selectTaskStatusesByIdsInBatches(taskIds)) {
if (task != null) {
statusByTaskId.put(task.getId(), task.getStatus());
}
@@ -465,7 +480,6 @@ public class ShopMatchTaskService {
}
@Transactional
public void submitResult(Long taskId, ShopMatchSubmitResultRequest request) {
if (taskId == null || taskId <= 0) {
throw new BusinessException("taskId 不合法");
@@ -540,7 +554,6 @@ public class ShopMatchTaskService {
updateTaskStatusFromLatestRows(task, latest);
}
@Transactional
public boolean tryFinalizeTask(Long taskId, boolean fromCompensation) {
if (taskId == null || taskId <= 0) {
return false;

View File

@@ -456,8 +456,8 @@ public class SplitRunService {
if (value == null) {
return "";
}
return value.replace("\ufeff", "")
.replace("\u3000", " ")
return value.replace(String.valueOf((char) 0xFEFF), "")
.replace((char) 0x3000, ' ')
.replace("\r\n", " ")
.replace("\r", " ")
.replace("\n", " ")

View File

@@ -23,7 +23,6 @@ public class TaskFileJobService {
private final TaskFileJobMapper taskFileJobMapper;
private final ApplicationEventPublisher applicationEventPublisher;
@Transactional
public TaskFileJobEntity enqueueAssembleResult(Long taskId, String moduleType, Long resultId, String scopeKey) {
if (taskId == null || taskId <= 0 || moduleType == null || moduleType.isBlank() || resultId == null || resultId <= 0) {
return null;
@@ -146,7 +145,6 @@ public class TaskFileJobService {
return reset;
}
@Transactional
public boolean markRunning(Long jobId) {
if (jobId == null || jobId <= 0) {
return false;
@@ -158,7 +156,6 @@ public class TaskFileJobService {
.set(TaskFileJobEntity::getUpdatedAt, LocalDateTime.now())) > 0;
}
@Transactional
public void touchRunning(Long jobId) {
if (jobId == null || jobId <= 0) {
return;
@@ -169,7 +166,6 @@ public class TaskFileJobService {
.set(TaskFileJobEntity::getUpdatedAt, LocalDateTime.now()));
}
@Transactional
public void markSuccess(TaskFileJobEntity job, String resultFileUrl) {
taskFileJobMapper.update(null, new LambdaUpdateWrapper<TaskFileJobEntity>()
.eq(TaskFileJobEntity::getId, job.getId())
@@ -180,7 +176,6 @@ public class TaskFileJobService {
.set(TaskFileJobEntity::getFinishedAt, LocalDateTime.now()));
}
@Transactional
public void markFailed(TaskFileJobEntity job, String message) {
int retryCount = job.getRetryCount() == null ? 0 : job.getRetryCount() + 1;
taskFileJobMapper.update(null, new LambdaUpdateWrapper<TaskFileJobEntity>()

View File

@@ -25,7 +25,6 @@ public class TaskResultItemService {
private final ObjectMapper objectMapper;
private final TransientPayloadStorageService transientPayloadStorageService;
@Transactional
public void replaceResultSnapshot(Long taskId, String moduleType, Long resultId, String scopeKey, Object snapshot) {
if (taskId == null || taskId <= 0 || isBlank(moduleType) || resultId == null || resultId <= 0 || snapshot == null) {
return;
@@ -35,7 +34,6 @@ public class TaskResultItemService {
upsert(taskId, moduleType, resultId, normalizedScopeKey, itemKey, null, null, null, snapshot);
}
@Transactional
public void replaceTaskSnapshots(Long taskId, String moduleType, List<? extends Object> snapshots, SnapshotKeyResolver resolver) {
if (taskId == null || taskId <= 0 || isBlank(moduleType) || snapshots == null) {
return;

View File

@@ -25,7 +25,6 @@ public class TaskResultPayloadService {
private final ObjectMapper objectMapper;
private final TransientPayloadStorageService transientPayloadStorageService;
@Transactional
public void saveLatest(Long taskId, String moduleType, String scopeKey, Object payload) {
if (taskId == null || taskId <= 0 || isBlank(moduleType) || isBlank(scopeKey) || payload == null) {
return;

View File

@@ -212,7 +212,7 @@ public boolean isIpWhitelistError(BusinessException ex) {
if (value == null) {
return "";
}
return value.replace("\u3000", " ")
return value.replace((char) 0x3000, ' ')
.trim();
}

View File

@@ -357,7 +357,7 @@ public class ZiniaoShopIndexService {
if (value == null) {
return "";
}
return value.replace("\u3000", " ").trim();
return value.replace((char) 0x3000, ' ').trim();
}
private ZiniaoShopMatchResultVo pendingResult(String message) {

View File

@@ -19,6 +19,10 @@ spring:
maximum-pool-size: ${AIIMAGE_DB_POOL_MAX_SIZE:30}
minimum-idle: ${AIIMAGE_DB_POOL_MIN_IDLE:5}
connection-timeout: ${AIIMAGE_DB_POOL_CONNECTION_TIMEOUT_MS:30000}
validation-timeout: ${AIIMAGE_DB_POOL_VALIDATION_TIMEOUT_MS:5000}
idle-timeout: ${AIIMAGE_DB_POOL_IDLE_TIMEOUT_MS:600000}
max-lifetime: ${AIIMAGE_DB_POOL_MAX_LIFETIME_MS:1500000}
keepalive-time: ${AIIMAGE_DB_POOL_KEEPALIVE_TIME_MS:120000}
leak-detection-threshold: ${AIIMAGE_DB_POOL_LEAK_DETECT_MS:0}
data:
redis:
@@ -54,7 +58,7 @@ mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
springdoc:
api-docs:

View File

@@ -0,0 +1,61 @@
SET @db_name = DATABASE();
SET @idx_exists := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = 'biz_shop_manage'
AND INDEX_NAME = 'idx_group_id_id'
);
SET @sql := IF(@idx_exists = 0,
'ALTER TABLE biz_shop_manage ADD INDEX idx_group_id_id (group_id, id)',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @idx_exists := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = 'biz_shop_manage'
AND INDEX_NAME = 'idx_created_by_id_id'
);
SET @sql := IF(@idx_exists = 0,
'ALTER TABLE biz_shop_manage ADD INDEX idx_created_by_id_id (created_by_id, id)',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @idx_exists := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = 'biz_skip_price_asin'
AND INDEX_NAME = 'idx_group_id_id'
);
SET @sql := IF(@idx_exists = 0,
'ALTER TABLE biz_skip_price_asin ADD INDEX idx_group_id_id (group_id, id)',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @idx_exists := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = 'biz_query_asin'
AND INDEX_NAME = 'idx_group_id_id'
);
SET @sql := IF(@idx_exists = 0,
'ALTER TABLE biz_query_asin ADD INDEX idx_group_id_id (group_id, id)',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

View File

@@ -0,0 +1,31 @@
SET @db_name = DATABASE();
SET @idx_exists := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = 'columns'
AND INDEX_NAME = 'idx_menu_type_sort_id'
);
SET @sql := IF(@idx_exists = 0,
'ALTER TABLE columns ADD INDEX idx_menu_type_sort_id (menu_type, sort_order, id)',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @idx_exists := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = 'user_column_permission'
AND INDEX_NAME = 'idx_user_column'
);
SET @sql := IF(@idx_exists = 0,
'ALTER TABLE user_column_permission ADD INDEX idx_user_column (user_id, column_id)',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

View File

@@ -0,0 +1,31 @@
SET @db_name = DATABASE();
SET @idx_exists := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = 'biz_file_result'
AND INDEX_NAME = 'idx_file_result_task_module_id'
);
SET @sql := IF(@idx_exists = 0,
'ALTER TABLE biz_file_result ADD INDEX idx_file_result_task_module_id (task_id, module_type, id)',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @idx_exists := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = 'biz_task_file_job'
AND INDEX_NAME = 'idx_file_job_status_retry_updated'
);
SET @sql := IF(@idx_exists = 0,
'ALTER TABLE biz_task_file_job ADD INDEX idx_file_job_status_retry_updated (status, retry_count, updated_at)',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;