Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
promotion-service
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
promotion
promotion-service
Commits
ea0a32cc
提交
ea0a32cc
authored
1月 13, 2026
作者:
窦馨雨
浏览文件
操作
浏览文件
下载
差异文件
合并分支 'dxy' 到 'qa'
CP计划小程序改造,新增模板改造,导出飞书文件改造 查看合并请求
!60
上级
05e98e6f
e1059dbb
隐藏空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
566 行增加
和
45 行删除
+566
-45
TemporaryActivityCoreController.java
...r/activity/temporary/TemporaryActivityCoreController.java
+12
-1
PromPlanCoreController.java
...ion/controller/activityplanv2/PromPlanCoreController.java
+1
-0
TencentLocationController.java
...n/controller/user/location/TencentLocationController.java
+35
-0
ActivityPlanInfoVo.java
...promotion/pojo/activity/manage/vo/ActivityPlanInfoVo.java
+1
-0
ActivityPlanInfoDto.java
...omotion/pojo/activity/planv2/dto/ActivityPlanInfoDto.java
+12
-2
ActivityPlanOperVo.java
...promotion/pojo/activity/planv2/vo/ActivityPlanOperVo.java
+11
-2
TemporaryActivityCoreServiceImpl.java
...vity/temporary/impl/TemporaryActivityCoreServiceImpl.java
+4
-0
PromPlanCoreServiceImpl.java
.../service/activityplanv2/impl/PromPlanCoreServiceImpl.java
+101
-40
TencentLocationQueryService.java
...u/promotion/service/user/TencentLocationQueryService.java
+17
-0
TencentLocationQueryServiceImpl.java
...on/service/user/impl/TencentLocationQueryServiceImpl.java
+52
-0
WeChatUserQueryService.java
...aolu/promotion/service/wechat/WeChatUserQueryService.java
+7
-0
WeChatUserQueryServiceImpl.java
...otion/service/wechat/impl/WeChatUserQueryServiceImpl.java
+5
-0
TencentMapUtil.java
...n/java/com/wangxiaolu/promotion/utils/TencentMapUtil.java
+308
-0
没有找到文件。
src/main/java/com/wangxiaolu/promotion/controller/activity/temporary/TemporaryActivityCoreController.java
浏览文件 @
ea0a32cc
package
com
.
wangxiaolu
.
promotion
.
controller
.
activity
.
temporary
;
package
com
.
wangxiaolu
.
promotion
.
controller
.
activity
.
temporary
;
import
com.wangxiaolu.promotion.controller.user.tem.TemporaryInfoQueryController
;
import
com.wangxiaolu.promotion.domain.user.dao.TemporaryInfoDao
;
import
com.wangxiaolu.promotion.domain.user.dao.TemporaryInfoDao
;
import
com.wangxiaolu.promotion.enums.activity.TemActApproveStatus
;
import
com.wangxiaolu.promotion.enums.activity.TemActApproveStatus
;
import
com.wangxiaolu.promotion.exception.DataException
;
import
com.wangxiaolu.promotion.exception.DataException
;
...
@@ -14,6 +15,7 @@ import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCloc
...
@@ -14,6 +15,7 @@ import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCloc
import
com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityClockQueryService
;
import
com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityClockQueryService
;
import
com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCoreService
;
import
com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCoreService
;
import
com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityQueryService
;
import
com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityQueryService
;
import
com.wangxiaolu.promotion.service.wechat.WeChatUserQueryService
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
@@ -41,6 +43,9 @@ public class TemporaryActivityCoreController {
...
@@ -41,6 +43,9 @@ public class TemporaryActivityCoreController {
@Autowired
@Autowired
private
TemporaryActivityClockCoreService
tempActivityClockCoreService
;
private
TemporaryActivityClockCoreService
tempActivityClockCoreService
;
@Autowired
private
WeChatUserQueryService
weChatUserQueryService
;
/**
/**
* 促销员[今日活动]数据保存
* 促销员[今日活动]数据保存
* 返回活动生成id
* 返回活动生成id
...
@@ -54,6 +59,11 @@ public class TemporaryActivityCoreController {
...
@@ -54,6 +59,11 @@ public class TemporaryActivityCoreController {
TemporaryActivityReportedDto
temActDto
=
new
TemporaryActivityReportedDto
();
TemporaryActivityReportedDto
temActDto
=
new
TemporaryActivityReportedDto
();
BeanUtils
.
copyProperties
(
activityVo
,
temActDto
);
BeanUtils
.
copyProperties
(
activityVo
,
temActDto
);
temActDto
.
setId
(
activityVo
.
getActivityReportedId
());
temActDto
.
setId
(
activityVo
.
getActivityReportedId
());
//保存促销员电话号码
String
temporaryPhone
=
weChatUserQueryService
.
findUserPhoneByID
(
activityVo
.
getTemporaryId
());
temActDto
.
setTemporaryPhone
(
temporaryPhone
);
/**
/**
* 已有id,修改任务
* 已有id,修改任务
*/
*/
...
@@ -78,7 +88,8 @@ public class TemporaryActivityCoreController {
...
@@ -78,7 +88,8 @@ public class TemporaryActivityCoreController {
.
setActivityPatternId
(
clockDto
.
getActivityPatternId
())
.
setActivityPatternId
(
clockDto
.
getActivityPatternId
())
.
setActivityPattern
(
clockDto
.
getActivityPattern
())
.
setActivityPattern
(
clockDto
.
getActivityPattern
())
.
setProvince
(
clockDto
.
getClockProvince
())
.
setProvince
(
clockDto
.
getClockProvince
())
.
setCity
(
clockDto
.
getClockCity
());
.
setCity
(
clockDto
.
getClockCity
()).
setTemporaryPhone
(
clockDto
.
getPhone
())
;
long
reportedId
=
tempActivityCoreService
.
activityDataReportedSave
(
temActDto
);
long
reportedId
=
tempActivityCoreService
.
activityDataReportedSave
(
temActDto
);
...
...
src/main/java/com/wangxiaolu/promotion/controller/activityplanv2/PromPlanCoreController.java
浏览文件 @
ea0a32cc
...
@@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j;
...
@@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.*
;
import
java.io.File
;
import
java.time.LocalDate
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.time.YearMonth
;
import
java.time.YearMonth
;
...
...
src/main/java/com/wangxiaolu/promotion/controller/user/location/TencentLocationController.java
0 → 100644
浏览文件 @
ea0a32cc
package
com
.
wangxiaolu
.
promotion
.
controller
.
user
.
location
;
import
com.wangxiaolu.promotion.result.basedata.R
;
import
com.wangxiaolu.promotion.service.user.TencentLocationQueryService
;
import
com.wangxiaolu.promotion.utils.TencentMapUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* @Author: DouXinYu
* @Date: 2026-01-12 11:10
* @Description:
*/
@RestController
@RequestMapping
(
"/user/location/query"
)
public
class
TencentLocationController
{
@Autowired
TencentLocationQueryService
tencentLocationQueryService
;
@GetMapping
(
"/reverse"
)
public
R
getDefaultLocation
(
@RequestParam
(
"lng"
)
double
lng
,
@RequestParam
(
"lat"
)
double
lat
){
TencentMapUtil
.
AddressInfo
addressByLngLat
=
tencentLocationQueryService
.
getAddressByLngLat
(
lng
,
lat
);
return
R
.
success
(
addressByLngLat
);
}
@GetMapping
(
"/list"
)
public
R
getProvinceDistinctList
(){
return
R
.
success
(
tencentLocationQueryService
.
getAddressList
());
}
}
src/main/java/com/wangxiaolu/promotion/pojo/activity/manage/vo/ActivityPlanInfoVo.java
浏览文件 @
ea0a32cc
...
@@ -77,4 +77,5 @@ public class ActivityPlanInfoVo {
...
@@ -77,4 +77,5 @@ public class ActivityPlanInfoVo {
private
String
lineName
;
private
String
lineName
;
}
}
src/main/java/com/wangxiaolu/promotion/pojo/activity/planv2/dto/ActivityPlanInfoDto.java
浏览文件 @
ea0a32cc
...
@@ -158,14 +158,24 @@ public class ActivityPlanInfoDto implements Serializable {
...
@@ -158,14 +158,24 @@ public class ActivityPlanInfoDto implements Serializable {
*/
*/
// private BigDecimal incidentals;
// private BigDecimal incidentals;
/**
/**
*
是否有
试吃台
*
门店是否已配
试吃台
*/
*/
private
String
temWlSct
;
private
String
temWlSct
;
/**
/**
* 活动品项:老品/黑鸭/散称
* 活动品项:老品/黑鸭/散称
/礼盒
*/
*/
private
String
prdClass
;
private
String
prdClass
;
/**
* 活动执行方式:经销商/第三方
*/
private
String
planExecuteMode
;
/**
* 门店是否允许使用试吃台
*/
private
String
isCanUseTasteCounter
;
/**
/**
* 是否执行:1:执行;0:未执行;
* 是否执行:1:执行;0:未执行;
*/
*/
...
...
src/main/java/com/wangxiaolu/promotion/pojo/activity/planv2/vo/ActivityPlanOperVo.java
浏览文件 @
ea0a32cc
...
@@ -80,12 +80,21 @@ public class ActivityPlanOperVo {
...
@@ -80,12 +80,21 @@ public class ActivityPlanOperVo {
private
LocalDateTime
noonClockInTime
;
private
LocalDateTime
noonClockInTime
;
/**
/**
* 是否有试吃台
* 门店是否可用试吃台
*/
private
String
isCanUseTasteCounter
;
/**
* 门店是否配有试吃台
*/
*/
private
String
temWlSct
;
private
String
temWlSct
;
/**
/**
* 活动品项:老品/黑鸭/散称
* 活动品项:老品/黑鸭/散称
/礼盒
*/
*/
private
String
prdClass
;
private
String
prdClass
;
/**
* 执行方式
*/
private
String
planExecuteMode
;
private
List
<
Long
>
planIds
;
private
List
<
Long
>
planIds
;
}
}
src/main/java/com/wangxiaolu/promotion/service/activity/temporary/impl/TemporaryActivityCoreServiceImpl.java
浏览文件 @
ea0a32cc
...
@@ -18,6 +18,7 @@ import com.wangxiaolu.promotion.pojo.activity.planv2.dto.ActivityPlanInfoDto;
...
@@ -18,6 +18,7 @@ import com.wangxiaolu.promotion.pojo.activity.planv2.dto.ActivityPlanInfoDto;
import
com.wangxiaolu.promotion.pojo.activity.temporary.dto.TemporaryActivityMarketCellDto
;
import
com.wangxiaolu.promotion.pojo.activity.temporary.dto.TemporaryActivityMarketCellDto
;
import
com.wangxiaolu.promotion.pojo.activity.temporary.dto.TemporaryActivityReportedDto
;
import
com.wangxiaolu.promotion.pojo.activity.temporary.dto.TemporaryActivityReportedDto
;
import
com.wangxiaolu.promotion.pojo.activity.temporary.vo.TemporaryActivityMarketCellVo
;
import
com.wangxiaolu.promotion.pojo.activity.temporary.vo.TemporaryActivityMarketCellVo
;
import
com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto
;
import
com.wangxiaolu.promotion.result.basedata.RCode
;
import
com.wangxiaolu.promotion.result.basedata.RCode
;
import
com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityClockQueryService
;
import
com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityClockQueryService
;
import
com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCoreService
;
import
com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCoreService
;
...
@@ -88,6 +89,7 @@ public class TemporaryActivityCoreServiceImpl implements TemporaryActivityCoreSe
...
@@ -88,6 +89,7 @@ public class TemporaryActivityCoreServiceImpl implements TemporaryActivityCoreSe
// 保存图片
// 保存图片
saveActivityPhotoV2
(
temActDto
);
saveActivityPhotoV2
(
temActDto
);
// 售卖单元新增保存
// 售卖单元新增保存
// String key = temMarketCellRedisKey(temActDto.getTemporaryId());
// String key = temMarketCellRedisKey(temActDto.getTemporaryId());
// temporaryActivityMarketCellDao.saveList(reportedId,redisCache.getToJsonArray(key));
// temporaryActivityMarketCellDao.saveList(reportedId,redisCache.getToJsonArray(key));
...
@@ -113,6 +115,8 @@ public class TemporaryActivityCoreServiceImpl implements TemporaryActivityCoreSe
...
@@ -113,6 +115,8 @@ public class TemporaryActivityCoreServiceImpl implements TemporaryActivityCoreSe
}
else
{
}
else
{
temActDto
.
setApproveStatus
(
TemActApproveStatus
.
SUBMITTED
);
temActDto
.
setApproveStatus
(
TemActApproveStatus
.
SUBMITTED
);
}
}
WxTemporaryInfoDto
wxTemporaryInfoDto
=
temporaryInfoDao
.
selectOneById
(
temActDto
.
getTemporaryId
());
temActDto
.
setTemporaryPhone
(
wxTemporaryInfoDto
.
getPhone
());
temporaryActivityReportedDao
.
updateById
(
temActDto
);
temporaryActivityReportedDao
.
updateById
(
temActDto
);
// 售卖单元新增保存
// 售卖单元新增保存
...
...
src/main/java/com/wangxiaolu/promotion/service/activityplanv2/impl/PromPlanCoreServiceImpl.java
浏览文件 @
ea0a32cc
...
@@ -91,7 +91,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -91,7 +91,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
String
[]
headers
=
readExcelUtils
.
readTitle
();
String
[]
headers
=
readExcelUtils
.
readTitle
();
Map
<
Integer
,
List
<
Object
>>
rows
=
readExcelUtils
.
readContent
();
Map
<
Integer
,
List
<
Object
>>
rows
=
readExcelUtils
.
readContent
();
if
(
headers
.
length
!=
1
2
)
{
if
(
headers
.
length
!=
1
4
)
{
throw
new
DataException
(
RCode
.
ACTIVITY_PLAN_TEM_ERROR
);
throw
new
DataException
(
RCode
.
ACTIVITY_PLAN_TEM_ERROR
);
}
}
if
(
CollectionUtil
.
isEmpty
(
rows
))
{
if
(
CollectionUtil
.
isEmpty
(
rows
))
{
...
@@ -102,7 +102,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -102,7 +102,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
for
(
Map
.
Entry
<
Integer
,
List
<
Object
>>
row
:
rows
.
entrySet
())
{
for
(
Map
.
Entry
<
Integer
,
List
<
Object
>>
row
:
rows
.
entrySet
())
{
List
<
Object
>
cells
=
row
.
getValue
();
List
<
Object
>
cells
=
row
.
getValue
();
// 判断当前行是否有任一数据为空,如果有则报错,不进行解析
// 判断当前行是否有任一数据为空,如果有则报错,不进行解析
boolean
isEmpty
=
(
cells
.
size
()
!=
1
2
)
||
cells
.
stream
().
anyMatch
(
cell
->
ObjectUtil
.
isNull
(
cell
)
||
StringUtils
.
isBlank
(
cell
.
toString
()));
boolean
isEmpty
=
(
cells
.
size
()
!=
1
4
)
||
cells
.
stream
().
anyMatch
(
cell
->
ObjectUtil
.
isNull
(
cell
)
||
StringUtils
.
isBlank
(
cell
.
toString
()));
if
(
isEmpty
)
{
if
(
isEmpty
)
{
indexList
.
add
(
row
.
getKey
()
+
1
);
indexList
.
add
(
row
.
getKey
()
+
1
);
}
}
...
@@ -171,7 +171,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -171,7 +171,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
dto
.
setErrorMsg
(
"门店编码错误;"
);
dto
.
setErrorMsg
(
"门店编码错误;"
);
}
else
{
}
else
{
if
(
StringUtils
.
isAnyBlank
(
storeDto
.
getDealersName
(),
storeDto
.
getDealerId
()))
{
if
(
StringUtils
.
isAnyBlank
(
storeDto
.
getDealersName
(),
storeDto
.
getDealerId
()))
{
dto
.
setErrorMsg
(
"门店「经销商」为空,请到勤策中
进
充;"
);
dto
.
setErrorMsg
(
"门店「经销商」为空,请到勤策中
补
充;"
);
}
}
dto
.
setLineName
(
storeDto
.
getLineName
());
dto
.
setLineName
(
storeDto
.
getLineName
());
dto
.
setStoreCode
(
sc
);
dto
.
setStoreCode
(
sc
);
...
@@ -188,10 +188,10 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -188,10 +188,10 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
* 3:活动模式
* 3:活动模式
*/
*/
String
pattern
=
row
.
get
(
3
).
toString
();
String
pattern
=
row
.
get
(
3
).
toString
();
if
(
"
单点CP,常规MINI秀,校园活动
"
.
contains
(
pattern
))
{
if
(
"
大区KA,重客KA,大区零食,重客零食,场景营销
"
.
contains
(
pattern
))
{
dto
.
setPattern
(
pattern
);
dto
.
setPattern
(
pattern
);
}
else
{
}
else
{
dto
.
setErrorMsg
(
"活动模式分为:
单点CP、常规MINI秀、校园活动
;"
);
dto
.
setErrorMsg
(
"活动模式分为:
大区KA、重客KA、大区零食、重客零食、场景营销
;"
);
}
}
/**
/**
...
@@ -248,24 +248,43 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -248,24 +248,43 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
/**
/**
* 10:
是否有促销台/
试吃台
* 10:
门店是否可用
试吃台
*/
*/
String
temWlSct
=
row
.
get
(
10
).
toString
();
String
isCanUseTasteCounter
=
row
.
get
(
10
).
toString
();
if
(
"
有,无"
.
contains
(
temWlSct
))
{
if
(
"
是,否"
.
contains
(
isCanUseTasteCounter
))
{
dto
.
set
TemWlSct
(
temWlSct
);
dto
.
set
IsCanUseTasteCounter
(
isCanUseTasteCounter
);
}
else
{
}
else
{
dto
.
setErrorMsg
(
"
是否有促销台请填写:有、无
;"
);
dto
.
setErrorMsg
(
"
门店是否可用试吃台请填写:是、否
;"
);
}
}
/**
* 11:门店是否已配试吃台
*/
String
temWlSct
=
row
.
get
(
11
).
toString
();
if
(
"是,否"
.
contains
(
temWlSct
))
{
dto
.
setTemWlSct
(
temWlSct
);
}
else
{
dto
.
setErrorMsg
(
"门店是否已配试吃台请填写:是、否;"
);
}
/**
/**
* 1
1
:活动品项
* 1
2
:活动品项
*/
*/
String
prdClass
=
row
.
get
(
1
1
).
toString
();
String
prdClass
=
row
.
get
(
1
2
).
toString
();
if
(
"黑鸭,散称,老品"
.
contains
(
prdClass
))
{
if
(
"黑鸭,散称,老品
,礼盒
"
.
contains
(
prdClass
))
{
dto
.
setPrdClass
(
prdClass
);
dto
.
setPrdClass
(
prdClass
);
}
else
{
}
else
{
dto
.
setErrorMsg
(
"活动品项请填写:黑鸭、散称、老品;"
);
dto
.
setErrorMsg
(
"活动品项请填写:黑鸭、散称、老品、礼盒;"
);
}
/**
* 13:活动执行模式
*/
String
planExecuteMode
=
row
.
get
(
13
).
toString
();
if
(
"第三方,经销商"
.
contains
(
planExecuteMode
))
{
dto
.
setPlanExecuteMode
(
planExecuteMode
);
}
else
{
dto
.
setErrorMsg
(
"活动执行模式请填写:第三方、经销商;"
);
}
}
// 作废:工资
// 作废:工资
...
@@ -325,7 +344,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -325,7 +344,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
String
[]
headers
=
readExcelUtils
.
readTitle
();
String
[]
headers
=
readExcelUtils
.
readTitle
();
Map
<
Integer
,
List
<
Object
>>
rows
=
readExcelUtils
.
readContent
();
Map
<
Integer
,
List
<
Object
>>
rows
=
readExcelUtils
.
readContent
();
if
(
headers
.
length
!=
1
2
)
{
if
(
headers
.
length
!=
1
4
)
{
throw
new
DataException
(
RCode
.
ACTIVITY_PLAN_TEM_ERROR
);
throw
new
DataException
(
RCode
.
ACTIVITY_PLAN_TEM_ERROR
);
}
}
if
(
CollectionUtil
.
isEmpty
(
rows
))
{
if
(
CollectionUtil
.
isEmpty
(
rows
))
{
...
@@ -336,7 +355,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -336,7 +355,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
for
(
Map
.
Entry
<
Integer
,
List
<
Object
>>
row
:
rows
.
entrySet
())
{
for
(
Map
.
Entry
<
Integer
,
List
<
Object
>>
row
:
rows
.
entrySet
())
{
List
<
Object
>
cells
=
row
.
getValue
();
List
<
Object
>
cells
=
row
.
getValue
();
// 判断当前行是否有任一数据为空,如果有则报错,不进行解析
// 判断当前行是否有任一数据为空,如果有则报错,不进行解析
boolean
isEmpty
=
(
cells
.
size
()
!=
1
2
)
||
cells
.
stream
().
anyMatch
(
cell
->
ObjectUtil
.
isNull
(
cell
)
||
StringUtils
.
isBlank
(
cell
.
toString
()));
boolean
isEmpty
=
(
cells
.
size
()
!=
1
4
)
||
cells
.
stream
().
anyMatch
(
cell
->
ObjectUtil
.
isNull
(
cell
)
||
StringUtils
.
isBlank
(
cell
.
toString
()));
if
(
isEmpty
)
{
if
(
isEmpty
)
{
indexList
.
add
(
row
.
getKey
()
+
1
);
indexList
.
add
(
row
.
getKey
()
+
1
);
}
}
...
@@ -409,7 +428,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -409,7 +428,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
dto
.
setErrorMsg
(
"门店编码错误;"
);
dto
.
setErrorMsg
(
"门店编码错误;"
);
}
else
{
}
else
{
if
(
StringUtils
.
isAnyBlank
(
storeDto
.
getDealersName
(),
storeDto
.
getDealerId
()))
{
if
(
StringUtils
.
isAnyBlank
(
storeDto
.
getDealersName
(),
storeDto
.
getDealerId
()))
{
dto
.
setErrorMsg
(
"门店「经销商」为空,请到勤策中
进
充;"
);
dto
.
setErrorMsg
(
"门店「经销商」为空,请到勤策中
补
充;"
);
}
}
dto
.
setLineName
(
storeDto
.
getLineName
());
dto
.
setLineName
(
storeDto
.
getLineName
());
dto
.
setStoreCode
(
sc
);
dto
.
setStoreCode
(
sc
);
...
@@ -426,10 +445,10 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -426,10 +445,10 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
* 3:活动模式
* 3:活动模式
*/
*/
String
pattern
=
row
.
get
(
3
).
toString
();
String
pattern
=
row
.
get
(
3
).
toString
();
if
(
"
单点CP,常规MINI秀,校园活动
"
.
contains
(
pattern
))
{
if
(
"
大区KA,重客KA,大区零食,重客零食,场景营销
"
.
contains
(
pattern
))
{
dto
.
setPattern
(
pattern
);
dto
.
setPattern
(
pattern
);
}
else
{
}
else
{
dto
.
setErrorMsg
(
"活动模式分为:
单点CP、常规MINI秀、校园活动
;"
);
dto
.
setErrorMsg
(
"活动模式分为:
大区KA、重客KA、大区零食、重客零食、场景营销
;"
);
}
}
/**
/**
...
@@ -482,23 +501,43 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -482,23 +501,43 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
}
}
/**
/**
* 10:是否有促销台/试吃台
* 10:门店是否可用试吃台
*/
String
isCanUseTasteCounter
=
row
.
get
(
10
).
toString
();
if
(
"是,否"
.
contains
(
isCanUseTasteCounter
))
{
dto
.
setIsCanUseTasteCounter
(
isCanUseTasteCounter
);
}
else
{
dto
.
setErrorMsg
(
"门店是否可用试吃台请填写:是、否;"
);
}
/**
* 11:门店是否已配试吃台
*/
*/
String
temWlSct
=
row
.
get
(
1
0
).
toString
();
String
temWlSct
=
row
.
get
(
1
1
).
toString
();
if
(
"
有,无
"
.
contains
(
temWlSct
))
{
if
(
"
是,否
"
.
contains
(
temWlSct
))
{
dto
.
setTemWlSct
(
temWlSct
);
dto
.
setTemWlSct
(
temWlSct
);
}
else
{
}
else
{
dto
.
setErrorMsg
(
"
是否有促销台请填写:有、无
;"
);
dto
.
setErrorMsg
(
"
门店是否已配试吃台请填写:是、否
;"
);
}
}
/**
/**
* 1
1
:活动品项
* 1
2
:活动品项
*/
*/
String
prdClass
=
row
.
get
(
1
1
).
toString
();
String
prdClass
=
row
.
get
(
1
2
).
toString
();
if
(
"黑鸭,散称,老品"
.
contains
(
prdClass
))
{
if
(
"黑鸭,散称,老品
,礼盒
"
.
contains
(
prdClass
))
{
dto
.
setPrdClass
(
prdClass
);
dto
.
setPrdClass
(
prdClass
);
}
else
{
}
else
{
dto
.
setErrorMsg
(
"活动品项请填写:黑鸭、散称、老品;"
);
dto
.
setErrorMsg
(
"活动品项请填写:黑鸭、散称、老品、礼盒;"
);
}
/**
* 13:活动执行模式
*/
String
planExecuteMode
=
row
.
get
(
13
).
toString
();
if
(
"第三方,经销商"
.
contains
(
planExecuteMode
))
{
dto
.
setPlanExecuteMode
(
planExecuteMode
);
}
else
{
dto
.
setErrorMsg
(
"活动执行模式请填写:第三方、经销商;"
);
}
}
// 8:工资
// 8:工资
...
@@ -605,8 +644,10 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -605,8 +644,10 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
.
setClockOutTime
(
operVo
.
getClockOutTime
())
.
setClockOutTime
(
operVo
.
getClockOutTime
())
.
setNoonClockOutTime
(
operVo
.
getNoonClockOutTime
())
.
setNoonClockOutTime
(
operVo
.
getNoonClockOutTime
())
.
setNoonClockInTime
(
operVo
.
getNoonClockInTime
())
.
setNoonClockInTime
(
operVo
.
getNoonClockInTime
())
.
setIsCanUseTasteCounter
(
operVo
.
getIsCanUseTasteCounter
())
.
setTemWlSct
(
operVo
.
getTemWlSct
())
.
setTemWlSct
(
operVo
.
getTemWlSct
())
.
setPrdClass
(
operVo
.
getPrdClass
())
.
setPrdClass
(
operVo
.
getPrdClass
())
.
setPlanExecuteMode
(
operVo
.
getPlanExecuteMode
())
.
setModifyBy
(
operVo
.
getOperName
());
.
setModifyBy
(
operVo
.
getOperName
());
activityPlanInfoDao
.
updateById
(
planDto
);
activityPlanInfoDao
.
updateById
(
planDto
);
}
}
...
@@ -641,8 +682,10 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -641,8 +682,10 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
.
setClockOutTime
(
operVo
.
getClockOutTime
())
.
setClockOutTime
(
operVo
.
getClockOutTime
())
.
setNoonClockOutTime
(
operVo
.
getNoonClockOutTime
())
.
setNoonClockOutTime
(
operVo
.
getNoonClockOutTime
())
.
setNoonClockInTime
(
operVo
.
getNoonClockInTime
())
.
setNoonClockInTime
(
operVo
.
getNoonClockInTime
())
.
setIsCanUseTasteCounter
(
operVo
.
getIsCanUseTasteCounter
())
.
setTemWlSct
(
operVo
.
getTemWlSct
())
.
setTemWlSct
(
operVo
.
getTemWlSct
())
.
setPrdClass
(
operVo
.
getPrdClass
())
.
setPrdClass
(
operVo
.
getPrdClass
())
.
setPlanExecuteMode
(
operVo
.
getPlanExecuteMode
())
.
setCreateBy
(
operVo
.
getOperName
());
.
setCreateBy
(
operVo
.
getOperName
());
activityPlanInfoDao
.
save
(
planDto
);
activityPlanInfoDao
.
save
(
planDto
);
}
}
...
@@ -673,7 +716,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -673,7 +716,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
String
[]
headers
=
readExcelUtils
.
readTitle
();
String
[]
headers
=
readExcelUtils
.
readTitle
();
Map
<
Integer
,
List
<
Object
>>
rows
=
readExcelUtils
.
readContent
();
Map
<
Integer
,
List
<
Object
>>
rows
=
readExcelUtils
.
readContent
();
if
(
headers
.
length
!=
1
2
)
{
if
(
headers
.
length
!=
1
4
)
{
throw
new
DataException
(
RCode
.
ACTIVITY_PLAN_TEM_ERROR
);
throw
new
DataException
(
RCode
.
ACTIVITY_PLAN_TEM_ERROR
);
}
}
if
(
CollectionUtil
.
isEmpty
(
rows
))
{
if
(
CollectionUtil
.
isEmpty
(
rows
))
{
...
@@ -684,7 +727,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -684,7 +727,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
for
(
Map
.
Entry
<
Integer
,
List
<
Object
>>
row
:
rows
.
entrySet
())
{
for
(
Map
.
Entry
<
Integer
,
List
<
Object
>>
row
:
rows
.
entrySet
())
{
List
<
Object
>
cells
=
row
.
getValue
();
List
<
Object
>
cells
=
row
.
getValue
();
// 判断当前行是否有任一数据为空,如果有则报错,不进行解析
// 判断当前行是否有任一数据为空,如果有则报错,不进行解析
boolean
isEmpty
=
(
cells
.
size
()
!=
1
2
)
||
cells
.
stream
().
anyMatch
(
cell
->
ObjectUtil
.
isNull
(
cell
)
||
StringUtils
.
isBlank
(
cell
.
toString
()));
boolean
isEmpty
=
(
cells
.
size
()
!=
1
4
)
||
cells
.
stream
().
anyMatch
(
cell
->
ObjectUtil
.
isNull
(
cell
)
||
StringUtils
.
isBlank
(
cell
.
toString
()));
if
(
isEmpty
)
{
if
(
isEmpty
)
{
indexList
.
add
(
row
.
getKey
()
+
1
);
indexList
.
add
(
row
.
getKey
()
+
1
);
}
}
...
@@ -747,7 +790,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -747,7 +790,7 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
dto
.
setErrorMsg
(
"门店编码错误;"
);
dto
.
setErrorMsg
(
"门店编码错误;"
);
}
else
{
}
else
{
if
(
StringUtils
.
isAnyBlank
(
storeDto
.
getDealersName
(),
storeDto
.
getDealerId
()))
{
if
(
StringUtils
.
isAnyBlank
(
storeDto
.
getDealersName
(),
storeDto
.
getDealerId
()))
{
dto
.
setErrorMsg
(
"门店「经销商」为空,请到勤策中
进
充;"
);
dto
.
setErrorMsg
(
"门店「经销商」为空,请到勤策中
补
充;"
);
}
}
dto
.
setStoreCode
(
sc
);
dto
.
setStoreCode
(
sc
);
dto
.
setStoreName
(
storeDto
.
getStoreName
());
dto
.
setStoreName
(
storeDto
.
getStoreName
());
...
@@ -813,32 +856,50 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
...
@@ -813,32 +856,50 @@ public class PromPlanCoreServiceImpl implements PromPlanCoreService {
* 3:活动模式
* 3:活动模式
*/
*/
String
pattern
=
row
.
get
(
3
).
toString
();
String
pattern
=
row
.
get
(
3
).
toString
();
if
(
"
单点CP,常规MINI秀,校园活动
"
.
contains
(
pattern
))
{
if
(
"
大区KA,重客KA,大区零食,重客零食,场景营销
"
.
contains
(
pattern
))
{
dto
.
setPattern
(
pattern
);
dto
.
setPattern
(
pattern
);
}
else
{
}
else
{
dto
.
setErrorMsg
(
"活动模式分为:单点CP、常规MINI秀、校园活动;"
);
dto
.
setErrorMsg
(
"活动模式分为:大区KA、重客KA、大区零食、重客零食、场景营销;"
);
}
/**
* 10:门店是否可用试吃台
*/
String
isCanUseTasteCounter
=
row
.
get
(
10
).
toString
();
if
(
"是,否"
.
contains
(
isCanUseTasteCounter
))
{
dto
.
setIsCanUseTasteCounter
(
isCanUseTasteCounter
);
}
else
{
dto
.
setErrorMsg
(
"门店是否可用试吃台请填写:是、否;"
);
}
}
/**
/**
* 1
0:是否有促销台/
试吃台
* 1
1:门店是否已配
试吃台
*/
*/
String
temWlSct
=
row
.
get
(
1
0
).
toString
();
String
temWlSct
=
row
.
get
(
1
1
).
toString
();
if
(
"
有,无
"
.
contains
(
temWlSct
))
{
if
(
"
是,否
"
.
contains
(
temWlSct
))
{
dto
.
setTemWlSct
(
temWlSct
);
dto
.
setTemWlSct
(
temWlSct
);
}
else
{
}
else
{
dto
.
setErrorMsg
(
"
是否有促销台请填写:有、无
;"
);
dto
.
setErrorMsg
(
"
门店是否已配试吃台请填写:是、否
;"
);
}
}
/**
/**
* 1
1
:活动品项
* 1
2
:活动品项
*/
*/
String
prdClass
=
row
.
get
(
1
1
).
toString
();
String
prdClass
=
row
.
get
(
1
2
).
toString
();
if
(
"黑鸭,散称,老品"
.
contains
(
prdClass
))
{
if
(
"黑鸭,散称,老品
,礼盒
"
.
contains
(
prdClass
))
{
dto
.
setPrdClass
(
prdClass
);
dto
.
setPrdClass
(
prdClass
);
}
else
{
}
else
{
dto
.
setErrorMsg
(
"活动品项请填写:黑鸭、散称、老品;"
);
dto
.
setErrorMsg
(
"活动品项请填写:黑鸭、散称、老品
、礼盒
;"
);
}
}
/**
* 13:活动执行模式
*/
String
planExecuteMode
=
row
.
get
(
13
).
toString
();
if
(
"第三方,经销商"
.
contains
(
planExecuteMode
))
{
dto
.
setPlanExecuteMode
(
planExecuteMode
);
}
else
{
dto
.
setErrorMsg
(
"活动执行模式请填写:第三方、经销商;"
);
}
// 8:工资
// 8:工资
// dto.setSalary(new BigDecimal(row.get(8).toString()));
// dto.setSalary(new BigDecimal(row.get(8).toString()));
// 9:杂费
// 9:杂费
...
...
src/main/java/com/wangxiaolu/promotion/service/user/TencentLocationQueryService.java
0 → 100644
浏览文件 @
ea0a32cc
package
com
.
wangxiaolu
.
promotion
.
service
.
user
;
import
com.wangxiaolu.promotion.utils.TencentMapUtil
;
import
java.util.List
;
/**
* @Author: DouXinYu
* @Date: 2026-01-12 11:17
* @Description:
*/
public
interface
TencentLocationQueryService
{
TencentMapUtil
.
AddressInfo
getAddressByLngLat
(
double
lng
,
double
lat
);
List
<
TencentMapUtil
.
RegionNode
>
getAddressList
();
}
src/main/java/com/wangxiaolu/promotion/service/user/impl/TencentLocationQueryServiceImpl.java
0 → 100644
浏览文件 @
ea0a32cc
package
com
.
wangxiaolu
.
promotion
.
service
.
user
.
impl
;
import
com.google.gson.Gson
;
import
com.google.gson.reflect.TypeToken
;
import
com.wangxiaolu.promotion.service.user.TencentLocationQueryService
;
import
com.wangxiaolu.promotion.utils.TencentMapUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.StringRedisTemplate
;
import
org.springframework.stereotype.Service
;
import
java.lang.reflect.Type
;
import
java.util.List
;
import
java.util.concurrent.TimeUnit
;
/**
* @Author: DouXinYu
* @Date: 2026-01-12 11:16
* @Description: 腾讯位置查询服务实现类
*/
@Service
public
class
TencentLocationQueryServiceImpl
implements
TencentLocationQueryService
{
private
static
final
String
TRIPLE_REGION_CACHE_KEY
=
"promotion:district:triple_level"
;
private
static
final
long
CACHE_EXPIRE
=
86400L
;
private
static
final
Type
REGION_NODE_TYPE
=
new
TypeToken
<
List
<
TencentMapUtil
.
RegionNode
>>()
{}.
getType
();
private
static
final
Gson
GSON
=
new
Gson
();
@Autowired
private
StringRedisTemplate
stringRedisTemplate
;
@Autowired
TencentMapUtil
tencentMapUtil
;
@Override
public
TencentMapUtil
.
AddressInfo
getAddressByLngLat
(
double
lng
,
double
lat
)
{
return
tencentMapUtil
.
getAddressByLngLat
(
lng
,
lat
);
}
@Override
public
List
<
TencentMapUtil
.
RegionNode
>
getAddressList
()
{
String
cacheJson
=
stringRedisTemplate
.
opsForValue
().
get
(
TRIPLE_REGION_CACHE_KEY
);
if
(
cacheJson
!=
null
&&
!
cacheJson
.
isEmpty
())
{
return
GSON
.
fromJson
(
cacheJson
,
REGION_NODE_TYPE
);
}
List
<
TencentMapUtil
.
RegionNode
>
regionList
=
tencentMapUtil
.
getTripleLevelRegion
();
if
(!
regionList
.
isEmpty
())
{
stringRedisTemplate
.
opsForValue
().
set
(
TRIPLE_REGION_CACHE_KEY
,
GSON
.
toJson
(
regionList
),
CACHE_EXPIRE
,
TimeUnit
.
SECONDS
);
}
return
regionList
;
}
}
src/main/java/com/wangxiaolu/promotion/service/wechat/WeChatUserQueryService.java
浏览文件 @
ea0a32cc
...
@@ -18,4 +18,11 @@ public interface WeChatUserQueryService {
...
@@ -18,4 +18,11 @@ public interface WeChatUserQueryService {
LoginVo
temporaryLoginByPhone
(
String
phone
);
LoginVo
temporaryLoginByPhone
(
String
phone
);
List
<
Map
<
String
,
String
>>
findStoreList
(
TemporaryRegisterVo
temporaryRegisterVo
);
List
<
Map
<
String
,
String
>>
findStoreList
(
TemporaryRegisterVo
temporaryRegisterVo
);
/**
* 根据临时ID查询手机号
* @param temporaryId 临时ID
* @return 手机号
*/
String
findUserPhoneByID
(
Long
temporaryId
);
}
}
src/main/java/com/wangxiaolu/promotion/service/wechat/impl/WeChatUserQueryServiceImpl.java
浏览文件 @
ea0a32cc
...
@@ -94,4 +94,9 @@ public class WeChatUserQueryServiceImpl implements WeChatUserQueryService {
...
@@ -94,4 +94,9 @@ public class WeChatUserQueryServiceImpl implements WeChatUserQueryService {
public
List
<
Map
<
String
,
String
>>
findStoreList
(
TemporaryRegisterVo
temporaryRegisterVo
)
{
public
List
<
Map
<
String
,
String
>>
findStoreList
(
TemporaryRegisterVo
temporaryRegisterVo
)
{
return
activityPlanInfoDao
.
findThisMonthStoreListByLocation
(
temporaryRegisterVo
);
return
activityPlanInfoDao
.
findThisMonthStoreListByLocation
(
temporaryRegisterVo
);
}
}
@Override
public
String
findUserPhoneByID
(
Long
temporaryId
)
{
return
temporaryInfoDao
.
selectOneById
(
temporaryId
).
getPhone
();
}
}
}
src/main/java/com/wangxiaolu/promotion/utils/TencentMapUtil.java
0 → 100644
浏览文件 @
ea0a32cc
package
com
.
wangxiaolu
.
promotion
.
utils
;
import
com.google.gson.Gson
;
import
okhttp3.ConnectionPool
;
import
okhttp3.OkHttpClient
;
import
okhttp3.Request
;
import
okhttp3.Response
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.StringRedisTemplate
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.PostConstruct
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.TimeUnit
;
/**
* 腾讯地图工具类(整合:逆地理编码 + 省市区三级嵌套列表)
*/
@Component
public
class
TencentMapUtil
{
// 你的腾讯API Key
private
static
final
String
API_KEY
=
"UTEBZ-UJ3KG-OORQO-QT3PT-JDWU7-YRBZA"
;
// 1. 逆地理编码接口
private
static
final
String
GEOCODER_URL
=
"https://apis.map.qq.com/ws/geocoder/v1/?location=%f,%f&key=%s&get_poi=0"
;
// 2. 省市区三级嵌套接口(新版结构)
private
static
final
String
DISTRICT_TRIPLE_URL
=
"https://apis.map.qq.com/ws/district/v1/list?key=%s&struct_type=1"
;
// OkHttp客户端
private
static
final
OkHttpClient
OK_HTTP_CLIENT
=
new
OkHttpClient
.
Builder
()
.
connectTimeout
(
10
,
TimeUnit
.
SECONDS
)
.
readTimeout
(
10
,
TimeUnit
.
SECONDS
)
.
connectionPool
(
new
ConnectionPool
(
10
,
30
,
TimeUnit
.
SECONDS
))
.
retryOnConnectionFailure
(
true
)
.
build
();
private
static
final
Gson
GSON
=
new
Gson
();
@Autowired
private
StringRedisTemplate
stringRedisTemplate
;
// ==================== 1. 逆地理编码实体(保留原有) ====================
public
static
class
AddressInfo
{
private
String
province
;
// 省份
private
String
city
;
// 城市
private
String
district
;
// 区县
private
String
street
;
// 街道
private
String
streetNumber
;
// 门牌号
private
String
fullAddress
;
// 完整地址
private
double
lng
;
// 经度
private
double
lat
;
// 纬度
// Getter & Setter
public
String
getProvince
()
{
return
province
;
}
public
void
setProvince
(
String
province
)
{
this
.
province
=
province
;
}
public
String
getCity
()
{
return
city
;
}
public
void
setCity
(
String
city
)
{
this
.
city
=
city
;
}
public
String
getDistrict
()
{
return
district
;
}
public
void
setDistrict
(
String
district
)
{
this
.
district
=
district
;
}
public
String
getStreet
()
{
return
street
;
}
public
void
setStreet
(
String
street
)
{
this
.
street
=
street
;
}
public
String
getStreetNumber
()
{
return
streetNumber
;
}
public
void
setStreetNumber
(
String
streetNumber
)
{
this
.
streetNumber
=
streetNumber
;
}
public
String
getFullAddress
()
{
return
fullAddress
;
}
public
void
setFullAddress
(
String
fullAddress
)
{
this
.
fullAddress
=
fullAddress
;
}
public
double
getLng
()
{
return
lng
;
}
public
void
setLng
(
double
lng
)
{
this
.
lng
=
lng
;
}
public
double
getLat
()
{
return
lat
;
}
public
void
setLat
(
double
lat
)
{
this
.
lat
=
lat
;
}
}
// ==================== 2. 三级嵌套列表实体(匹配前端) ====================
public
static
class
RegionNode
{
private
String
text
;
// 全称(如“北京市”)
private
String
value
;
// adcode(如“110000”)
private
List
<
RegionNode
>
children
;
// 下级节点
public
RegionNode
()
{
this
.
children
=
new
ArrayList
<>();
}
public
RegionNode
(
String
text
,
String
value
)
{
this
.
text
=
text
;
this
.
value
=
value
;
this
.
children
=
new
ArrayList
<>();
}
// Getter & Setter
public
String
getText
()
{
return
text
;
}
public
void
setText
(
String
text
)
{
this
.
text
=
text
;
}
public
String
getValue
()
{
return
value
;
}
public
void
setValue
(
String
value
)
{
this
.
value
=
value
;
}
public
List
<
RegionNode
>
getChildren
()
{
return
children
;
}
public
void
setChildren
(
List
<
RegionNode
>
children
)
{
this
.
children
=
children
;
}
}
// ==================== 腾讯API内部解析实体 ====================
// 逆地理编码响应
private
static
class
GeoResponse
{
private
int
status
;
private
String
message
;
private
GeoResult
result
;
// Getter & Setter
public
int
getStatus
()
{
return
status
;
}
public
void
setStatus
(
int
status
)
{
this
.
status
=
status
;
}
public
String
getMessage
()
{
return
message
;
}
public
void
setMessage
(
String
message
)
{
this
.
message
=
message
;
}
public
GeoResult
getResult
()
{
return
result
;
}
public
void
setResult
(
GeoResult
result
)
{
this
.
result
=
result
;
}
}
private
static
class
GeoResult
{
private
String
formatted_address
;
private
AddressComponent
address_component
;
// Getter & Setter
public
String
getFormatted_address
()
{
return
formatted_address
;
}
public
void
setFormatted_address
(
String
formatted_address
)
{
this
.
formatted_address
=
formatted_address
;
}
public
AddressComponent
getAddress_component
()
{
return
address_component
;
}
public
void
setAddress_component
(
AddressComponent
address_component
)
{
this
.
address_component
=
address_component
;
}
}
private
static
class
AddressComponent
{
private
String
province
;
private
String
city
;
private
String
district
;
private
String
street
;
private
String
street_number
;
// Getter & Setter
public
String
getProvince
()
{
return
province
;
}
public
void
setProvince
(
String
province
)
{
this
.
province
=
province
;
}
public
String
getCity
()
{
return
city
;
}
public
void
setCity
(
String
city
)
{
this
.
city
=
city
;
}
public
String
getDistrict
()
{
return
district
;
}
public
void
setDistrict
(
String
district
)
{
this
.
district
=
district
;
}
public
String
getStreet
()
{
return
street
;
}
public
void
setStreet
(
String
street
)
{
this
.
street
=
street
;
}
public
String
getStreet_number
()
{
return
street_number
;
}
public
void
setStreet_number
(
String
street_number
)
{
this
.
street_number
=
street_number
;
}
}
// 三级嵌套响应
private
static
class
DistrictResponse
{
private
int
status
;
private
String
message
;
private
List
<
ProvinceItem
>
result
;
// Getter & Setter
public
int
getStatus
()
{
return
status
;
}
public
void
setStatus
(
int
status
)
{
this
.
status
=
status
;
}
public
String
getMessage
()
{
return
message
;
}
public
void
setMessage
(
String
message
)
{
this
.
message
=
message
;
}
public
List
<
ProvinceItem
>
getResult
()
{
return
result
;
}
public
void
setResult
(
List
<
ProvinceItem
>
result
)
{
this
.
result
=
result
;
}
}
private
static
class
ProvinceItem
{
private
String
id
;
private
String
fullname
;
private
List
<
CityItem
>
districts
;
// Getter & Setter
public
String
getId
()
{
return
id
;
}
public
void
setId
(
String
id
)
{
this
.
id
=
id
;
}
public
String
getFullname
()
{
return
fullname
;
}
public
void
setFullname
(
String
fullname
)
{
this
.
fullname
=
fullname
;
}
public
List
<
CityItem
>
getDistricts
()
{
return
districts
;
}
public
void
setDistricts
(
List
<
CityItem
>
districts
)
{
this
.
districts
=
districts
;
}
}
private
static
class
CityItem
{
private
String
id
;
private
String
fullname
;
private
List
<
DistrictItem
>
districts
;
// Getter & Setter
public
String
getId
()
{
return
id
;
}
public
void
setId
(
String
id
)
{
this
.
id
=
id
;
}
public
String
getFullname
()
{
return
fullname
;
}
public
void
setFullname
(
String
fullname
)
{
this
.
fullname
=
fullname
;
}
public
List
<
DistrictItem
>
getDistricts
()
{
return
districts
;
}
public
void
setDistricts
(
List
<
DistrictItem
>
districts
)
{
this
.
districts
=
districts
;
}
}
private
static
class
DistrictItem
{
private
String
id
;
private
String
fullname
;
// Getter & Setter
public
String
getId
()
{
return
id
;
}
public
void
setId
(
String
id
)
{
this
.
id
=
id
;
}
public
String
getFullname
()
{
return
fullname
;
}
public
void
setFullname
(
String
fullname
)
{
this
.
fullname
=
fullname
;
}
}
// ==================== 核心功能方法 ====================
/**
* 1. 逆地理编码:经纬度转地址(保留原有功能)
*/
public
AddressInfo
getAddressByLngLat
(
double
lng
,
double
lat
)
{
AddressInfo
addressInfo
=
new
AddressInfo
();
try
{
// 拼接请求地址(注意:腾讯接口是 lat,lng 顺序)
String
requestUrl
=
String
.
format
(
GEOCODER_URL
,
lat
,
lng
,
API_KEY
);
Request
request
=
new
Request
.
Builder
().
url
(
requestUrl
).
get
().
build
();
try
(
Response
response
=
OK_HTTP_CLIENT
.
newCall
(
request
).
execute
())
{
if
(!
response
.
isSuccessful
())
{
throw
new
IOException
(
"逆地理编码请求失败,响应码:"
+
response
.
code
());
}
GeoResponse
resp
=
GSON
.
fromJson
(
response
.
body
().
string
(),
GeoResponse
.
class
);
if
(
resp
.
getStatus
()
!=
0
)
{
throw
new
IOException
(
"逆地理编码API失败:"
+
resp
.
getMessage
());
}
// 解析地址信息
GeoResult
result
=
resp
.
getResult
();
AddressComponent
component
=
result
.
getAddress_component
();
addressInfo
.
setProvince
(
component
.
getProvince
());
addressInfo
.
setCity
(
component
.
getCity
());
addressInfo
.
setDistrict
(
component
.
getDistrict
());
addressInfo
.
setStreet
(
component
.
getStreet
());
addressInfo
.
setStreetNumber
(
component
.
getStreet_number
());
addressInfo
.
setFullAddress
(
result
.
getFormatted_address
());
addressInfo
.
setLng
(
lng
);
addressInfo
.
setLat
(
lat
);
}
}
catch
(
Exception
e
)
{
System
.
err
.
println
(
"逆地理编码失败:"
+
e
.
getMessage
());
e
.
printStackTrace
();
}
return
addressInfo
;
}
/**
* 2. 获取省→市→区三级嵌套列表(匹配前端)
*/
public
List
<
RegionNode
>
getTripleLevelRegion
()
{
List
<
RegionNode
>
regionList
=
new
ArrayList
<>();
try
{
String
requestUrl
=
String
.
format
(
DISTRICT_TRIPLE_URL
,
API_KEY
);
Request
request
=
new
Request
.
Builder
().
url
(
requestUrl
).
get
().
build
();
try
(
Response
response
=
OK_HTTP_CLIENT
.
newCall
(
request
).
execute
())
{
if
(!
response
.
isSuccessful
())
{
throw
new
IOException
(
"三级区划请求失败,响应码:"
+
response
.
code
());
}
DistrictResponse
resp
=
GSON
.
fromJson
(
response
.
body
().
string
(),
DistrictResponse
.
class
);
if
(
resp
.
getStatus
()
!=
0
)
{
throw
new
IOException
(
"三级区划API失败:"
+
resp
.
getMessage
());
}
// 转换为前端结构
if
(
resp
.
getResult
()
!=
null
&&
!
resp
.
getResult
().
isEmpty
())
{
for
(
ProvinceItem
province
:
resp
.
getResult
())
{
RegionNode
provinceNode
=
new
RegionNode
(
province
.
getFullname
(),
province
.
getId
());
if
(
province
.
getDistricts
()
!=
null
&&
!
province
.
getDistricts
().
isEmpty
())
{
for
(
CityItem
city
:
province
.
getDistricts
())
{
RegionNode
cityNode
=
new
RegionNode
(
city
.
getFullname
(),
city
.
getId
());
if
(
city
.
getDistricts
()
!=
null
&&
!
city
.
getDistricts
().
isEmpty
())
{
for
(
DistrictItem
district
:
city
.
getDistricts
())
{
cityNode
.
getChildren
().
add
(
new
RegionNode
(
district
.
getFullname
(),
district
.
getId
()));
}
}
provinceNode
.
getChildren
().
add
(
cityNode
);
}
}
regionList
.
add
(
provinceNode
);
}
}
}
}
catch
(
Exception
e
)
{
System
.
err
.
println
(
"生成三级区划失败:"
+
e
.
getMessage
());
e
.
printStackTrace
();
}
return
regionList
;
}
// ==================== 缓存预热 ====================
@PostConstruct
public
void
preloadCache
()
{
// 预热三级区划缓存
new
Thread
(()
->
{
try
{
List
<
RegionNode
>
regionList
=
getTripleLevelRegion
();
if
(!
regionList
.
isEmpty
())
{
stringRedisTemplate
.
opsForValue
().
set
(
"promotion:district:triple_level"
,
GSON
.
toJson
(
regionList
),
86400L
,
TimeUnit
.
SECONDS
);
}
}
catch
(
Exception
e
)
{
System
.
err
.
println
(
"三级区划缓存预热失败:"
+
e
.
getMessage
());
}
}).
start
();
}
}
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论