Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
custom-server
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lizhonghong
custom-server
Commits
bdb8936e
Commit
bdb8936e
authored
Jun 16, 2026
by
Lizh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
调整integrate目录结构,删除无用代码
parent
1c5f75aa
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
270 additions
and
560 deletions
+270
-560
.gitignore
+1
-0
custom-server-app/src/main/java/com/jomalls/custom/app/service/CustomProductWarehouseRelService.java
+0
-90
custom-server-app/src/main/java/com/jomalls/custom/app/service/impl/CustomProductInfoServiceImpl.java
+99
-57
custom-server-app/src/main/java/com/jomalls/custom/app/service/impl/CustomProductWarehouseRelServiceImpl.java
+0
-169
custom-server-app/src/main/java/com/jomalls/custom/app/service/impl/DiyUserServiceImpl.java
+4
-5
custom-server-core/src/main/java/com/jomalls/custom/page/PageAdapter.java
+3
-3
custom-server-domain/src/main/java/com/jomalls/custom/dal/entity/CraftCenterEntity.java
+3
-2
custom-server-domain/src/main/resources/mapper/SysUserMapper.xml
+0
-38
custom-server-integrate/src/main/java/com/jomalls/custom/integrate/configuration/WebClientConfig.java
+1
-1
custom-server-integrate/src/main/java/com/jomalls/custom/integrate/service/SaasAdminService.java
+3
-189
custom-server-integrate/src/main/java/com/jomalls/custom/integrate/service/impl/SaasAdminServiceImpl.java
+150
-0
custom-server-starter/src/main/java/com/jomalls/custom/config/RestResponseBodyConfig.java
+2
-2
custom-server-starter/src/main/resources/application-datasource.properties
+1
-1
custom-server-starter/src/main/resources/application.properties
+2
-2
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/CustomProductInfoController.java
+1
-1
No files found.
.gitignore
View file @
bdb8936e
...
@@ -12,6 +12,7 @@
...
@@ -12,6 +12,7 @@
/logs/
/logs/
.trae/
.trae/
.vscode/
.vscode/
.claude/
CLAUDE.md
CLAUDE.md
docs
docs
custom-server-app/src/main/java/com/jomalls/custom/app/service/CustomProductWarehouseRelService.java
deleted
100644 → 0
View file @
1c5f75aa
package
com
.
jomalls
.
custom
.
app
.
service
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.jomalls.custom.app.vo.CustomProductWarehouseRelPageVO
;
import
com.jomalls.custom.app.vo.CustomProductWarehouseRelVO
;
import
com.jomalls.custom.dal.entity.CustomProductWarehouseRelEntity
;
import
java.util.List
;
/**
* @author Lizh
* @version 0.01
* @description: 接口
* @date 2026-05-29 10:43:29
*/
public
interface
CustomProductWarehouseRelService
{
/**
* 列表查询接口
*
* @param customProductWarehouseRelVO 条件model
* @return list集合
*/
List
<
CustomProductWarehouseRelVO
>
list
(
CustomProductWarehouseRelVO
customProductWarehouseRelVO
);
/**
* 根据条件查询分页列表接口
*
* @param customProductWarehouseRelPageVO 分页入参model
* @return 分页对象
*/
IPage
<
CustomProductWarehouseRelVO
>
pageList
(
CustomProductWarehouseRelPageVO
customProductWarehouseRelPageVO
);
/**
* 根据id查询详情
*
* @param id 主键
* @return 实体model
*/
CustomProductWarehouseRelVO
info
(
Integer
id
);
/**
* 保存对象
*
* @param customProductWarehouseRelVO 保存对象
*/
void
save
(
CustomProductWarehouseRelVO
customProductWarehouseRelVO
);
/**
* 根据id修改对象
*
* @param customProductWarehouseRelVO 修改对象
*/
void
updateById
(
CustomProductWarehouseRelVO
customProductWarehouseRelVO
);
/**
* 根据主键ID进行删除
*
* @param id 主键
*/
void
deleteById
(
Integer
id
);
/**
* 根据仓库ID获取关联列表
*/
List
<
CustomProductWarehouseRelEntity
>
getListByWareHouseId
(
Long
warehouseId
);
/**
* 根据产品ID获取关联列表
*/
List
<
CustomProductWarehouseRelEntity
>
getListByProductId
(
Long
productId
);
/**
* 根据产品ID获取仓库ID列表
*/
List
<
Long
>
getWarehouseIdsByProductId
(
Long
productId
);
/**
* 批量保存产品与仓库的关联
* 逻辑:先删除该产品现有的所有关联,再批量插入新的
*/
void
saveBatch
(
Integer
productId
,
List
<
Long
>
warehouseIds
);
/**
* 根据产品ID删除关联
* 注意:原 TS 代码支持手动传入 transaction,Java 中通常使用 @Transactional 注解管理事务
*/
void
deleteByProductId
(
Integer
productId
);
}
custom-server-app/src/main/java/com/jomalls/custom/app/service/impl/CustomProductInfoServiceImpl.java
View file @
bdb8936e
...
@@ -83,6 +83,12 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -83,6 +83,12 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
/** 并行查询超时时间(秒) */
/** 并行查询超时时间(秒) */
private
static
final
long
QUERY_TIMEOUT_SECONDS
=
30
;
private
static
final
long
QUERY_TIMEOUT_SECONDS
=
30
;
/** 最小列表长度 */
private
static
final
int
MIN_LIST_SIZE
=
1
;
/** 负数 1 */
private
static
final
int
NEGATIVE_ONE
=
-
1
;
@Override
@Override
public
IPage
<
CustomProductInfoPageSnakeVO
>
pageList
(
CustomProductInfoQuerySnakeDTO
param
)
{
public
IPage
<
CustomProductInfoPageSnakeVO
>
pageList
(
CustomProductInfoQuerySnakeDTO
param
)
{
...
@@ -111,8 +117,9 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -111,8 +117,9 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
* @param isErp true=ERP 模式(title 双字段 OR 搜索,processing 支持 2=IS NULL,跳过 DIY/黑名单过滤)
* @param isErp true=ERP 模式(title 双字段 OR 搜索,processing 支持 2=IS NULL,跳过 DIY/黑名单过滤)
*/
*/
private
void
toQueryWrapper
(
CustomProductInfoQuerySnakeDTO
param
,
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
,
boolean
isErp
)
{
private
void
toQueryWrapper
(
CustomProductInfoQuerySnakeDTO
param
,
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
,
boolean
isErp
)
{
// 分类层级过滤
// 分类层级过滤
,获取该分类以及其子类, page查询条件
if
(
param
.
getCategory_id
()
!=
null
)
{
if
(
param
.
getCategory_id
()
!=
null
)
{
// 调用saasAdmin服务,获取所有分类信息
List
<
CategoryInfoModel
>
cateList
=
saasAdminService
.
getAllList
();
List
<
CategoryInfoModel
>
cateList
=
saasAdminService
.
getAllList
();
if
(
CollectionUtils
.
isEmpty
(
cateList
))
{
if
(
CollectionUtils
.
isEmpty
(
cateList
))
{
cateList
=
Collections
.
emptyList
();
cateList
=
Collections
.
emptyList
();
...
@@ -121,9 +128,11 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -121,9 +128,11 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
CategoryInfoModel
cate
=
cateList
.
stream
().
filter
(
c
->
c
.
getId
().
equals
(
param
.
getCategory_id
()))
CategoryInfoModel
cate
=
cateList
.
stream
().
filter
(
c
->
c
.
getId
().
equals
(
param
.
getCategory_id
()))
.
findFirst
().
orElseThrow
(()
->
new
ServiceException
(
"不存在该类别, category_id="
+
param
.
getCategory_id
()));
.
findFirst
().
orElseThrow
(()
->
new
ServiceException
(
"不存在该类别, category_id="
+
param
.
getCategory_id
()));
String
pids
=
String
.
valueOf
(
cate
.
getId
());
String
pids
=
String
.
valueOf
(
cate
.
getId
());
// 获取该类别的父类
if
(
StringUtils
.
isNotBlank
(
cate
.
getPids
()))
{
if
(
StringUtils
.
isNotBlank
(
cate
.
getPids
()))
{
pids
=
cate
.
getPids
()
+
","
+
pids
;
pids
=
cate
.
getPids
()
+
","
+
pids
;
}
}
// 父类id,如: 0,19,26,33
String
finalPids
=
pids
;
String
finalPids
=
pids
;
// 获取该类别及子类别的 ID
// 获取该类别及子类别的 ID
List
<
Integer
>
cateIds
=
cateList
.
stream
()
List
<
Integer
>
cateIds
=
cateList
.
stream
()
...
@@ -136,7 +145,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -136,7 +145,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getCategoryId
,
cateIds
);
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getCategoryId
,
cateIds
);
}
}
// 工厂 ID 过滤(通过 product_factory_rel M2M 表
)
// 工厂 ID 过滤(通过 product_factory_rel M2M 表
,每个工厂可以有不一样的价格), page查询条件
if
(
param
.
getFactory_id
()
!=
null
)
{
if
(
param
.
getFactory_id
()
!=
null
)
{
List
<
Integer
>
factoryProductIds
=
productFactoryRelDomainService
.
list
(
List
<
Integer
>
factoryProductIds
=
productFactoryRelDomainService
.
list
(
new
LambdaQueryWrapper
<
ProductFactoryRelEntity
>()
new
LambdaQueryWrapper
<
ProductFactoryRelEntity
>()
...
@@ -150,13 +159,13 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -150,13 +159,13 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
}
}
}
// DIY 用户过滤与黑名单过滤(仅标准分页使用,ERP权限过滤)
// DIY 用户过滤与黑名单过滤(仅标准分页使用,ERP权限过滤)
, page查询条件, erpPage查询跳过
if
(!
isErp
)
{
if
(!
isErp
)
{
applyDiyAndBlacklistFilter
(
param
,
queryWrapper
);
applyDiyAndBlacklistFilter
(
param
,
queryWrapper
);
queryWrapper
.
orderByDesc
(
CustomProductInfoEntity:
:
getId
);
queryWrapper
.
orderByDesc
(
CustomProductInfoEntity:
:
getId
);
}
}
// 是否九猫处理过滤(0=否 1=是 2=未设置,也支持 true/false)
// 是否九猫处理过滤(0=否 1=是 2=未设置,也支持 true/false)
, page查询条件, erpPage查询跳过
Integer
processing
=
param
.
getProcessing
();
Integer
processing
=
param
.
getProcessing
();
if
(
processing
!=
null
)
{
if
(
processing
!=
null
)
{
if
(
processing
==
ProcessingStatus
.
NOT_SET
.
getCode
())
{
if
(
processing
==
ProcessingStatus
.
NOT_SET
.
getCode
())
{
...
@@ -170,48 +179,51 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -170,48 +179,51 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
if
(
param
.
getId
()
!=
null
)
{
if
(
param
.
getId
()
!=
null
)
{
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getId
,
param
.
getId
());
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getId
,
param
.
getId
());
}
}
// sku 支持逗号分隔多值 IN 查询
// sku 支持逗号分隔多值 IN 查询
, erpPage查询条件 TODO
if
(
StringUtils
.
isNotBlank
(
param
.
getSku
()))
{
if
(
StringUtils
.
isNotBlank
(
param
.
getSku
()))
{
String
[]
skuArr
=
param
.
getSku
().
split
(
","
);
String
[]
skuArr
=
param
.
getSku
().
split
(
","
);
if
(
skuArr
.
length
>
1
)
{
if
(
skuArr
.
length
>
MIN_LIST_SIZE
)
{
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getSku
,
(
Object
[])
skuArr
);
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getSku
,
(
Object
[])
skuArr
);
}
else
{
}
else
{
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getSku
,
param
.
getSku
());
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getSku
,
param
.
getSku
());
}
}
}
}
// 状态过滤(支持逗号分隔多值,对齐 TS status split(","))
// ERP: title 关键词同时搜索 name 和 title 两列, erpPage查询条件
if
(
param
.
getStatusList
()
!=
null
&&
!
param
.
getStatusList
().
isEmpty
())
{
if
(
StringUtils
.
isNotBlank
(
param
.
getTitle
()))
{
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getStatus
,
param
.
getStatusList
());
if
(
isErp
)
{
}
else
if
(
param
.
getStatus
()
!=
null
)
{
queryWrapper
.
and
(
w
->
w
.
like
(
CustomProductInfoEntity:
:
getName
,
param
.
getTitle
())
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getStatus
,
param
.
getStatus
());
.
or
().
like
(
CustomProductInfoEntity:
:
getTitle
,
param
.
getTitle
()));
}
else
{
queryWrapper
.
like
(
CustomProductInfoEntity:
:
getTitle
,
param
.
getTitle
());
}
}
}
// 产品归属(平台共享/客户私有), erpPage查询条件
if
(
StringUtils
.
isNotBlank
(
param
.
getProduct_type
()))
{
if
(
StringUtils
.
isNotBlank
(
param
.
getProduct_type
()))
{
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getProductType
,
param
.
getProduct_type
());
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getProductType
,
param
.
getProduct_type
());
}
}
// 货号:逗号分隔多值 IN 查询,单个值模糊 LIKE 查询
// 货号:逗号分隔多值 IN 查询,单个值模糊 LIKE 查询
, erpPage查询条件 TODO
if
(
StringUtils
.
isNotBlank
(
param
.
getProduct_no
()))
{
if
(
StringUtils
.
isNotBlank
(
param
.
getProduct_no
()))
{
String
[]
productNoArr
=
param
.
getProduct_no
().
split
(
","
);
String
[]
productNoArr
=
param
.
getProduct_no
().
split
(
","
);
if
(
productNoArr
.
length
>
1
)
{
if
(
productNoArr
.
length
>
MIN_LIST_SIZE
)
{
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getProductNo
,
(
Object
[])
productNoArr
);
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getProductNo
,
(
Object
[])
productNoArr
);
}
else
{
}
else
{
queryWrapper
.
like
(
CustomProductInfoEntity:
:
getProductNo
,
param
.
getProduct_no
());
queryWrapper
.
like
(
CustomProductInfoEntity:
:
getProductNo
,
param
.
getProduct_no
());
}
}
}
}
// 状态过滤(支持逗号分隔多值,对齐 TS status split(",")), erpPage查询条件
if
(
CollectionUtils
.
isNotEmpty
(
param
.
getStatusList
()))
{
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getStatus
,
param
.
getStatusList
());
}
else
if
(
param
.
getStatus
()
!=
null
)
{
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getStatus
,
param
.
getStatus
());
}
// 商品类型(局部印/满印), erpPage查询条件
if
(
param
.
getPrint_type
()
!=
null
)
{
if
(
param
.
getPrint_type
()
!=
null
)
{
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getPrintType
,
param
.
getPrint_type
());
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getPrintType
,
param
.
getPrint_type
());
}
}
if
(
StringUtils
.
isNotBlank
(
param
.
getName
()))
{
if
(
StringUtils
.
isNotBlank
(
param
.
getName
()))
{
queryWrapper
.
like
(
CustomProductInfoEntity:
:
getName
,
param
.
getName
());
queryWrapper
.
like
(
CustomProductInfoEntity:
:
getName
,
param
.
getName
());
}
}
// ERP: title 关键词同时搜索 name 和 title 两列
if
(
StringUtils
.
isNotBlank
(
param
.
getTitle
()))
{
if
(
isErp
)
{
queryWrapper
.
and
(
w
->
w
.
like
(
CustomProductInfoEntity:
:
getName
,
param
.
getTitle
())
.
or
().
like
(
CustomProductInfoEntity:
:
getTitle
,
param
.
getTitle
()));
}
else
{
queryWrapper
.
like
(
CustomProductInfoEntity:
:
getTitle
,
param
.
getTitle
());
}
}
// 工厂过滤(factoryIds 直接列 — 用于创建/更新场景,保留兼容)
// 工厂过滤(factoryIds 直接列 — 用于创建/更新场景,保留兼容)
if
(
param
.
getFactoryIds
()
!=
null
)
{
if
(
param
.
getFactoryIds
()
!=
null
)
{
...
@@ -220,18 +232,18 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -220,18 +232,18 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
}
/**
/**
* DIY 用户与黑名单过滤(标准分页专用)
* DIY 用户与黑名单过滤(标准分页专用)
, page查询条件
* <p>
* <p>
* diyUserId 与 blackUserId 互斥(else if),
* diyUserId 与 blackUserId 互斥(else if),
* diyUserId=-1 使用 LEFT JOIN 语义查找无绑定的商品。
* diyUserId=-1 使用 LEFT JOIN 语义查找无绑定的商品。
*/
*/
private
void
applyDiyAndBlacklistFilter
(
CustomProductInfoQuerySnakeDTO
param
,
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
)
{
private
void
applyDiyAndBlacklistFilter
(
CustomProductInfoQuerySnakeDTO
param
,
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
)
{
if
(
param
.
getDiyUserId
()
!=
null
)
{
if
(
param
.
getDiyUserId
()
!=
null
)
{
if
(
param
.
getDiyUserId
()
==
-
1
)
{
if
(
param
.
getDiyUserId
()
==
NEGATIVE_ONE
)
{
// 查找无任何 diy_user 绑定的商品(通过 Domain 层 LEFT JOIN 查询)
// 查找无任何 diy_user 绑定的商品(通过 Domain 层 LEFT JOIN 查询)
List
<
Integer
>
unboundIds
=
customProductInfoDomainService
.
selectIdsWithoutDiyUserBind
();
List
<
Integer
>
unboundIds
=
customProductInfoDomainService
.
selectIdsWithoutDiyUserBind
();
if
(
CollectionUtils
.
isEmpty
(
unboundIds
))
{
if
(
CollectionUtils
.
isEmpty
(
unboundIds
))
{
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getId
,
-
1
);
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getId
,
NEGATIVE_ONE
);
}
else
{
}
else
{
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
unboundIds
);
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
unboundIds
);
}
}
...
@@ -242,7 +254,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -242,7 +254,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
.
stream
().
map
(
CustomProductDiyUserRelEntity:
:
getProductId
)
.
stream
().
map
(
CustomProductDiyUserRelEntity:
:
getProductId
)
.
distinct
().
collect
(
Collectors
.
toList
());
.
distinct
().
collect
(
Collectors
.
toList
());
if
(
CollectionUtils
.
isEmpty
(
productIds
))
{
if
(
CollectionUtils
.
isEmpty
(
productIds
))
{
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getId
,
-
1
);
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getId
,
NEGATIVE_ONE
);
}
else
{
}
else
{
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
productIds
);
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
productIds
);
}
}
...
@@ -255,7 +267,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -255,7 +267,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
.
stream
().
map
(
CustomProductBlacklistEntity:
:
getProductId
)
.
stream
().
map
(
CustomProductBlacklistEntity:
:
getProductId
)
.
distinct
().
collect
(
Collectors
.
toList
());
.
distinct
().
collect
(
Collectors
.
toList
());
if
(
productIds
.
isEmpty
())
{
if
(
productIds
.
isEmpty
())
{
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getId
,
-
1
);
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getId
,
NEGATIVE_ONE
);
}
else
{
}
else
{
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
productIds
);
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
productIds
);
}
}
...
@@ -416,7 +428,11 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -416,7 +428,11 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
return
fullVO
;
return
fullVO
;
}
}
/** 校验并查询商品主表实体 */
/**
* 校验并查询商品主表实体 , getByIdOrSku 接口检查
* @param id 商品 ID
* @param sku 商品 SKU
*/
private
CustomProductInfoEntity
validateAndQueryEntity
(
Integer
id
,
String
sku
)
{
private
CustomProductInfoEntity
validateAndQueryEntity
(
Integer
id
,
String
sku
)
{
CustomProductInfoEntity
entity
;
CustomProductInfoEntity
entity
;
if
(
id
!=
null
)
{
if
(
id
!=
null
)
{
...
@@ -433,7 +449,8 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -433,7 +449,8 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
}
/**
/**
* 并行查询所有子表数据,带超时保护
* 并行查询所有子表数据,带超时保护, getByIdOrSku 接口组装数据
* @param productId 商品 ID
*/
*/
private
ProductRelatedData
queryRelatedDataInParallel
(
Integer
productId
)
{
private
ProductRelatedData
queryRelatedDataInParallel
(
Integer
productId
)
{
CompletableFuture
<
List
<
CustomProductItemEntity
>>
itemsFuture
=
CompletableFuture
.
supplyAsync
(()
->
CompletableFuture
<
List
<
CustomProductItemEntity
>>
itemsFuture
=
CompletableFuture
.
supplyAsync
(()
->
...
@@ -520,7 +537,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -520,7 +537,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
}
/**
/**
* 并行查询结果聚合
* 并行查询结果聚合
, getByIdOrSku 接口组装数据
*/
*/
private
record
ProductRelatedData
(
private
record
ProductRelatedData
(
List
<
CustomProductItemEntity
>
items
,
List
<
CustomProductItemEntity
>
items
,
...
@@ -537,14 +554,14 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -537,14 +554,14 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
/**
/**
* 通过 AdminPropertyService 解析属性名称,填充到 FullVO 的 skuProperties / normalProperties 中
* 通过 AdminPropertyService 解析属性名称,填充到 FullVO 的 skuProperties / normalProperties 中
* <p>
* <p>
* 对齐ts代码,将数据库中存储的 property_id/value_id 转换为带名称的属性列表。
* 对齐ts代码,将数据库中存储的 property_id/value_id 转换为带名称的属性列表。
getByIdOrSku 接口组装数据
*
*
* @param properties 数据库原始属性记录
* @param properties 数据库原始属性记录
* @param fullVO 待填充的商品完整详情
* @param fullVO 待填充的商品完整详情
*/
*/
private
void
resolvePropertyNames
(
List
<
CustomProductInfoPropertyEntity
>
properties
,
private
void
resolvePropertyNames
(
List
<
CustomProductInfoPropertyEntity
>
properties
,
CustomProductInfoSnakeVO
fullVO
)
{
CustomProductInfoSnakeVO
fullVO
)
{
if
(
properties
==
null
||
properties
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
properties
))
{
return
;
return
;
}
}
fullVO
.
setProperties
(
properties
.
stream
().
map
(
e
->
BeanMapper
.
snakeCase
()
fullVO
.
setProperties
(
properties
.
stream
().
map
(
e
->
BeanMapper
.
snakeCase
()
...
@@ -875,20 +892,19 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -875,20 +892,19 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
diyWrapper
.
eq
(
DbDiyEntity:
:
getNamespace
,
param
.
getSource
());
diyWrapper
.
eq
(
DbDiyEntity:
:
getNamespace
,
param
.
getSource
());
}
}
List
<
DbDiyEntity
>
diys
=
dbDiyDomainService
.
list
(
diyWrapper
);
List
<
DbDiyEntity
>
diys
=
dbDiyDomainService
.
list
(
diyWrapper
);
if
(
diys
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
diys
))
{
return
emptyPage
(
param
);
return
emptyPage
(
param
);
}
}
List
<
Integer
>
diyIds
=
diys
.
stream
().
map
(
DbDiyEntity:
:
getId
).
collect
(
Collectors
.
toList
());
List
<
Integer
>
diyIds
=
diys
.
stream
().
map
(
DbDiyEntity:
:
getId
).
collect
(
Collectors
.
toList
());
List
<
ProductTemplateInfoEntity
>
temps
=
productTemplateInfoDomainService
.
selectByDiyIds
(
diyIds
);
List
<
ProductTemplateInfoEntity
>
temps
=
productTemplateInfoDomainService
.
selectByDiyIds
(
diyIds
);
if
(
temps
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
temps
))
{
return
emptyPage
(
param
);
return
emptyPage
(
param
);
}
}
List
<
Integer
>
productIds
=
temps
.
stream
()
List
<
Integer
>
productIds
=
temps
.
stream
()
.
map
(
ProductTemplateInfoEntity:
:
getProductId
)
.
map
(
ProductTemplateInfoEntity:
:
getProductId
)
.
filter
(
Objects:
:
nonNull
)
.
filter
(
Objects:
:
nonNull
)
.
distinct
()
.
distinct
().
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
if
(
CollectionUtils
.
isEmpty
(
productIds
))
{
if
(
productIds
.
isEmpty
())
{
return
emptyPage
(
param
);
return
emptyPage
(
param
);
}
}
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
productIds
);
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
productIds
);
...
@@ -899,14 +915,14 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -899,14 +915,14 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
List
<
CustomWarehouseInfoEntity
>
warehouses
=
customWarehouseInfoDomainService
.
list
(
List
<
CustomWarehouseInfoEntity
>
warehouses
=
customWarehouseInfoDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomWarehouseInfoEntity
>()
new
LambdaQueryWrapper
<
CustomWarehouseInfoEntity
>()
.
eq
(
CustomWarehouseInfoEntity:
:
getCountryCode
,
param
.
getWarehouseCountry
()));
.
eq
(
CustomWarehouseInfoEntity:
:
getCountryCode
,
param
.
getWarehouseCountry
()));
if
(
warehouses
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
warehouses
))
{
return
emptyPage
(
param
);
return
emptyPage
(
param
);
}
}
List
<
Integer
>
wIds
=
warehouses
.
stream
()
List
<
Integer
>
wIds
=
warehouses
.
stream
()
.
map
(
w
->
w
.
getId
().
intValue
())
.
map
(
w
->
w
.
getId
().
intValue
())
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
List
<
CustomProductWarehouseRelEntity
>
rels
=
customProductWarehouseRelDomainService
.
selectByWarehouseIds
(
wIds
);
List
<
CustomProductWarehouseRelEntity
>
rels
=
customProductWarehouseRelDomainService
.
selectByWarehouseIds
(
wIds
);
if
(
rels
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
rels
))
{
return
emptyPage
(
param
);
return
emptyPage
(
param
);
}
}
List
<
Integer
>
productIds
=
rels
.
stream
()
List
<
Integer
>
productIds
=
rels
.
stream
()
...
@@ -917,7 +933,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -917,7 +933,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
// 5. ERP 权限过滤
// 5. ERP 权限过滤
if
(
user
!=
null
)
{
if
(
user
!=
null
)
{
List
<
Integer
>
allowedIds
=
customProductInfoDomainService
.
selectIdsByErpPermission
(
user
.
getId
());
List
<
Integer
>
allowedIds
=
customProductInfoDomainService
.
selectIdsByErpPermission
(
user
.
getId
());
if
(
allowedIds
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
allowedIds
))
{
return
emptyPage
(
param
);
return
emptyPage
(
param
);
}
}
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
allowedIds
);
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
allowedIds
);
...
@@ -931,8 +947,10 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -931,8 +947,10 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
queryWrapper
.
orderByDesc
(
CustomProductInfoEntity:
:
getId
);
queryWrapper
.
orderByDesc
(
CustomProductInfoEntity:
:
getId
);
}
}
}
else
{
}
else
{
// 默认排序需要 sort IS NULL ASC 确保 NULL 排在非 NULL 之后(对齐 TS Sequelize.literal)
// 默认排序:sort 升序(未设置排序的排最后),同值按 id 倒序
queryWrapper
.
last
(
" ORDER BY sort IS NULL ASC, sort ASC, id DESC"
);
// sort 字段在 save/update 时已将 NULL 替换为 SORT_UNSET,无需 sort IS NULL 表达式
queryWrapper
.
orderByAsc
(
CustomProductInfoEntity:
:
getSort
)
.
orderByDesc
(
CustomProductInfoEntity:
:
getId
);
}
}
// 7. 执行分页查询
// 7. 执行分页查询
...
@@ -995,7 +1013,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -995,7 +1013,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
}
/**
/**
* 批量查询 DIY 模板上架状态,返回 diyId → isShelf 映射
* 批量查询 DIY 模板上架状态,返回 diyId → isShelf 映射
,erpPage 接口中使用
* <p>
* <p>
* 使用单次 IN 查询代替 N+1 逐条查询。
* 使用单次 IN 查询代替 N+1 逐条查询。
*/
*/
...
@@ -1005,7 +1023,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -1005,7 +1023,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
.
filter
(
Objects:
:
nonNull
)
.
filter
(
Objects:
:
nonNull
)
.
distinct
()
.
distinct
()
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
if
(
diyIds
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
diyIds
))
{
return
Collections
.
emptyMap
();
return
Collections
.
emptyMap
();
}
}
List
<
DbDiyEntity
>
diys
=
dbDiyDomainService
.
list
(
List
<
DbDiyEntity
>
diys
=
dbDiyDomainService
.
list
(
...
@@ -1021,19 +1039,19 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -1021,19 +1039,19 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
* 批量查询工艺关联(对齐 TS erpPage include: CraftCenter → BelongsToMany → CustomProductCraftRel)
* 批量查询工艺关联(对齐 TS erpPage include: CraftCenter → BelongsToMany → CustomProductCraftRel)
* <p>
* <p>
* 每个 craft VO 嵌套一份 CustomProductCraftRel 数据(product_id + craft_id),
* 每个 craft VO 嵌套一份 CustomProductCraftRel 数据(product_id + craft_id),
* 对齐 TS Sequelize BelongsToMany 自动包含的 junction 表数据
。
* 对齐 TS Sequelize BelongsToMany 自动包含的 junction 表数据
,erpPage 接口中使用
*
*
* @return productId → List<CraftCenterSnakeVO>
* @return productId → List<CraftCenterSnakeVO>
*/
*/
private
Map
<
Integer
,
List
<
CraftCenterSnakeVO
>>
batchLoadCraftsByProductIds
(
List
<
Integer
>
productIds
)
{
private
Map
<
Integer
,
List
<
CraftCenterSnakeVO
>>
batchLoadCraftsByProductIds
(
List
<
Integer
>
productIds
)
{
if
(
productIds
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
productIds
))
{
return
Collections
.
emptyMap
();
return
Collections
.
emptyMap
();
}
}
// 1. 关联表
// 1. 关联表
List
<
CustomProductCraftRelEntity
>
rels
=
customProductCraftRelDomainService
.
list
(
List
<
CustomProductCraftRelEntity
>
rels
=
customProductCraftRelDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomProductCraftRelEntity
>()
new
LambdaQueryWrapper
<
CustomProductCraftRelEntity
>()
.
in
(
CustomProductCraftRelEntity:
:
getProductId
,
productIds
));
.
in
(
CustomProductCraftRelEntity:
:
getProductId
,
productIds
));
if
(
rels
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
rels
))
{
return
Collections
.
emptyMap
();
return
Collections
.
emptyMap
();
}
}
// 2. 工艺实体
// 2. 工艺实体
...
@@ -1061,18 +1079,20 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -1061,18 +1079,20 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
/**
/**
* 批量查询仓库关联(对齐 TS erpPage include: CustomWarehouseInfo → BelongsToMany → CustomProductWarehouseRel)
* 批量查询仓库关联(对齐 TS erpPage include: CustomWarehouseInfo → BelongsToMany → CustomProductWarehouseRel)
* <p>
* erpPage 接口中使用
*
*
* @return productId → List
<CustomWarehouseInfoSnakeVO>
* @return productId → List
<CustomWarehouseInfoSnakeVO>
*/
*/
private
Map
<
Integer
,
List
<
CustomWarehouseInfoSnakeVO
>>
batchLoadWarehousesByProductIds
(
List
<
Integer
>
productIds
)
{
private
Map
<
Integer
,
List
<
CustomWarehouseInfoSnakeVO
>>
batchLoadWarehousesByProductIds
(
List
<
Integer
>
productIds
)
{
if
(
productIds
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
productIds
))
{
return
Collections
.
emptyMap
();
return
Collections
.
emptyMap
();
}
}
// 1. 关联表
// 1. 关联表
List
<
CustomProductWarehouseRelEntity
>
rels
=
customProductWarehouseRelDomainService
.
list
(
List
<
CustomProductWarehouseRelEntity
>
rels
=
customProductWarehouseRelDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomProductWarehouseRelEntity
>()
new
LambdaQueryWrapper
<
CustomProductWarehouseRelEntity
>()
.
in
(
CustomProductWarehouseRelEntity:
:
getProductId
,
productIds
));
.
in
(
CustomProductWarehouseRelEntity:
:
getProductId
,
productIds
));
if
(
rels
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
rels
))
{
return
Collections
.
emptyMap
();
return
Collections
.
emptyMap
();
}
}
// 2. 仓库实体
// 2. 仓库实体
...
@@ -1099,17 +1119,18 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -1099,17 +1119,18 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
/**
/**
* 批量查询工厂价格区间关联(对齐 TS erpPage include: CustomProductFactoryPriceIntervalRel → HasMany)
* 批量查询工厂价格区间关联(对齐 TS erpPage include: CustomProductFactoryPriceIntervalRel → HasMany)
*
* <p>
* @return productId → List<FactoryPriceIntervalRelSnakeVO>
* erpPage 接口中使用
* @return productId → List<FactoryPriceIntervalRelSnakeVO>
*/
*/
private
Map
<
Integer
,
List
<
FactoryPriceIntervalRelSnakeVO
>>
batchLoadFactoryPriceIntervalsByProductIds
(
List
<
Integer
>
productIds
)
{
private
Map
<
Integer
,
List
<
FactoryPriceIntervalRelSnakeVO
>>
batchLoadFactoryPriceIntervalsByProductIds
(
List
<
Integer
>
productIds
)
{
if
(
productIds
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
productIds
))
{
return
Collections
.
emptyMap
();
return
Collections
.
emptyMap
();
}
}
List
<
CustomProductFactoryPriceIntervalRelEntity
>
rels
=
customProductFactoryPriceIntervalRelDomainService
.
list
(
List
<
CustomProductFactoryPriceIntervalRelEntity
>
rels
=
customProductFactoryPriceIntervalRelDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomProductFactoryPriceIntervalRelEntity
>()
new
LambdaQueryWrapper
<
CustomProductFactoryPriceIntervalRelEntity
>()
.
in
(
CustomProductFactoryPriceIntervalRelEntity:
:
getProductId
,
productIds
));
.
in
(
CustomProductFactoryPriceIntervalRelEntity:
:
getProductId
,
productIds
));
if
(
rels
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
rels
))
{
return
Collections
.
emptyMap
();
return
Collections
.
emptyMap
();
}
}
List
<
FactoryPriceIntervalRelSnakeVO
>
voList
=
rels
.
stream
().
map
(
r
->
{
List
<
FactoryPriceIntervalRelSnakeVO
>
voList
=
rels
.
stream
().
map
(
r
->
{
...
@@ -1128,7 +1149,21 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -1128,7 +1149,21 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
/**
/**
* 从事务外的子项列表中计算主表的 factory_price / sales_price / sales_price_max
* 从事务外的子项列表中计算主表的 factory_price / sales_price / sales_price_max
* <p>
* <p>
* factory_price 取子项中的最小值,sales_price 取子项中的最大值,sales_price_max 取子项中的最大值。
* factory_price 取子项中的最大值,sales_price 取子项中的最大值,sales_price_max 取子项中的最大值。
* <p>
* 参考TS 代码如下:
* if (productInfo.factory_price == null || new Decimal(productInfo.factory_price).lessThan(new Decimal(item.factory_price))) {
* productInfo.factory_price = item.factory_price;
* }
* if (productInfo.sales_price == null || new Decimal(productInfo.sales_price).lessThan(new Decimal(item.sales_price))) {
* productInfo.sales_price = item.sales_price;
* }
* if (productInfo.sales_price_max == null || new Decimal(productInfo.sales_price_max).greaterThan(new Decimal(item.sales_price))) {
* productInfo.sales_price_max = item.sales_price;
* }
*
* saveFull 批量保存时使用
*
*/
*/
private
void
computeProductPricesFromItems
(
CustomProductInfoSaveSnakeDTO
dto
)
{
private
void
computeProductPricesFromItems
(
CustomProductInfoSaveSnakeDTO
dto
)
{
if
(
dto
.
getProductList
()
==
null
||
dto
.
getProductList
().
isEmpty
())
{
if
(
dto
.
getProductList
()
==
null
||
dto
.
getProductList
().
isEmpty
())
{
...
@@ -1171,6 +1206,8 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -1171,6 +1206,8 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
* <p>
* <p>
* SaveDTO 使用驼峰命名,与 Entity 字段名一致,直接用默认 mapper 转换。
* SaveDTO 使用驼峰命名,与 Entity 字段名一致,直接用默认 mapper 转换。
* 对于蛇形命名的 {@link CustomProductInfoSaveSnakeDTO},调用方需先用 {@code BeanMapper.snakeCase()} 转为 SaveDTO。
* 对于蛇形命名的 {@link CustomProductInfoSaveSnakeDTO},调用方需先用 {@code BeanMapper.snakeCase()} 转为 SaveDTO。
* <p>
* saveFull 批量保存时使用
*
*
* @param dto 保存 DTO(驼峰命名)
* @param dto 保存 DTO(驼峰命名)
* @param sku 生成的 SKU(创建时传入,更新时传 null)
* @param sku 生成的 SKU(创建时传入,更新时传 null)
...
@@ -1188,6 +1225,8 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -1188,6 +1225,8 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
* 逐条保存子项并返回原始 SKU → 已保存实体的映射
* 逐条保存子项并返回原始 SKU → 已保存实体的映射
* <p>
* <p>
* 逐条保存是为了获取每条记录的自增 ID,供后续工厂价格关联的 item_id 填充使用。
* 逐条保存是为了获取每条记录的自增 ID,供后续工厂价格关联的 item_id 填充使用。
* <p>
* saveFull 批量保存时使用
*
*
* @return Map<原始DTO中的SKU, 已保存的实体(含自增ID和替换后的SKU)>
* @return Map<原始DTO中的SKU, 已保存的实体(含自增ID和替换后的SKU)>
*/
*/
...
@@ -1222,6 +1261,9 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -1222,6 +1261,9 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
* 保存工厂价格关联(利用 itemMap 替换 item_sku 为生成的 SKU 并填充 item_id)
* 保存工厂价格关联(利用 itemMap 替换 item_sku 为生成的 SKU 并填充 item_id)
* <p>
* <p>
* 对齐 TS {@code save}
* 对齐 TS {@code save}
* <p>
* saveFull 批量保存时使用
*
*/
*/
private
void
saveFactoryPriceRels
(
List
<
FactoryPriceRelSnakeDTO
>
factoryPriceList
,
private
void
saveFactoryPriceRels
(
List
<
FactoryPriceRelSnakeDTO
>
factoryPriceList
,
Integer
productId
,
Integer
productId
,
...
@@ -1669,7 +1711,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -1669,7 +1711,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
}
/**
/**
* 重建关联关系(先删后插)
* 重建关联关系(先删后插)
,update接口使用
*/
*/
private
void
rebuildRels
(
List
<
Integer
>
factoryIds
,
List
<
Integer
>
warehouseIds
,
private
void
rebuildRels
(
List
<
Integer
>
factoryIds
,
List
<
Integer
>
warehouseIds
,
List
<
Integer
>
craftIds
,
List
<
Integer
>
diyUserIds
,
List
<
Integer
>
craftIds
,
List
<
Integer
>
diyUserIds
,
...
@@ -1750,7 +1792,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
...
@@ -1750,7 +1792,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
}
/**
/**
* 将并行查询结果组装为 FullVO
* 将并行查询结果组装为 FullVO
, getByIdOrSku接口使用
*/
*/
private
CustomProductInfoSnakeVO
buildProductFullVO
(
CustomProductInfoEntity
entity
,
private
CustomProductInfoSnakeVO
buildProductFullVO
(
CustomProductInfoEntity
entity
,
List
<
CustomProductItemEntity
>
items
,
List
<
CustomProductItemEntity
>
items
,
...
...
custom-server-app/src/main/java/com/jomalls/custom/app/service/impl/CustomProductWarehouseRelServiceImpl.java
deleted
100644 → 0
View file @
1c5f75aa
package
com
.
jomalls
.
custom
.
app
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.core.toolkit.CollectionUtils
;
import
com.jomalls.custom.app.exception.ServiceException
;
import
com.jomalls.custom.app.vo.CustomProductWarehouseRelPageVO
;
import
com.jomalls.custom.app.vo.CustomProductWarehouseRelVO
;
import
com.jomalls.custom.app.service.CustomProductWarehouseRelService
;
import
com.jomalls.custom.app.utils.BeanMapper
;
import
com.jomalls.custom.app.utils.CustomAsserts
;
import
com.jomalls.custom.dal.entity.CustomProductWarehouseRelEntity
;
import
com.jomalls.custom.domain.service.CustomProductWarehouseRelDomainService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.dao.DuplicateKeyException
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.stream.Collectors
;
/**
* @author Lizh
* @version 0.01
* @description: 接口实现
* @date 2026-05-29 10:43:29
*/
@Slf4j
@Service
public
class
CustomProductWarehouseRelServiceImpl
implements
CustomProductWarehouseRelService
{
private
final
CustomProductWarehouseRelDomainService
customProductWarehouseRelDomainService
;
@Autowired
public
CustomProductWarehouseRelServiceImpl
(
CustomProductWarehouseRelDomainService
customProductWarehouseRelDomainService
)
{
this
.
customProductWarehouseRelDomainService
=
customProductWarehouseRelDomainService
;
}
@Override
public
List
<
CustomProductWarehouseRelVO
>
list
(
CustomProductWarehouseRelVO
customProductWarehouseRelVO
)
{
QueryWrapper
<
CustomProductWarehouseRelEntity
>
queryWrapper
=
new
QueryWrapper
<>();
// TODO 根据业务条件组装入参
List
<
CustomProductWarehouseRelEntity
>
list
=
customProductWarehouseRelDomainService
.
list
(
queryWrapper
);
return
list
.
stream
().
map
(
e
->
BeanMapper
.
mapper
().
convert
(
e
,
CustomProductWarehouseRelVO
.
class
)).
collect
(
Collectors
.
toList
());
}
@Override
public
IPage
<
CustomProductWarehouseRelVO
>
pageList
(
CustomProductWarehouseRelPageVO
customProductWarehouseRelPageVO
)
{
CustomAsserts
.
nonNull
(
customProductWarehouseRelPageVO
,
"分页查询参数不能为空"
);
QueryWrapper
<
CustomProductWarehouseRelEntity
>
queryWrapper
=
new
QueryWrapper
<>();
// TODO 根据业务条件组装入参
IPage
<
CustomProductWarehouseRelEntity
>
page
=
customProductWarehouseRelDomainService
.
selectPage
(
queryWrapper
,
customProductWarehouseRelPageVO
);
return
page
.
convert
(
e
->
BeanMapper
.
mapper
().
convert
(
e
,
CustomProductWarehouseRelVO
.
class
));
}
@Override
public
CustomProductWarehouseRelVO
info
(
Integer
id
)
{
CustomAsserts
.
nonNull
(
id
,
"主键id不能为空"
);
CustomProductWarehouseRelEntity
customProductWarehouseRel
=
customProductWarehouseRelDomainService
.
getById
(
id
);
return
BeanMapper
.
mapper
().
convert
(
customProductWarehouseRel
,
CustomProductWarehouseRelVO
.
class
);
}
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Override
public
void
save
(
CustomProductWarehouseRelVO
customProductWarehouseRelVO
)
{
CustomAsserts
.
nonNull
(
customProductWarehouseRelVO
,
"实体对象不能为空"
);
CustomProductWarehouseRelEntity
customProductWarehouseRelEntity
=
BeanMapper
.
mapper
().
convert
(
customProductWarehouseRelVO
,
CustomProductWarehouseRelEntity
.
class
);
try
{
customProductWarehouseRelDomainService
.
save
(
customProductWarehouseRelEntity
);
}
catch
(
DuplicateKeyException
e
)
{
log
.
info
(
"[ CustomProductWarehouseRelServiceImpl save ] 实体对象唯一约束重复,请调整后再试!"
,
e
);
throw
new
ServiceException
(
"实体对象唯一约束重复,请调整后再试!"
);
}
}
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Override
public
void
updateById
(
CustomProductWarehouseRelVO
customProductWarehouseRelVO
)
{
CustomAsserts
.
nonNull
(
customProductWarehouseRelVO
,
"实体对象不能为空"
);
CustomProductWarehouseRelEntity
customProductWarehouseRel
=
BeanMapper
.
mapper
().
convert
(
customProductWarehouseRelVO
,
CustomProductWarehouseRelEntity
.
class
);
try
{
customProductWarehouseRelDomainService
.
updateById
(
customProductWarehouseRel
);
}
catch
(
DuplicateKeyException
e
)
{
log
.
info
(
"[ CustomProductWarehouseRelServiceImpl updateById ] 实体对象唯一约束重复,请调整后再试!"
,
e
);
throw
new
ServiceException
(
"实体对象唯一约束重复,请调整后再试!"
);
}
}
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Override
public
void
deleteById
(
Integer
id
)
{
CustomAsserts
.
nonNull
(
id
,
"主键id不能为空"
);
customProductWarehouseRelDomainService
.
removeById
(
id
);
}
/**
* 根据仓库ID获取关联列表
*/
@Override
public
List
<
CustomProductWarehouseRelEntity
>
getListByWareHouseId
(
Long
warehouseId
)
{
return
customProductWarehouseRelDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomProductWarehouseRelEntity
>()
.
eq
(
CustomProductWarehouseRelEntity:
:
getWarehouseId
,
warehouseId
));
}
/**
* 根据产品ID获取关联列表
*/
@Override
public
List
<
CustomProductWarehouseRelEntity
>
getListByProductId
(
Long
productId
)
{
return
customProductWarehouseRelDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomProductWarehouseRelEntity
>()
.
eq
(
CustomProductWarehouseRelEntity:
:
getProductId
,
productId
));
}
/**
* 根据产品ID获取仓库ID列表
*/
@Override
public
List
<
Long
>
getWarehouseIdsByProductId
(
Long
productId
)
{
List
<
CustomProductWarehouseRelEntity
>
rels
=
customProductWarehouseRelDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomProductWarehouseRelEntity
>()
.
eq
(
CustomProductWarehouseRelEntity:
:
getProductId
,
productId
)
.
select
(
CustomProductWarehouseRelEntity:
:
getWarehouseId
));
// 只查询需要的字段以提高性能
if
(
CollectionUtils
.
isEmpty
(
rels
))
{
return
null
;
}
return
rels
.
stream
()
.
map
(
CustomProductWarehouseRelEntity:
:
getWarehouseId
)
.
collect
(
Collectors
.
toList
());
}
/**
* 根据产品ID删除关联
* 注意:原 TS 代码支持手动传入 transaction,Java 中通常使用 @Transactional 注解管理事务
*/
@Override
public
void
deleteByProductId
(
Integer
productId
)
{
customProductWarehouseRelDomainService
.
remove
(
new
LambdaQueryWrapper
<
CustomProductWarehouseRelEntity
>()
.
eq
(
CustomProductWarehouseRelEntity:
:
getProductId
,
productId
));
}
/**
* 批量保存产品与仓库的关联
* 逻辑:先删除该产品现有的所有关联,再批量插入新的
*/
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
void
saveBatch
(
Integer
productId
,
List
<
Long
>
warehouseIds
)
{
this
.
deleteByProductId
(
productId
);
if
(
CollectionUtils
.
isEmpty
(
warehouseIds
))
{
return
;
}
List
<
CustomProductWarehouseRelEntity
>
relList
=
new
ArrayList
<>();
for
(
Long
warehouseId
:
warehouseIds
)
{
CustomProductWarehouseRelEntity
rel
=
new
CustomProductWarehouseRelEntity
();
rel
.
setProductId
(
productId
);
rel
.
setWarehouseId
(
warehouseId
);
relList
.
add
(
rel
);
}
customProductWarehouseRelDomainService
.
saveBatch
(
relList
);
}
}
custom-server-app/src/main/java/com/jomalls/custom/app/service/impl/DiyUserServiceImpl.java
View file @
bdb8936e
...
@@ -42,15 +42,14 @@ public class DiyUserServiceImpl implements DiyUserService {
...
@@ -42,15 +42,14 @@ public class DiyUserServiceImpl implements DiyUserService {
if
(
StringUtils
.
isBlank
(
namespace
))
{
if
(
StringUtils
.
isBlank
(
namespace
))
{
return
null
;
return
null
;
}
}
DbDiyUserEntity
user
=
dbDiyUserDomainService
.
getByNamespace
(
namespace
);
return
dbDiyUserDomainService
.
getByNamespace
(
namespace
);
if
(
user
==
null
)
{
throw
new
ServiceException
(
"用户不存在, namespace="
+
namespace
);
}
return
user
;
}
}
@Override
@Override
public
DbDiyUserEntity
getByUserMark
(
String
userMark
)
{
public
DbDiyUserEntity
getByUserMark
(
String
userMark
)
{
if
(
StringUtils
.
isBlank
(
userMark
))
{
return
null
;
}
return
dbDiyUserDomainService
.
getByUserMark
(
userMark
);
return
dbDiyUserDomainService
.
getByUserMark
(
userMark
);
}
}
...
...
custom-server-core/src/main/java/com/jomalls/custom/page/PageAdapt
t
er.java
→
custom-server-core/src/main/java/com/jomalls/custom/page/PageAdapter.java
View file @
bdb8936e
...
@@ -24,7 +24,7 @@ import java.util.List;
...
@@ -24,7 +24,7 @@ import java.util.List;
*/
*/
@Getter
@Getter
@AllArgsConstructor
@AllArgsConstructor
public
class
PageAdapt
t
er
<
T
>
implements
Serializable
{
public
class
PageAdapter
<
T
>
implements
Serializable
{
@Serial
@Serial
private
static
final
long
serialVersionUID
=
1L
;
private
static
final
long
serialVersionUID
=
1L
;
...
@@ -51,8 +51,8 @@ public class PageAdaptter<T> implements Serializable {
...
@@ -51,8 +51,8 @@ public class PageAdaptter<T> implements Serializable {
* @param <T> 数据类型
* @param <T> 数据类型
* @return 老服务格式的分页结果
* @return 老服务格式的分页结果
*/
*/
public
static
<
T
>
PageAdapt
t
er
<
T
>
from
(
IPage
<
T
>
page
)
{
public
static
<
T
>
PageAdapter
<
T
>
from
(
IPage
<
T
>
page
)
{
return
new
PageAdapt
t
er
<>(
return
new
PageAdapter
<>(
page
.
getRecords
(),
page
.
getRecords
(),
page
.
getCurrent
(),
page
.
getCurrent
(),
page
.
getTotal
(),
page
.
getTotal
(),
...
...
custom-server-domain/src/main/java/com/jomalls/custom/dal/entity/CraftCenterEntity.java
View file @
bdb8936e
...
@@ -8,6 +8,7 @@ import lombok.Data;
...
@@ -8,6 +8,7 @@ import lombok.Data;
import
java.io.Serial
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.io.Serializable
;
import
java.math.BigDecimal
;
import
java.util.Date
;
import
java.util.Date
;
/**
/**
...
@@ -50,11 +51,11 @@ public class CraftCenterEntity implements Serializable {
...
@@ -50,11 +51,11 @@ public class CraftCenterEntity implements Serializable {
/** 工艺成本 */
/** 工艺成本 */
@TableField
(
"craft_cost"
)
@TableField
(
"craft_cost"
)
private
String
craftCost
;
private
BigDecimal
craftCost
;
/** 其他面的价格 */
/** 其他面的价格 */
@TableField
(
"other_side_cost"
)
@TableField
(
"other_side_cost"
)
private
String
otherSideCost
;
private
BigDecimal
otherSideCost
;
/** 是否启用(1启用,0未启用) */
/** 是否启用(1启用,0未启用) */
@TableField
(
"craft_enable"
)
@TableField
(
"craft_enable"
)
...
...
custom-server-domain/src/main/resources/mapper/SysUserMapper.xml
View file @
bdb8936e
...
@@ -33,44 +33,6 @@
...
@@ -33,44 +33,6 @@
create_by, create_time, update_by, update_time, remark
create_by, create_time, update_by, update_time, remark
</sql>
</sql>
<!-- 根据用户名查询用户 -->
<select
id=
"selectByUsername"
resultMap=
"sysUserMap"
>
SELECT
<include
refid=
"tableColumns"
/>
FROM sys_user
WHERE user_name = #{userName}
AND status = '0'
AND del_flag = '0'
</select>
<!-- 根据邮箱查询用户 -->
<select
id=
"selectByEmail"
resultMap=
"sysUserMap"
>
SELECT
<include
refid=
"tableColumns"
/>
FROM sys_user
WHERE email = #{email}
AND status = '0'
AND del_flag = '0'
</select>
<!-- 分页查询用户列表 -->
<select
id=
"selectUserPage"
resultMap=
"sysUserMap"
>
SELECT
<include
refid=
"tableColumns"
/>
FROM sys_user
WHERE del_flag = '0'
<if
test=
"status != null"
>
AND status = #{status}
</if>
ORDER BY create_time DESC
</select>
<!-- 查询所有启用状态的用户 -->
<select
id=
"selectAllActiveUsers"
resultMap=
"sysUserMap"
>
SELECT
<include
refid=
"tableColumns"
/>
FROM sys_user
WHERE status = '0'
AND del_flag = '0'
ORDER BY create_time DESC
</select>
<!-- 批量插入 -->
<!-- 批量插入 -->
<insert
id=
"insertBatchSomeColumn"
>
<insert
id=
"insertBatchSomeColumn"
>
INSERT INTO sys_user (user_name, nick_name, user_type,
INSERT INTO sys_user (user_name, nick_name, user_type,
...
...
custom-server-integrate/src/main/java/com/jomalls/custom/integrate/configuration/WebClientConfig.java
View file @
bdb8936e
...
@@ -44,7 +44,7 @@ public class WebClientConfig {
...
@@ -44,7 +44,7 @@ public class WebClientConfig {
public
ConnectionProvider
connectionProvider
()
{
public
ConnectionProvider
connectionProvider
()
{
return
ConnectionProvider
.
builder
(
"custom-server-http-pool"
)
return
ConnectionProvider
.
builder
(
"custom-server-http-pool"
)
.
maxConnections
(
poolMaxConnections
)
.
maxConnections
(
poolMaxConnections
)
.
pendingAcquireMaxCount
(
-
1
)
.
pendingAcquireMaxCount
(
100
)
.
pendingAcquireTimeout
(
Duration
.
ofMillis
(
poolAcquireTimeout
))
.
pendingAcquireTimeout
(
Duration
.
ofMillis
(
poolAcquireTimeout
))
.
maxIdleTime
(
Duration
.
ofSeconds
(
60
))
.
maxIdleTime
(
Duration
.
ofSeconds
(
60
))
.
maxLifeTime
(
Duration
.
ofMinutes
(
5
))
.
maxLifeTime
(
Duration
.
ofMinutes
(
5
))
...
...
custom-server-integrate/src/main/java/com/jomalls/custom/integrate/service/SaasAdminService.java
View file @
bdb8936e
...
@@ -27,44 +27,10 @@ import java.util.concurrent.atomic.AtomicReference;
...
@@ -27,44 +27,10 @@ import java.util.concurrent.atomic.AtomicReference;
* 调用 admin API 获取商品分类数据。
* 调用 admin API 获取商品分类数据。
* 对齐 TS 项目 {@code baseCategoryInfoService}。
* 对齐 TS 项目 {@code baseCategoryInfoService}。
*
*
* @author zhengcunwen
* @author Lizh (Java 迁移)
* @author Lizh (Java 迁移)
* @since 2019-09-02
* @since 2019-09-02
*/
*/
@Slf4j
public
interface
SaasAdminService
{
@Service
@RequiredArgsConstructor
public
class
SaasAdminService
{
private
static
final
String
GET_TREE_URL
=
"/api/manage/rest/baseCategoryInfo/tree_list"
;
private
static
final
String
GET_BY_IDS_URL
=
"/api/manage/rest/baseCategoryInfo/getDataByIds"
;
private
static
final
String
GET_BY_ID_URL
=
"/api/manage/rest/baseCategoryInfo/get"
;
private
static
final
String
GET_ALL_LIST_URL
=
"/api/manage/rest/baseCategoryInfo/all_list"
;
private
static
final
String
GET_PROPERTY_BY_IDS_URL
=
"/api/manage/rest/baseProperty/getByIds"
;
private
static
final
int
DEFAULT_MAP_SIZE
=
2
;
/** 分类列表缓存 TTL(毫秒):5 分钟 */
private
static
final
long
CACHE_TTL_MS
=
5
*
60
*
1000
;
private
final
RemoteApiClient
remoteApiClient
;
/** 分类列表本地缓存 */
private
final
AtomicReference
<
CacheEntry
<
List
<
CategoryInfoModel
>>>
categoryCache
=
new
AtomicReference
<>();
@Value
(
"${server.admin.base-url:https://admin.jomalls.com}"
)
private
String
adminBaseUrl
;
private
Map
<
String
,
String
>
getHeader
()
{
Map
<
String
,
String
>
headers
=
new
HashMap
<>(
DEFAULT_MAP_SIZE
);
headers
.
put
(
"Content-Type"
,
"application/json"
);
LoginUser
loginUser
=
SecurityUtils
.
getLoginUser
();
if
(
loginUser
==
null
)
{
return
headers
;
}
headers
.
put
(
"jwt-token"
,
loginUser
.
getToken
());
return
headers
;
}
/**
/**
* 根据属性 ID 列表批量查询属性(含属性值列表)
* 根据属性 ID 列表批量查询属性(含属性值列表)
...
@@ -74,115 +40,7 @@ public class SaasAdminService {
...
@@ -74,115 +40,7 @@ public class SaasAdminService {
* @param ids 属性 ID,逗号分隔(如 "1,2,3")
* @param ids 属性 ID,逗号分隔(如 "1,2,3")
* @return 属性列表,包含 valueList 和 skuProperty 等字段
* @return 属性列表,包含 valueList 和 skuProperty 等字段
*/
*/
public
List
<
PropertyModel
>
getPropertyByIds
(
String
ids
)
{
List
<
PropertyModel
>
getPropertyByIds
(
String
ids
);
if
(!
StringUtils
.
hasText
(
ids
))
{
return
Collections
.
emptyList
();
}
try
{
String
url
=
adminBaseUrl
+
GET_PROPERTY_BY_IDS_URL
+
"?ids="
+
ids
;
ResponseEntity
<
SaasAdminApiResponseModel
<
List
<
PropertyModel
>>>
response
=
remoteApiClient
.
get
(
url
,
new
ParameterizedTypeReference
<>()
{},
getHeader
());
if
(
response
!=
null
&&
response
.
getBody
()
!=
null
)
{
log
.
debug
(
"[ SaasAdminService ] getByIds 成功, ids={}, 返回: {}"
,
ids
,
response
.
toString
());
SaasAdminApiResponseModel
<
List
<
PropertyModel
>>
responseBody
=
response
.
getBody
();
if
(
responseBody
.
getCode
()
==
CodeEnum
.
SUCCESS
.
getCode
())
{
return
responseBody
.
getData
();
}
}
log
.
warn
(
"[ SaasAdminService ] getByIds 返回空, ids={}"
,
ids
);
return
Collections
.
emptyList
();
}
catch
(
Exception
e
)
{
log
.
error
(
"[ SaasAdminService ] getByIds 调用失败, ids={}"
,
ids
,
e
);
return
Collections
.
emptyList
();
}
}
/**
* 获取分类树
* <p>
* 对齐 TS {@code getTree()}
*/
public
List
<
CategoryInfoModel
>
getTree
()
{
try
{
ResponseEntity
<
List
<
CategoryInfoModel
>>
response
=
remoteApiClient
.
get
(
adminBaseUrl
+
GET_TREE_URL
,
new
ParameterizedTypeReference
<>()
{},
getHeader
());
if
(
response
!=
null
&&
response
.
getBody
()
!=
null
)
{
return
response
.
getBody
();
}
}
catch
(
Exception
e
)
{
log
.
error
(
"[ SaasAdminService ] getTree 调用失败"
,
e
);
}
return
Collections
.
emptyList
();
}
/**
* 根据 ID 列表批量查询
* <p>
* 对齐 TS {@code getByIds(ids)}
*/
public
List
<
CategoryInfoModel
>
getByIds
(
String
ids
)
{
if
(
ids
==
null
||
ids
.
isEmpty
())
{
return
Collections
.
emptyList
();
}
try
{
String
url
=
adminBaseUrl
+
GET_BY_IDS_URL
+
"?ids="
+
ids
;
ResponseEntity
<
List
<
CategoryInfoModel
>>
response
=
remoteApiClient
.
get
(
url
,
new
ParameterizedTypeReference
<>()
{},
getHeader
());
if
(
response
!=
null
&&
response
.
getBody
()
!=
null
)
{
return
response
.
getBody
();
}
}
catch
(
Exception
e
)
{
log
.
error
(
"[ SaasAdminService ] getByIds 调用失败, ids={}"
,
ids
,
e
);
}
return
Collections
.
emptyList
();
}
/**
* 获取带有风格属性的树形结构
* <p>
* 对齐 TS {@code treeList()}
*/
public
List
<
CategoryInfoModel
>
treeList
()
{
try
{
ResponseEntity
<
List
<
CategoryInfoModel
>>
response
=
remoteApiClient
.
get
(
adminBaseUrl
+
GET_TREE_URL
,
new
ParameterizedTypeReference
<>()
{},
getHeader
());
if
(
response
!=
null
&&
response
.
getBody
()
!=
null
)
{
return
response
.
getBody
();
}
}
catch
(
Exception
e
)
{
log
.
error
(
"[ SaasAdminService ] treeList 调用失败"
,
e
);
}
return
Collections
.
emptyList
();
}
/**
* 根据 ID 查询单个分类
* <p>
* 对齐 TS {@code getById(id)}
*/
public
CategoryInfoModel
getById
(
Integer
id
)
{
if
(
id
==
null
)
{
return
null
;
}
try
{
String
url
=
adminBaseUrl
+
GET_BY_ID_URL
+
"?id="
+
id
;
ResponseEntity
<
CategoryInfoModel
>
response
=
remoteApiClient
.
get
(
url
,
CategoryInfoModel
.
class
,
null
);
if
(
response
!=
null
)
{
return
response
.
getBody
();
}
}
catch
(
Exception
e
)
{
log
.
error
(
"[ SaasAdminService ] getById 调用失败, id={}"
,
id
,
e
);
}
return
null
;
}
/**
/**
* 查询所有分类(带本地缓存,TTL 5 分钟)
* 查询所有分类(带本地缓存,TTL 5 分钟)
...
@@ -190,49 +48,5 @@ public class SaasAdminService {
...
@@ -190,49 +48,5 @@ public class SaasAdminService {
* 对齐 TS {@code allList()}。分类数据不频繁变动,
* 对齐 TS {@code allList()}。分类数据不频繁变动,
* 使用本地缓存避免每次分页查询都发起远程 HTTP 调用。
* 使用本地缓存避免每次分页查询都发起远程 HTTP 调用。
*/
*/
public
List
<
CategoryInfoModel
>
getAllList
()
{
List
<
CategoryInfoModel
>
getAllList
();
// 命中缓存且未过期 → 直接返回
CacheEntry
<
List
<
CategoryInfoModel
>>
entry
=
categoryCache
.
get
();
if
(
entry
!=
null
&&
!
entry
.
isExpired
())
{
return
entry
.
data
;
}
// 未命中或已过期 → 远程调用刷新
try
{
ResponseEntity
<
SaasAdminApiResponseModel
<
List
<
CategoryInfoModel
>>>
response
=
remoteApiClient
.
get
(
adminBaseUrl
+
GET_ALL_LIST_URL
,
new
ParameterizedTypeReference
<>()
{},
getHeader
());
if
(
response
!=
null
&&
response
.
getBody
()
!=
null
)
{
SaasAdminApiResponseModel
<
List
<
CategoryInfoModel
>>
responseBody
=
response
.
getBody
();
if
(
responseBody
.
getCode
()
==
CodeEnum
.
SUCCESS
.
getCode
())
{
List
<
CategoryInfoModel
>
data
=
responseBody
.
getData
();
categoryCache
.
set
(
new
CacheEntry
<>(
data
));
return
data
;
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"[ SaasAdminService ] getAllList 调用失败"
,
e
);
}
// 远程调用失败但有旧缓存 → 降级返回旧缓存
if
(
entry
!=
null
)
{
log
.
warn
(
"[ SaasAdminService ] getAllList 远程失败,降级使用过期缓存"
);
return
entry
.
data
;
}
return
Collections
.
emptyList
();
}
/** 简单 TTL 缓存条目 */
private
static
class
CacheEntry
<
T
>
{
final
T
data
;
final
long
expireAt
;
CacheEntry
(
T
data
)
{
this
.
data
=
data
;
this
.
expireAt
=
System
.
currentTimeMillis
()
+
CACHE_TTL_MS
;
}
boolean
isExpired
()
{
return
System
.
currentTimeMillis
()
>
expireAt
;
}
}
}
}
custom-server-integrate/src/main/java/com/jomalls/custom/integrate/service/impl/SaasAdminServiceImpl.java
0 → 100644
View file @
bdb8936e
package
com
.
jomalls
.
custom
.
integrate
.
service
.
impl
;
import
com.jomalls.custom.enums.CodeEnum
;
import
com.jomalls.custom.integrate.client.RemoteApiClient
;
import
com.jomalls.custom.integrate.model.CategoryInfoModel
;
import
com.jomalls.custom.integrate.model.PropertyModel
;
import
com.jomalls.custom.integrate.model.SaasAdminApiResponseModel
;
import
com.jomalls.custom.integrate.service.SaasAdminService
;
import
com.jomalls.custom.security.LoginUser
;
import
com.jomalls.custom.security.SecurityUtils
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.core.ParameterizedTypeReference
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.StringUtils
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.atomic.AtomicReference
;
/**
* 商品分类服务
* <p>
* 调用 admin API 获取商品分类数据。
* 对齐 TS 项目 {@code baseCategoryInfoService}。
*
* @author Lizh (Java 迁移)
* @since 2019-09-02
*/
@Slf4j
@Service
@RequiredArgsConstructor
public
class
SaasAdminServiceImpl
implements
SaasAdminService
{
private
static
final
String
GET_ALL_LIST_URL
=
"/api/manage/rest/baseCategoryInfo/all_list"
;
private
static
final
String
GET_PROPERTY_BY_IDS_URL
=
"/api/manage/rest/baseProperty/getByIds"
;
private
static
final
int
DEFAULT_MAP_SIZE
=
2
;
/** 分类列表缓存 TTL(毫秒):5 分钟 */
private
static
final
long
CACHE_TTL_MS
=
5
*
60
*
1000
;
private
final
RemoteApiClient
remoteApiClient
;
/** 分类列表本地缓存 */
private
final
AtomicReference
<
CacheEntry
<
List
<
CategoryInfoModel
>>>
categoryCache
=
new
AtomicReference
<>();
@Value
(
"${server.admin.base-url:https://admin.jomalls.com}"
)
private
String
adminBaseUrl
;
private
Map
<
String
,
String
>
getHeader
()
{
Map
<
String
,
String
>
headers
=
new
HashMap
<>(
DEFAULT_MAP_SIZE
);
headers
.
put
(
"Content-Type"
,
"application/json"
);
LoginUser
loginUser
=
SecurityUtils
.
getLoginUser
();
if
(
loginUser
==
null
)
{
return
headers
;
}
headers
.
put
(
"jwt-token"
,
loginUser
.
getToken
());
return
headers
;
}
/**
* 根据属性 ID 列表批量查询属性(含属性值列表)
* <p>
* 对齐 TS {@code getByIds(ids)} 方法。
*
* @param ids 属性 ID,逗号分隔(如 "1,2,3")
* @return 属性列表,包含 valueList 和 skuProperty 等字段
*/
public
List
<
PropertyModel
>
getPropertyByIds
(
String
ids
)
{
if
(!
StringUtils
.
hasText
(
ids
))
{
return
Collections
.
emptyList
();
}
try
{
String
url
=
adminBaseUrl
+
GET_PROPERTY_BY_IDS_URL
+
"?ids="
+
ids
;
ResponseEntity
<
SaasAdminApiResponseModel
<
List
<
PropertyModel
>>>
response
=
remoteApiClient
.
get
(
url
,
new
ParameterizedTypeReference
<>()
{},
getHeader
());
if
(
response
!=
null
&&
response
.
getBody
()
!=
null
)
{
log
.
debug
(
"[ SaasAdminService ] getByIds 成功, ids={}, 返回: {}"
,
ids
,
response
.
toString
());
SaasAdminApiResponseModel
<
List
<
PropertyModel
>>
responseBody
=
response
.
getBody
();
if
(
responseBody
.
getCode
()
==
CodeEnum
.
SUCCESS
.
getCode
())
{
return
responseBody
.
getData
();
}
}
log
.
warn
(
"[ SaasAdminService ] getByIds 返回空, ids={}"
,
ids
);
return
Collections
.
emptyList
();
}
catch
(
Exception
e
)
{
log
.
error
(
"[ SaasAdminService ] getByIds 调用失败, ids={}"
,
ids
,
e
);
return
Collections
.
emptyList
();
}
}
/**
* 查询所有分类(带本地缓存,TTL 5 分钟)
* <p>
* 对齐 TS {@code allList()}。分类数据不频繁变动,
* 使用本地缓存避免每次分页查询都发起远程 HTTP 调用。
*/
public
List
<
CategoryInfoModel
>
getAllList
()
{
// 命中缓存且未过期 → 直接返回
CacheEntry
<
List
<
CategoryInfoModel
>>
entry
=
categoryCache
.
get
();
if
(
entry
!=
null
&&
!
entry
.
isExpired
())
{
return
entry
.
data
;
}
// 未命中或已过期 → 远程调用刷新
try
{
ResponseEntity
<
SaasAdminApiResponseModel
<
List
<
CategoryInfoModel
>>>
response
=
remoteApiClient
.
get
(
adminBaseUrl
+
GET_ALL_LIST_URL
,
new
ParameterizedTypeReference
<>()
{},
getHeader
());
if
(
response
!=
null
&&
response
.
getBody
()
!=
null
)
{
SaasAdminApiResponseModel
<
List
<
CategoryInfoModel
>>
responseBody
=
response
.
getBody
();
if
(
responseBody
.
getCode
()
==
CodeEnum
.
SUCCESS
.
getCode
())
{
List
<
CategoryInfoModel
>
data
=
responseBody
.
getData
();
categoryCache
.
set
(
new
CacheEntry
<>(
data
));
return
data
;
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"[ SaasAdminService ] getAllList 调用失败"
,
e
);
}
// 远程调用失败但有旧缓存 → 降级返回旧缓存
if
(
entry
!=
null
)
{
log
.
warn
(
"[ SaasAdminService ] getAllList 远程失败,降级使用过期缓存"
);
return
entry
.
data
;
}
return
Collections
.
emptyList
();
}
/** 简单 TTL 缓存条目 */
private
static
class
CacheEntry
<
T
>
{
final
T
data
;
final
long
expireAt
;
CacheEntry
(
T
data
)
{
this
.
data
=
data
;
this
.
expireAt
=
System
.
currentTimeMillis
()
+
CACHE_TTL_MS
;
}
boolean
isExpired
()
{
return
System
.
currentTimeMillis
()
>
expireAt
;
}
}
}
custom-server-starter/src/main/java/com/jomalls/custom/config/RestResponseBodyConfig.java
View file @
bdb8936e
...
@@ -3,7 +3,7 @@ package com.jomalls.custom.config;
...
@@ -3,7 +3,7 @@ package com.jomalls.custom.config;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.jomalls.custom.enums.CodeEnum
;
import
com.jomalls.custom.enums.CodeEnum
;
import
com.jomalls.custom.page.PageAdapt
t
er
;
import
com.jomalls.custom.page.PageAdapter
;
import
org.jspecify.annotations.NonNull
;
import
org.jspecify.annotations.NonNull
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.core.annotation.AnnotatedElementUtils
;
import
org.springframework.core.annotation.AnnotatedElementUtils
;
...
@@ -63,7 +63,7 @@ public class RestResponseBodyConfig implements ResponseBodyAdvice<Object> {
...
@@ -63,7 +63,7 @@ public class RestResponseBodyConfig implements ResponseBodyAdvice<Object> {
}
else
{
}
else
{
// 分页结果转为老服务(TS)格式:records→list, current→curPage, total→totalRow, pages→totalPage
// 分页结果转为老服务(TS)格式:records→list, current→curPage, total→totalRow, pages→totalPage
if
(
body
instanceof
IPage
<?>
page
)
{
if
(
body
instanceof
IPage
<?>
page
)
{
body
=
PageAdapt
t
er
.
from
(
page
);
body
=
PageAdapter
.
from
(
page
);
}
}
if
(
body
instanceof
String
)
{
if
(
body
instanceof
String
)
{
try
{
try
{
...
...
custom-server-starter/src/main/resources/application-datasource.properties
View file @
bdb8936e
...
@@ -8,7 +8,7 @@ spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
...
@@ -8,7 +8,7 @@ spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#最小空闲连接数
#最小空闲连接数
spring.datasource.hikari.minimum-idle
=
5
spring.datasource.hikari.minimum-idle
=
5
#最大连接池大小
#最大连接池大小
spring.datasource.hikari.maximum-pool-size
=
2
0
spring.datasource.hikari.maximum-pool-size
=
5
0
#连接超时时间(60秒)
#连接超时时间(60秒)
spring.datasource.hikari.connection-timeout
=
60000
spring.datasource.hikari.connection-timeout
=
60000
#空闲连接超时时间(600秒)
#空闲连接超时时间(600秒)
...
...
custom-server-starter/src/main/resources/application.properties
View file @
bdb8936e
...
@@ -5,7 +5,7 @@ server.servlet.context-path=/
...
@@ -5,7 +5,7 @@ server.servlet.context-path=/
## Tomcat配置
## Tomcat配置
server.tomcat.uri-encoding
=
UTF-8
server.tomcat.uri-encoding
=
UTF-8
server.tomcat.accept-count
=
1000
server.tomcat.accept-count
=
1000
server.tomcat.threads.max
=
8
00
server.tomcat.threads.max
=
2
00
server.tomcat.threads.min-spare
=
100
server.tomcat.threads.min-spare
=
100
## Spring配置
## Spring配置
...
@@ -35,7 +35,7 @@ server.needAuthentication=true
...
@@ -35,7 +35,7 @@ server.needAuthentication=true
token.header
=
Authorization
token.header
=
Authorization
# 令牌密钥(兼容旧版本)
# 令牌密钥(兼容旧版本)
token.secret
=
custom
token.secret
=
custom
# 令牌有效期(
默认30
分钟)
# 令牌有效期(
单位:
分钟)
token.expireTime
=
720
token.expireTime
=
720
# HTTP Client Configuration
# HTTP Client Configuration
...
...
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/CustomProductInfoController.java
View file @
bdb8936e
...
@@ -69,7 +69,7 @@ public class CustomProductInfoController {
...
@@ -69,7 +69,7 @@ public class CustomProductInfoController {
}
}
@Operation
(
summary
=
"绑定默认模型"
,
description
=
"设置商品的默认 DIY 模板"
)
@Operation
(
summary
=
"绑定默认模型"
,
description
=
"设置商品的默认 DIY 模板"
)
@
Ge
tMapping
(
"/bindDefaultDiy"
)
@
Pos
tMapping
(
"/bindDefaultDiy"
)
public
void
bindDefaultDiy
(
public
void
bindDefaultDiy
(
@Parameter
(
description
=
"商品 ID"
)
@RequestParam
Integer
id
,
@Parameter
(
description
=
"商品 ID"
)
@RequestParam
Integer
id
,
@Parameter
(
description
=
"DIY 模板 ID"
)
@RequestParam
Integer
diyId
,
@Parameter
(
description
=
"DIY 模板 ID"
)
@RequestParam
Integer
diyId
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment