Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
W
wangxiaolu-sfa-common-core
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
sfa
wangxiaolu-sfa-common-core
Commits
957fd5e5
提交
957fd5e5
authored
12月 31, 2025
作者:
douxy
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
新增同步【基本单位建议零售价】到勤策
上级
2b8f7eb2
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
191 行增加
和
0 行删除
+191
-0
FeiShuUtil.java
src/main/java/com/sfa/common/core/utils/sdk/FeiShuUtil.java
+191
-0
没有找到文件。
src/main/java/com/sfa/common/core/utils/sdk/FeiShuUtil.java
浏览文件 @
957fd5e5
...
@@ -24,14 +24,20 @@ import com.lark.oapi.service.corehr.v1.model.SearchOffboardingReq;
...
@@ -24,14 +24,20 @@ import com.lark.oapi.service.corehr.v1.model.SearchOffboardingReq;
import
com.lark.oapi.service.corehr.v1.model.SearchOffboardingReqBody
;
import
com.lark.oapi.service.corehr.v1.model.SearchOffboardingReqBody
;
import
com.lark.oapi.service.corehr.v1.model.SearchOffboardingResp
;
import
com.lark.oapi.service.corehr.v1.model.SearchOffboardingResp
;
import
com.lark.oapi.service.corehr.v2.model.*
;
import
com.lark.oapi.service.corehr.v2.model.*
;
import
com.lark.oapi.service.im.v1.model.CreateMessageReq
;
import
com.lark.oapi.service.im.v1.model.CreateMessageReqBody
;
import
com.lark.oapi.service.im.v1.model.CreateMessageResp
;
import
com.sfa.common.core.enums.ECode
;
import
com.sfa.common.core.enums.ECode
;
import
com.sfa.common.core.exception.ServiceException
;
import
com.sfa.common.core.exception.ServiceException
;
import
com.sfa.common.core.exception.auth.NotLoginException
;
import
com.sfa.common.core.exception.auth.NotLoginException
;
import
org.apache.commons.lang3.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
java.math.BigDecimal
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -65,6 +71,12 @@ public class FeiShuUtil {
...
@@ -65,6 +71,12 @@ public class FeiShuUtil {
@Value
(
"${feishu.lbxy_redirectUri}"
)
@Value
(
"${feishu.lbxy_redirectUri}"
)
private
String
lbxyRedirectUri
;
private
String
lbxyRedirectUri
;
/**
* 推送异常信息给指定用户
*/
@Value
(
"${feishu.message.user_open_id}"
)
private
String
receiveId
;
/**
/**
* 飞书群机器人推送,此机器人为勤策消息通知机器人
* 飞书群机器人推送,此机器人为勤策消息通知机器人
*/
*/
...
@@ -84,6 +96,8 @@ public class FeiShuUtil {
...
@@ -84,6 +96,8 @@ public class FeiShuUtil {
private
static
final
String
VALUES
=
"/values"
;
private
static
final
String
VALUES
=
"/values"
;
private
static
final
String
STYLE
=
"/style"
;
private
static
final
String
STYLE
=
"/style"
;
private
static
final
String
RECEIVE_ID_TYPE
=
"open_id"
;
/**
/**
* 根据用户的登录临时code获取useraccessToken
* 根据用户的登录临时code获取useraccessToken
...
@@ -463,6 +477,183 @@ public class FeiShuUtil {
...
@@ -463,6 +477,183 @@ public class FeiShuUtil {
}
}
/**
* 从审批信息字符串中提取核心业务值(产品名称、编码、箱规、供货价等)
* @param approvalInfoStr 完整的审批信息JSON字符串(包含form字段的那个字符串)
* @return 提取的核心值Map:key=字段名,value=字段值(已做类型转换)
*/
public
Map
<
String
,
Object
>
getApprovalFormValues
(
String
approvalInfoStr
)
{
// 定义返回的核心值Map,key用固定标识方便调用,value存对应值
Map
<
String
,
Object
>
formValueMap
=
new
HashMap
<>();
// 初始化默认值,避免空指针
// 产品名称(字符串)
formValueMap
.
put
(
"productName"
,
null
);
// 产品编码(字符串)
formValueMap
.
put
(
"productCode"
,
null
);
// 产品规格(字符串)
formValueMap
.
put
(
"productSpec"
,
null
);
// 2B供货价(BigDecimal)
formValueMap
.
put
(
"supplyPrice"
,
null
);
// 标准成本(BigDecimal)
formValueMap
.
put
(
"standardCost"
,
null
);
try
{
// 校验入参
if
(
StringUtils
.
isBlank
(
approvalInfoStr
))
{
log
.
error
(
"审批信息字符串为空,无法提取字段值"
);
return
formValueMap
;
}
// 解析审批信息JSON字符串
JSONObject
approvalJson
=
JSONObject
.
parseObject
(
approvalInfoStr
);
// 提取form字段(字符串类型的JSON数组)并解析
String
formStr
=
approvalJson
.
getString
(
"form"
);
if
(
StringUtils
.
isBlank
(
formStr
))
{
log
.
error
(
"审批信息中form字段为空,无法提取字段值"
);
return
formValueMap
;
}
JSONArray
formFields
=
JSONArray
.
parseArray
(
formStr
);
// 4遍历form数组,提取核心值(按字段名精准匹配)
for
(
int
i
=
0
;
i
<
formFields
.
size
();
i
++)
{
JSONObject
field
=
formFields
.
getJSONObject
(
i
);
String
fieldName
=
field
.
getString
(
"name"
);
Object
fieldValue
=
field
.
get
(
"value"
);
// 跳过空字段名/空值
if
(
StringUtils
.
isBlank
(
fieldName
)
||
fieldValue
==
null
)
{
continue
;
}
// 按业务需求提取指定字段,做类型转换和容错
switch
(
fieldName
)
{
case
"产品名称"
:
formValueMap
.
put
(
"productName"
,
fieldValue
.
toString
().
trim
());
break
;
case
"产品编码"
:
formValueMap
.
put
(
"productCode"
,
fieldValue
.
toString
().
trim
());
break
;
case
"产品箱规"
:
try
{
Integer
spec
=
Integer
.
parseInt
(
fieldValue
.
toString
().
trim
());
formValueMap
.
put
(
"productSpec"
,
spec
);
}
catch
(
NumberFormatException
e
)
{
log
.
error
(
"产品箱规格式错误,值为:{}"
,
fieldValue
);
formValueMap
.
put
(
"productSpec"
,
null
);
}
break
;
case
"2B供货价/出厂价(与T100一致的最小售卖单元)"
:
try
{
BigDecimal
price
=
new
BigDecimal
(
fieldValue
.
toString
().
trim
());
formValueMap
.
put
(
"supplyPrice"
,
price
);
}
catch
(
NumberFormatException
e
)
{
log
.
error
(
"2B供货价格式错误,值为:{}"
,
fieldValue
);
formValueMap
.
put
(
"supplyPrice"
,
null
);
}
break
;
case
"标准成本(与T100一致的最小售卖单元)"
:
try
{
BigDecimal
cost
=
new
BigDecimal
(
fieldValue
.
toString
().
trim
());
formValueMap
.
put
(
"standardCost"
,
cost
);
}
catch
(
NumberFormatException
e
)
{
log
.
error
(
"标准成本格式错误,值为:{}"
,
fieldValue
);
formValueMap
.
put
(
"standardCost"
,
null
);
}
break
;
// 如需提取其他字段,直接在case里添加即可
default
:
break
;
}
}
log
.
info
(
"审批信息字段提取完成,结果:{}"
,
formValueMap
);
}
catch
(
Exception
e
)
{
log
.
error
(
"解析审批信息、提取字段值异常"
,
e
);
}
return
formValueMap
;
}
/**
* 飞书机器人推送单聊消息给指定工号的用户
* @param message 推送的消息内容
* @return 是否推送成功
*/
public
boolean
sendMessageToUserByEmployeeId
(
String
message
)
{
Client
client
=
getClientLUZX
();
try
{
// 构建消息发送请求(SDK封装的请求对象)
CreateMessageReq
req
=
CreateMessageReq
.
newBuilder
()
// 核心:指定ID类型(对应open_id/user_id等)
.
receiveIdType
(
RECEIVE_ID_TYPE
)
// 消息体配置
.
createMessageReqBody
(
CreateMessageReqBody
.
newBuilder
()
// 接收者ID(如open_id)
.
receiveId
(
receiveId
)
// 消息类型:文本
.
msgType
(
"text"
)
// 消息内容:需封装为JSON字符串(SDK要求)
.
content
(
"{\"text\":\""
+
message
.
replace
(
"\""
,
"\\\""
)
+
"\"}"
)
.
build
())
.
build
();
// 4. 调用SDK的消息发送接口(无需手动处理token,SDK自动维护)
CreateMessageResp
resp
=
client
.
im
().
v1
().
message
().
create
(
req
);
// 5. 结果校验
if
(!
resp
.
success
())
{
// 失败时打印详细错误信息
log
.
error
(
"SDK发消息失败:code={}, msg={}, reqId={}, 错误详情={}"
,
resp
.
getCode
(),
resp
.
getMsg
(),
resp
.
getRequestId
(),
new
String
(
resp
.
getRawResponse
().
getBody
(),
UTF_8
));
return
false
;
}
// 6. 成功返回,可获取消息ID
log
.
info
(
"SDK发消息成功:receiveId={}, 消息ID={}"
,
receiveId
,
resp
.
getData
().
getMessageId
());
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"SDK发消息异常:receiveIdType={}, receiveId={}"
,
RECEIVE_ID_TYPE
,
receiveId
,
e
);
return
false
;
}
}
/**
* 获取luzx应用的tenant_access_token
* 链路中心应用专用,用于审批接口调用
*/
public
String
getLuzxTenantToken
()
{
try
{
Map
<
String
,
Object
>
bodyMap
=
new
HashMap
<>();
bodyMap
.
put
(
"app_id"
,
appId
);
bodyMap
.
put
(
"app_secret"
,
appSecret
);
String
bodyJson
=
JSONObject
.
toJSONString
(
bodyMap
);
// 调用飞书tenant_token获取接口
String
result
=
HttpUtil
.
createPost
(
TENANT_ACCESS_TOKEN_URL
)
.
contentType
(
CONTENT_TYPE
)
.
body
(
bodyJson
)
.
execute
().
body
();
JSONObject
resultJson
=
JSONObject
.
parseObject
(
result
);
int
code
=
resultJson
.
getInteger
(
"code"
);
if
(
code
!=
0
)
{
throw
new
RuntimeException
(
"获取luzx应用tenant_token失败:"
+
resultJson
.
getString
(
"msg"
));
}
String
luzxToken
=
resultJson
.
getString
(
"tenant_access_token"
);
log
.
info
(
"成功获取luzx应用tenant_token:{}(脱敏后:{})"
,
luzxToken
,
luzxToken
.
substring
(
0
,
10
)
+
"****"
+
luzxToken
.
substring
(
luzxToken
.
length
()-
10
));
return
luzxToken
;
}
catch
(
Exception
e
)
{
log
.
error
(
"获取luzx应用tenant_token异常"
,
e
);
throw
new
RuntimeException
(
"获取luzx token失败,无法调用审批接口"
);
}
}
@Value
(
"${feishu.group_robot.qince_webhook}"
)
@Value
(
"${feishu.group_robot.qince_webhook}"
)
public
void
setQinceWebhook
(
String
qinceWebhook
)
{
public
void
setQinceWebhook
(
String
qinceWebhook
)
{
FeiShuUtil
.
qinceWebhook
=
qinceWebhook
;
FeiShuUtil
.
qinceWebhook
=
qinceWebhook
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论