Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
0d2f60f7
authored
Sep 18, 2026
by
renyizhao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
商品可永久 newapi登录修改
parent
17beaa7b
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
206 additions
and
42 deletions
+206
-42
build.out
+0
-0
computility-module-apihub/computility-module-apihub-biz/src/main/java/com/luhu/computility/module/apihub/controller/admin/newapi/NewApiLoginRespVO.java
+39
-0
computility-module-apihub/computility-module-apihub-biz/src/main/java/com/luhu/computility/module/apihub/service/newapi/AiTokenService.java
+9
-22
computility-module-apihub/computility-module-apihub-biz/src/main/java/com/luhu/computility/module/apihub/service/newapi/NewApiClient.java
+89
-4
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourcesku/vo/ResourceSkuSaveReqVO.java
+3
-2
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/app/resourceordersnapshot/vo/AppResourceOrderSnapshotSaveReqVO.java
+3
-1
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/app/resourcesku/AppResourceSkuController.java
+4
-2
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/service/resourceorder/ResourceOrderServiceImpl.java
+26
-7
computility-server/src/main/resources/application-local.yaml
+2
-4
sql/migration/2026_09_17_add_compute_resource_duration_permanent.sql
+31
-0
No files found.
build.out
0 → 100644
View file @
0d2f60f7
This diff is collapsed.
Click to expand it.
computility-module-apihub/computility-module-apihub-biz/src/main/java/com/luhu/computility/module/apihub/controller/admin/newapi/NewApiLoginRespVO.java
0 → 100644
View file @
0d2f60f7
package
com
.
luhu
.
computility
.
module
.
apihub
.
controller
.
admin
.
newapi
;
import
lombok.AllArgsConstructor
;
import
lombok.experimental.Accessors
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
/**
* NewAPI /api/user/login 响应 data 字段映射
*
* <p>NewAPI v3 登录成功时,data 顶层字段结构:
* <pre>
* {
* "access_token": "...",
* "token_type": "Bearer",
* "access_expires_at": ...,
* "session": { ... },
* "user": { "id": 123, "username": "...", ... }
* }
* </pre>
* 之前 puhui 错误地把整个 data 映射到 NewApiUserVO,导致 id 等字段全为 null;
* 本 VO 直接持有 access_token 和嵌套 user.id,避免再次去取 session cookie / 走 /api/user/token 生成访问令牌。
*/
@Data
@Accessors
(
chain
=
true
)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public
class
NewApiLoginRespVO
{
/** data.access_token:可直接作为后续接口的 Bearer 凭据 */
private
String
accessToken
;
/** data.token_type(如 "Bearer") */
private
String
tokenType
;
/** data.user.id:NewAPI 用户 ID */
private
Long
userId
;
/** data.user.username:冗余,便于日志/持久化 */
private
String
username
;
}
computility-module-apihub/computility-module-apihub-biz/src/main/java/com/luhu/computility/module/apihub/service/newapi/AiTokenService.java
View file @
0d2f60f7
...
@@ -83,44 +83,31 @@ public class AiTokenService {
...
@@ -83,44 +83,31 @@ public class AiTokenService {
log
.
info
(
"[AiTokenService.createTokenStep2] 准备登录: username={}"
,
username
);
log
.
info
(
"[AiTokenService.createTokenStep2] 准备登录: username={}"
,
username
);
try
{
try
{
NewApiResponse
<
NewApi
User
VO
>
loginResp
=
newApiClient
.
login
(
username
,
password
);
NewApiResponse
<
NewApi
LoginResp
VO
>
loginResp
=
newApiClient
.
login
(
username
,
password
);
log
.
info
(
"[AiTokenService.createTokenStep2] 登录结果: success={}, message={}"
,
loginResp
.
getSuccess
(),
loginResp
.
getMessage
());
log
.
info
(
"[AiTokenService.createTokenStep2] 登录结果: success={}, message={}"
,
loginResp
.
getSuccess
(),
loginResp
.
getMessage
());
if
(!
Boolean
.
TRUE
.
equals
(
loginResp
.
getSuccess
())
||
loginResp
.
getData
()
==
null
)
{
if
(!
Boolean
.
TRUE
.
equals
(
loginResp
.
getSuccess
())
||
loginResp
.
getData
()
==
null
)
{
return
AiTokenResult
.
builder
()
return
AiTokenResult
.
builder
()
.
success
(
false
)
.
success
(
false
)
.
message
(
"登录NewAPI失败: "
+
loginResp
.
getMessage
())
.
message
(
"登录NewAPI失败: "
+
loginResp
.
getMessage
())
.
build
();
}
Integer
newApiUserId
=
loginResp
.
getData
().
getId
();
log
.
info
(
"[AiTokenService.createTokenStep2] 登录成功, newApiUserId={}"
,
newApiUserId
);
String
session
=
newApiClient
.
getSessionCookie
(
loginResp
.
getHttpResponse
());
log
.
info
(
"[AiTokenService.createTokenStep2] 获取session: {}"
,
session
!=
null
?
"成功"
:
"失败"
);
NewApiResponse
<
String
>
tokenResp
=
newApiClient
.
generateAccessToken
(
session
,
newApiUserId
);
log
.
info
(
"[AiTokenService.createTokenStep2] 生成AccessToken结果: success={}, message={}"
,
tokenResp
.
getSuccess
(),
tokenResp
.
getMessage
());
if
(!
Boolean
.
TRUE
.
equals
(
tokenResp
.
getSuccess
())
||
tokenResp
.
getData
()
==
null
)
{
return
AiTokenResult
.
builder
()
.
success
(
false
)
.
message
(
"生成访问令牌失败: "
+
tokenResp
.
getMessage
())
.
newApiUsername
(
username
)
.
newApiUsername
(
username
)
.
newApiPassword
(
password
)
.
newApiPassword
(
password
)
.
newApiUserId
(
newApiUserId
.
longValue
())
.
build
();
.
build
();
}
}
String
accessToken
=
tokenResp
.
getData
();
Long
newApiUserId
=
loginResp
.
getData
().
getUserId
();
log
.
info
(
"[AiTokenService.createTokenStep2] AccessToken生成成功: {}***"
,
accessToken
.
substring
(
0
,
Math
.
min
(
5
,
accessToken
.
length
())));
String
accessToken
=
loginResp
.
getData
().
getAccessToken
();
log
.
info
(
"[AiTokenService.createTokenStep2] 登录成功, newApiUserId={}, accessToken={}***"
,
newApiUserId
,
accessToken
.
substring
(
0
,
Math
.
min
(
5
,
accessToken
.
length
())));
return
createTokenStep4
(
newApiUserId
,
accessToken
,
userId
,
username
,
password
);
// NewAPI v3 登录响应已直接返回 access_token,无需再调 /api/user/token;
// 直接以该 token 作为 Bearer 凭据进入 step4 创建 API Key。
return
createTokenStep4
(
newApiUserId
.
intValue
(),
accessToken
,
userId
,
username
,
password
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
error
(
"[AiTokenService.createTokenStep2] 登录异常"
,
e
);
log
.
error
(
"[AiTokenService.createTokenStep2] 登录异常"
,
e
);
return
AiTokenResult
.
builder
()
return
AiTokenResult
.
builder
()
.
success
(
false
)
.
success
(
false
)
.
message
(
"登录NewAPI异常: "
+
e
.
getMessage
(
))
.
message
(
"登录NewAPI异常: "
+
(
e
.
getMessage
()
==
null
?
e
.
getClass
().
getSimpleName
()
:
e
.
getMessage
()
))
.
newApiUsername
(
username
)
.
newApiUsername
(
username
)
.
newApiPassword
(
password
)
.
newApiPassword
(
password
)
.
build
();
.
build
();
...
...
computility-module-apihub/computility-module-apihub-biz/src/main/java/com/luhu/computility/module/apihub/service/newapi/NewApiClient.java
View file @
0d2f60f7
...
@@ -96,7 +96,22 @@ public class NewApiClient {
...
@@ -96,7 +96,22 @@ public class NewApiClient {
}
}
}
}
public
NewApiResponse
<
NewApiUserVO
>
login
(
String
username
,
String
password
)
{
/**
* 用户登录(NewAPI v3 /api/user/login)
*
* <p>NewAPI v3 登录响应 data 字段结构:
* <pre>
* {
* "access_token": "...", // 直接可用作 Bearer 凭据
* "token_type": "Bearer",
* "user": { "id": 123, "username": "...", ... }
* }
* </pre>
* 旧实现错误地把整个 data 映射到 NewApiUserVO,导致 userId 拿不到;
* 本方法改为显式从 data.access_token 和 data.user.id 取值,避免依赖
* session cookie 和后续 /api/user/token 步骤。
*/
public
NewApiResponse
<
NewApiLoginRespVO
>
login
(
String
username
,
String
password
)
{
String
url
=
newApiProperties
.
getBaseUrl
()
+
"/api/user/login"
;
String
url
=
newApiProperties
.
getBaseUrl
()
+
"/api/user/login"
;
log
.
info
(
"[NewApiClient.login] 请求URL: {}"
,
url
);
log
.
info
(
"[NewApiClient.login] 请求URL: {}"
,
url
);
...
@@ -113,18 +128,88 @@ public class NewApiClient {
...
@@ -113,18 +128,88 @@ public class NewApiClient {
.
execute
();
.
execute
();
log
.
info
(
"[NewApiClient.login] 响应状态: {}"
,
response
.
getStatus
());
log
.
info
(
"[NewApiClient.login] 响应状态: {}"
,
response
.
getStatus
());
log
.
info
(
"[NewApiClient.login] 响应Cookie: {}"
,
response
.
getCookies
());
return
parseResponse
(
response
,
NewApiUserVO
.
class
);
NewApiResponse
<
NewApiLoginRespVO
>
resp
=
parseLoginResponse
(
response
);
resp
.
setHttpResponse
(
response
);
return
resp
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
error
(
"[NewApiClient.login] 请求异常"
,
e
);
log
.
error
(
"[NewApiClient.login] 请求异常"
,
e
);
return
NewApiResponse
.<
NewApi
User
VO
>
builder
()
return
NewApiResponse
.<
NewApi
LoginResp
VO
>
builder
()
.
success
(
false
)
.
success
(
false
)
.
message
(
"请求异常: "
+
e
.
getMessage
())
.
message
(
"请求异常: "
+
e
.
getMessage
())
.
build
();
.
build
();
}
}
}
}
/**
* 解析 NewAPI /api/user/login 响应
*
* <p>只关心 data.access_token、data.token_type、data.user.id、data.user.username;
* 不抛异常,统一返回 NewApiResponse 调用方判断。
*/
private
NewApiResponse
<
NewApiLoginRespVO
>
parseLoginResponse
(
HttpResponse
response
)
{
try
{
String
body
=
response
.
body
();
if
(
StrUtil
.
isBlank
(
body
))
{
return
NewApiResponse
.<
NewApiLoginRespVO
>
builder
()
.
success
(
false
)
.
message
(
"Empty response"
)
.
build
();
}
JSONObject
json
=
JSONUtil
.
parseObj
(
body
);
NewApiResponse
<
NewApiLoginRespVO
>
result
=
new
NewApiResponse
<>();
result
.
setSuccess
(
json
.
getBool
(
"success"
));
result
.
setMessage
(
json
.
getStr
(
"message"
));
if
(!
Boolean
.
TRUE
.
equals
(
json
.
getBool
(
"success"
)))
{
return
result
;
}
JSONObject
data
=
json
.
getJSONObject
(
"data"
);
if
(
data
==
null
)
{
return
NewApiResponse
.<
NewApiLoginRespVO
>
builder
()
.
success
(
false
)
.
message
(
"登录响应缺少 data 字段"
)
.
build
();
}
NewApiLoginRespVO
vo
=
new
NewApiLoginRespVO
();
vo
.
setAccessToken
(
data
.
getStr
(
"access_token"
));
vo
.
setTokenType
(
data
.
getStr
(
"token_type"
));
JSONObject
user
=
data
.
getJSONObject
(
"user"
);
if
(
user
!=
null
)
{
Object
idObj
=
user
.
get
(
"id"
);
if
(
idObj
instanceof
Number
)
{
vo
.
setUserId
(((
Number
)
idObj
).
longValue
());
}
else
if
(
idObj
!=
null
)
{
try
{
vo
.
setUserId
(
Long
.
parseLong
(
idObj
.
toString
()));
}
catch
(
NumberFormatException
ignored
)
{
}
}
vo
.
setUsername
(
user
.
getStr
(
"username"
));
}
if
(
vo
.
getAccessToken
()
==
null
||
vo
.
getAccessToken
().
isEmpty
()
||
vo
.
getUserId
()
==
null
)
{
return
NewApiResponse
.<
NewApiLoginRespVO
>
builder
()
.
success
(
false
)
.
message
(
"登录响应缺少 access_token 或 user.id"
)
.
build
();
}
result
.
setData
(
vo
);
return
result
;
}
catch
(
Exception
e
)
{
log
.
error
(
"[NewApiClient.parseLoginResponse] 解析响应异常"
,
e
);
return
NewApiResponse
.<
NewApiLoginRespVO
>
builder
()
.
success
(
false
)
.
message
(
"解析响应失败: "
+
e
.
getMessage
())
.
build
();
}
}
public
String
getSessionCookie
(
HttpResponse
loginResponse
)
{
public
String
getSessionCookie
(
HttpResponse
loginResponse
)
{
String
session
=
loginResponse
.
getCookieValue
(
"session"
);
String
session
=
loginResponse
.
getCookieValue
(
"session"
);
log
.
info
(
"[NewApiClient.getSessionCookie] session={}"
,
session
!=
null
?
session
:
"null"
);
log
.
info
(
"[NewApiClient.getSessionCookie] session={}"
,
session
!=
null
?
session
:
"null"
);
...
...
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourcesku/vo/ResourceSkuSaveReqVO.java
View file @
0d2f60f7
...
@@ -18,8 +18,9 @@ public class ResourceSkuSaveReqVO {
...
@@ -18,8 +18,9 @@ public class ResourceSkuSaveReqVO {
@NotNull
(
message
=
"关联的SPU ID不能为空"
)
@NotNull
(
message
=
"关联的SPU ID不能为空"
)
private
Long
spuId
;
private
Long
spuId
;
@Schema
(
description
=
"租赁天数(30/90/365等)"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@Schema
(
description
=
"租赁天数(30/90/365等;0=永久)"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotNull
(
message
=
"租赁天数(30/90/365等)不能为空"
)
@NotNull
(
message
=
"租赁天数不能为空"
)
@Min
(
value
=
0
,
message
=
"租赁天数不能小于 0"
)
private
Integer
durationDays
;
private
Integer
durationDays
;
@Schema
(
description
=
"支付价格(单位:分)"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"22794"
)
@Schema
(
description
=
"支付价格(单位:分)"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"22794"
)
...
...
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/app/resourceordersnapshot/vo/AppResourceOrderSnapshotSaveReqVO.java
View file @
0d2f60f7
...
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
...
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import
lombok.Data
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
lombok.experimental.Accessors
;
import
javax.validation.constraints.Min
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.NotNull
;
import
javax.validation.constraints.NotNull
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
...
@@ -52,8 +53,9 @@ public class AppResourceOrderSnapshotSaveReqVO {
...
@@ -52,8 +53,9 @@ public class AppResourceOrderSnapshotSaveReqVO {
// - 数据库 spu_name 列允许 NULL
// - 数据库 spu_name 列允许 NULL
private
String
spuName
;
private
String
spuName
;
@Schema
(
description
=
"租赁天数
"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"7"
)
@Schema
(
description
=
"租赁天数
(0=永久)"
,
example
=
"7"
)
@NotNull
(
message
=
"租赁天数不能为空"
)
@NotNull
(
message
=
"租赁天数不能为空"
)
@Min
(
value
=
0
,
message
=
"租赁天数不能小于 0"
)
private
Integer
durationDays
;
private
Integer
durationDays
;
@Schema
(
description
=
"租赁开始时间"
)
@Schema
(
description
=
"租赁开始时间"
)
...
...
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/app/resourcesku/AppResourceSkuController.java
View file @
0d2f60f7
...
@@ -76,7 +76,8 @@ public class AppResourceSkuController {
...
@@ -76,7 +76,8 @@ public class AppResourceSkuController {
respVO
.
setName
(
spuVo
.
getName
());
respVO
.
setName
(
spuVo
.
getName
());
respVO
.
setRemark
(
spuVo
.
getIntro
());
respVO
.
setRemark
(
spuVo
.
getIntro
());
respVO
.
setPrice
(
sku
.
getPaymentPrice
());
respVO
.
setPrice
(
sku
.
getPaymentPrice
());
respVO
.
setFeeInfo
(
sku
.
getDurationDays
()
+
"天"
);
// duration_days=0 表示永久,前端「/X天」后缀置空
respVO
.
setFeeInfo
(
sku
.
getDurationDays
()
!=
null
&&
sku
.
getDurationDays
()
>
0
?
sku
.
getDurationDays
()
+
"天"
:
""
);
respVO
.
setSpecMap
(
spuVo
.
getSpecMap
());
respVO
.
setSpecMap
(
spuVo
.
getSpecMap
());
respVO
.
setLocation
(
spuVo
.
getLocation
());
respVO
.
setLocation
(
spuVo
.
getLocation
());
return
respVO
;
return
respVO
;
...
@@ -102,7 +103,8 @@ public class AppResourceSkuController {
...
@@ -102,7 +103,8 @@ public class AppResourceSkuController {
respVO
.
setName
(
resourceSpuVo
.
getName
());
respVO
.
setName
(
resourceSpuVo
.
getName
());
respVO
.
setRemark
(
resourceSpuVo
.
getIntro
());
respVO
.
setRemark
(
resourceSpuVo
.
getIntro
());
respVO
.
setPrice
(
resourceSku
.
getPaymentPrice
());
respVO
.
setPrice
(
resourceSku
.
getPaymentPrice
());
respVO
.
setFeeInfo
(
resourceSku
.
getDurationDays
()
+
"天"
);
// duration_days=0 表示永久,前端「/X天」后缀置空
respVO
.
setFeeInfo
(
resourceSku
.
getDurationDays
()
!=
null
&&
resourceSku
.
getDurationDays
()
>
0
?
resourceSku
.
getDurationDays
()
+
"天"
:
""
);
respVO
.
setSpecMap
(
resourceSpuVo
.
getSpecMap
());
respVO
.
setSpecMap
(
resourceSpuVo
.
getSpecMap
());
respVO
.
setLocation
(
resourceSpuVo
.
getLocation
());
respVO
.
setLocation
(
resourceSpuVo
.
getLocation
());
return
success
(
respVO
);
return
success
(
respVO
);
...
...
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/service/resourceorder/ResourceOrderServiceImpl.java
View file @
0d2f60f7
...
@@ -249,7 +249,11 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
...
@@ -249,7 +249,11 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
.
setAppKey
(
resourceOrderProperties
.
getPayAppKey
()).
setUserIp
(
order
.
getUserIp
());
.
setAppKey
(
resourceOrderProperties
.
getPayAppKey
()).
setUserIp
(
order
.
getUserIp
());
// 商户相关字段
// 商户相关字段
payOrderCreateReqDTO
.
setMerchantOrderId
(
String
.
valueOf
(
order
.
getId
()));
payOrderCreateReqDTO
.
setMerchantOrderId
(
String
.
valueOf
(
order
.
getId
()));
String
subject
=
order
.
getSpuName
()
+
" - "
+
getDurationDaysFromSku
(
order
.
getSkuId
())
+
"天"
;
// 永久订单(durationDays=0)只拼 SPU 名,不带「 - X天」后缀
Integer
payDurationDays
=
getDurationDaysFromSku
(
order
.
getSkuId
());
String
subject
=
(
payDurationDays
!=
null
&&
payDurationDays
>
0
)
?
order
.
getSpuName
()
+
" - "
+
payDurationDays
+
"天"
:
order
.
getSpuName
();
subject
=
StrUtils
.
maxLength
(
subject
,
PayOrderCreateReqDTO
.
SUBJECT_MAX_LENGTH
);
// 避免超过 32 位
subject
=
StrUtils
.
maxLength
(
subject
,
PayOrderCreateReqDTO
.
SUBJECT_MAX_LENGTH
);
// 避免超过 32 位
payOrderCreateReqDTO
.
setSubject
(
subject
);
payOrderCreateReqDTO
.
setSubject
(
subject
);
payOrderCreateReqDTO
.
setBody
(
subject
);
payOrderCreateReqDTO
.
setBody
(
subject
);
...
@@ -463,7 +467,10 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
...
@@ -463,7 +467,10 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
if
(
snapshot
.
getSpecSnapshot
()
!=
null
)
{
if
(
snapshot
.
getSpecSnapshot
()
!=
null
)
{
respVO
.
setSpecMap
(
JSONUtil
.
toBean
(
snapshot
.
getSpecSnapshot
(),
Map
.
class
));
respVO
.
setSpecMap
(
JSONUtil
.
toBean
(
snapshot
.
getSpecSnapshot
(),
Map
.
class
));
}
}
respVO
.
setSkuName
(
snapshot
.
getSpuName
()
+
" - "
+
snapshot
.
getDurationDays
()
+
"天"
);
// 永久订单(duration_days=0)只拼 SPU 名,不带「 - X天」后缀
respVO
.
setSkuName
(
snapshot
.
getDurationDays
()
!=
null
&&
snapshot
.
getDurationDays
()
>
0
?
snapshot
.
getSpuName
()
+
" - "
+
snapshot
.
getDurationDays
()
+
"天"
:
snapshot
.
getSpuName
());
// 快照中没有的字段(分类、位置)需要从SPU获取
// 快照中没有的字段(分类、位置)需要从SPU获取
ResourceSkuDO
sku
=
resourceSkuService
.
getResourceSku
(
order
.
getSkuId
());
ResourceSkuDO
sku
=
resourceSkuService
.
getResourceSku
(
order
.
getSkuId
());
...
@@ -490,7 +497,11 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
...
@@ -490,7 +497,11 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
respVO
.
setSpuName
(
spu
.
getName
());
respVO
.
setSpuName
(
spu
.
getName
());
respVO
.
setCategoryId
(
spu
.
getCategoryId
());
respVO
.
setCategoryId
(
spu
.
getCategoryId
());
respVO
.
setLocation
(
spu
.
getLocation
());
respVO
.
setLocation
(
spu
.
getLocation
());
respVO
.
setSkuName
(
spu
.
getName
()
+
" - "
+
sku
.
getDurationDays
()
+
"天"
);
// 永久订单(duration_days=0)只拼 SPU 名,不带「 - X天」后缀
Integer
legacyDurationDays
=
sku
.
getDurationDays
();
respVO
.
setSkuName
(
legacyDurationDays
!=
null
&&
legacyDurationDays
>
0
?
spu
.
getName
()
+
" - "
+
legacyDurationDays
+
"天"
:
spu
.
getName
());
// 设置分类名称
// 设置分类名称
if
(
spu
.
getCategoryId
()
!=
null
)
{
if
(
spu
.
getCategoryId
()
!=
null
)
{
...
@@ -531,7 +542,10 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
...
@@ -531,7 +542,10 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
if
(
snapshot
.
getSpecSnapshot
()
!=
null
)
{
if
(
snapshot
.
getSpecSnapshot
()
!=
null
)
{
respVO
.
setSpecMap
(
JSONUtil
.
toBean
(
snapshot
.
getSpecSnapshot
(),
Map
.
class
));
respVO
.
setSpecMap
(
JSONUtil
.
toBean
(
snapshot
.
getSpecSnapshot
(),
Map
.
class
));
}
}
respVO
.
setSkuName
(
snapshot
.
getSpuName
()
+
" - "
+
snapshot
.
getDurationDays
()
+
"天"
);
// 永久订单(duration_days=0)只拼 SPU 名,不带「 - X天」后缀
respVO
.
setSkuName
(
snapshot
.
getDurationDays
()
!=
null
&&
snapshot
.
getDurationDays
()
>
0
?
snapshot
.
getSpuName
()
+
" - "
+
snapshot
.
getDurationDays
()
+
"天"
:
snapshot
.
getSpuName
());
// 快照中没有的字段(分类、位置)需要从SPU获取
// 快照中没有的字段(分类、位置)需要从SPU获取
ResourceSkuDO
sku
=
resourceSkuService
.
getResourceSku
(
order
.
getSkuId
());
ResourceSkuDO
sku
=
resourceSkuService
.
getResourceSku
(
order
.
getSkuId
());
...
@@ -663,7 +677,11 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
...
@@ -663,7 +677,11 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
CommonWpgjCreateReqDTO
createReqDTO
=
new
CommonWpgjCreateReqDTO
();
CommonWpgjCreateReqDTO
createReqDTO
=
new
CommonWpgjCreateReqDTO
();
createReqDTO
.
setBusinessType
(
1
);
// 1-算力资源订单
createReqDTO
.
setBusinessType
(
1
);
// 1-算力资源订单
createReqDTO
.
setBusinessOrderId
(
order
.
getId
());
createReqDTO
.
setBusinessOrderId
(
order
.
getId
());
String
orderTitle
=
order
.
getSpuName
()
+
" - "
+
getDurationDaysFromSku
(
order
.
getSkuId
())
+
"天"
;
// 永久订单(durationDays=0)只拼 SPU 名,不带「 - X天」后缀
Integer
wpgjDurationDays
=
getDurationDaysFromSku
(
order
.
getSkuId
());
String
orderTitle
=
(
wpgjDurationDays
!=
null
&&
wpgjDurationDays
>
0
)
?
order
.
getSpuName
()
+
" - "
+
wpgjDurationDays
+
"天"
:
order
.
getSpuName
();
createReqDTO
.
setOrderTitle
(
orderTitle
);
createReqDTO
.
setOrderTitle
(
orderTitle
);
createReqDTO
.
setPayAmount
(
order
.
getPaymentPrice
().
intValue
());
createReqDTO
.
setPayAmount
(
order
.
getPaymentPrice
().
intValue
());
...
@@ -916,7 +934,7 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
...
@@ -916,7 +934,7 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
throw
exception
(
RESOURCE_ORDER_DELIVERY_FIELDS_REQUIRED
);
throw
exception
(
RESOURCE_ORDER_DELIVERY_FIELDS_REQUIRED
);
}
}
// 2. 取租赁天数
// 2. 取租赁天数
(0=永久,不设置结束时间)
Integer
durationDays
=
getDurationDaysFromSku
(
order
.
getSkuId
());
Integer
durationDays
=
getDurationDaysFromSku
(
order
.
getSkuId
());
if
(
durationDays
==
null
)
{
if
(
durationDays
==
null
)
{
throw
exception
(
RESOURCE_ORDER_SKU_NOT_EXISTS
);
throw
exception
(
RESOURCE_ORDER_SKU_NOT_EXISTS
);
...
@@ -924,6 +942,7 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
...
@@ -924,6 +942,7 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
// 3. 算租赁时间
// 3. 算租赁时间
LocalDateTime
now
=
LocalDateTime
.
now
();
LocalDateTime
now
=
LocalDateTime
.
now
();
LocalDateTime
rentEndTime
=
durationDays
>
0
?
now
.
plusDays
(
durationDays
)
:
null
;
// 4. 写订单
// 4. 写订单
ResourceOrderDO
updateOrder
=
new
ResourceOrderDO
();
ResourceOrderDO
updateOrder
=
new
ResourceOrderDO
();
...
@@ -934,7 +953,7 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
...
@@ -934,7 +953,7 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
updateOrder
.
setDeliveryPassword
(
reqVO
.
getDeliveryPassword
());
updateOrder
.
setDeliveryPassword
(
reqVO
.
getDeliveryPassword
());
updateOrder
.
setDeliveredTime
(
now
);
updateOrder
.
setDeliveredTime
(
now
);
updateOrder
.
setRentStartTime
(
now
);
updateOrder
.
setRentStartTime
(
now
);
updateOrder
.
setRentEndTime
(
now
.
plusDays
(
durationDays
)
);
updateOrder
.
setRentEndTime
(
rentEndTime
);
updateOrder
.
setDeliverOperatorId
(
operatorId
);
updateOrder
.
setDeliverOperatorId
(
operatorId
);
updateOrder
.
setDeliverOperatorName
(
getOperatorName
(
operatorId
));
updateOrder
.
setDeliverOperatorName
(
getOperatorName
(
operatorId
));
resourceOrderMapper
.
updateById
(
updateOrder
);
resourceOrderMapper
.
updateById
(
updateOrder
);
...
...
computility-server/src/main/resources/application-local.yaml
View file @
0d2f60f7
...
@@ -212,10 +212,8 @@ wx:
...
@@ -212,10 +212,8 @@ wx:
# 芋道配置项,设置当前项目所有自定义的配置
# 芋道配置项,设置当前项目所有自定义的配置
computility
:
computility
:
new-api
:
new-api
:
# 线上 NewAPI 地址(用于获取 /api/pricing 数据)
base-url
:
http://172.25.164.0:3000
base-url
:
http://phslgld.hnluchuan.com:3000
admin-token
:
nfcJyVtYb6xtREHA2MyL4f4o5TDg/qU=
# 线上 NewAPI 管理员 token(在 NewAPI 后台 → 用户管理 → 管理员账号详情获取)
admin-token
:
V33oMN4fI5H0wKSs0gXipXZ4WvU6DQ==
admin-user-id
:
1
admin-user-id
:
1
captcha
:
captcha
:
enable
:
false
# 本地环境,暂时关闭图片验证码,方便登录等接口的测试;
enable
:
false
# 本地环境,暂时关闭图片验证码,方便登录等接口的测试;
...
...
sql/migration/2026_09_17_add_compute_resource_duration_permanent.sql
0 → 100644
View file @
0d2f60f7
-- ============================================================
-- 算力资源 SKU「永久」租赁时长字典项
-- 库:new_computility
-- 文件:2026_09_17_add_compute_resource_duration_permanent.sql
--
-- 【背景】
-- 算力资源 SKU 原本强制要求租赁天数(30/90/365 等),不支持「永久」商品。
-- 本次放开:duration_days = 0 表示永久,下单时 rent_end_time 不设置,
-- expireFinishedOrders 定时任务依赖 BETWEEN NULL 跳过永久订单。
--
-- 【目标】
-- 给字典 compute_resource_duration 新增一条 value=0, label=永久 的选项,
-- 让管理端 SKU 表单「租赁时长」下拉框出现「永久」选项。
--
-- 【安全说明】
-- - INSERT IGNORE:已存在则跳过(id 自增会跳过,dict_type+value 唯一则跳过)
-- - 不会影响现有 30/90/365 等天数选项
-- - 不修改表结构
-- ============================================================
USE
`new_computility`
;
-- 新增「永久」字典项
INSERT
IGNORE
INTO
`system_dict_data`
(
`sort`
,
`label`
,
`value`
,
`dict_type`
,
`status`
,
`color_type`
,
`css_class`
,
`remark`
,
`creator`
,
`create_time`
,
`updater`
,
`update_time`
,
`deleted`
)
VALUES
(
0
,
'永久'
,
'0'
,
'compute_resource_duration'
,
0
,
'default'
,
''
,
'duration_days=0 表示永久租赁'
,
'1'
,
NOW
(),
'1'
,
NOW
(),
b
'0'
);
-- 验证:
-- SELECT * FROM system_dict_data WHERE dict_type = 'compute_resource_duration' ORDER BY sort;
-- 期望:除原有 30天/90天/365天 等项外,新增一条 value=0 label=永久 sort=0 的项
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