Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
cloud-platform
Project
Project
Details
Activity
Releases
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
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
youjj
cloud-platform
Commits
31d1ca15
Commit
31d1ca15
authored
Dec 30, 2019
by
jiaorz
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/dev' into dev
parents
377a736b
a5a151bf
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
124 additions
and
64 deletions
+124
-64
AppUserDetailBiz.java
...m/github/wxiaoqi/security/admin/biz/AppUserDetailBiz.java
+6
-1
IPJobHandler.java
...ithub/wxiaoqi/security/admin/jobhandler/IPJobHandler.java
+97
-0
AppUserDetailMapper.java
...ub/wxiaoqi/security/admin/mapper/AppUserDetailMapper.java
+3
-0
AppPermissionService.java
...aoqi/security/admin/rpc/service/AppPermissionService.java
+0
-50
AppUserDetailMapper.xml
...e-admin/src/main/resources/mapper/AppUserDetailMapper.xml
+5
-0
ActivityLuckyDrawBiz.java
.../com/xxfc/platform/activity/biz/ActivityLuckyDrawBiz.java
+9
-8
ActivityLuckyDrawAdminController.java
...activity/rest/admin/ActivityLuckyDrawAdminController.java
+4
-5
No files found.
ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/admin/biz/AppUserDetailBiz.java
View file @
31d1ca15
...
@@ -236,4 +236,9 @@ public class AppUserDetailBiz extends BaseBiz<AppUserDetailMapper, AppUserDetail
...
@@ -236,4 +236,9 @@ public class AppUserDetailBiz extends BaseBiz<AppUserDetailMapper, AppUserDetail
List
<
AppUserDetail
>
userDetails
=
mapper
.
selectByExample
(
example
);
List
<
AppUserDetail
>
userDetails
=
mapper
.
selectByExample
(
example
);
return
CollectionUtils
.
isEmpty
(
userDetails
)?
Collections
.
emptyList
():
userDetails
;
return
CollectionUtils
.
isEmpty
(
userDetails
)?
Collections
.
emptyList
():
userDetails
;
}
}
}
public
List
<
AppUserDetail
>
findAllUserDetailWithNoProinceCode
()
{
List
<
AppUserDetail
>
appUserDetails
=
mapper
.
selectAllWithNoProviinceCode
();
return
CollectionUtils
.
isEmpty
(
appUserDetails
)?
Collections
.
EMPTY_LIST
:
appUserDetails
;
}
}
ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/admin/jobhandler/IPJobHandler.java
0 → 100644
View file @
31d1ca15
package
com
.
github
.
wxiaoqi
.
security
.
admin
.
jobhandler
;
import
com.alibaba.fastjson.JSONObject
;
import
com.github.wxiaoqi.security.admin.biz.AppUserDetailBiz
;
import
com.github.wxiaoqi.security.admin.entity.AppUserDetail
;
import
com.xxfc.platform.universal.dto.RegionDTO
;
import
com.xxfc.platform.universal.feign.RegionFeign
;
import
com.xxl.job.core.biz.model.ReturnT
;
import
com.xxl.job.core.handler.IJobHandler
;
import
com.xxl.job.core.handler.annotation.JobHandler
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.client.RestTemplate
;
import
java.util.List
;
/**
* @author libin
* @version 1.0
* @description
* @data 2019/12/27 11:14
*/
@JobHandler
(
value
=
"ipAnalyticalJobHandler"
)
@Component
@RequiredArgsConstructor
(
onConstructor
=
@__
(
@Autowired
))
@Slf4j
//@RefreshScope
public
class
IPJobHandler
extends
IJobHandler
{
private
final
RestTemplate
restTemplate
;
private
final
RegionFeign
regionFeign
;
private
final
AppUserDetailBiz
appUserDetailBiz
;
private
static
final
Integer
PROVINCECODE
=
440000
;
@Value
(
"${ip.analytical.appId:xcjtqjromfuvjjtt}"
)
private
String
appId
;
@Value
(
"${ip.analytical.secret:bzNRK3FUR2d3WGc0MmhKWGZINm5MQT09}"
)
private
String
secret
;
@Override
public
ReturnT
<
String
>
execute
(
String
s
)
throws
Exception
{
List
<
AppUserDetail
>
appUserDetails
=
appUserDetailBiz
.
findAllUserDetailWithNoProinceCode
();
for
(
AppUserDetail
appUserDetail
:
appUserDetails
)
{
String
crtHost
=
appUserDetail
.
getCrtHost
();
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"解析的地址:【{}】"
,
crtHost
+
"---time==="
+
System
.
currentTimeMillis
()
/
1000L
);
}
try
{
analyticalIPByWebSiteAndIPAddress
(
IPAddress
.
BASE_IP_PARSING_URL2
,
crtHost
,
appUserDetail
);
}
catch
(
Exception
e
)
{
try
{
analyticalIPByWebSiteAndIPAddress
(
IPAddress
.
BASE_IP_PARSING_URL1
,
crtHost
,
appUserDetail
);
}
catch
(
Exception
ex
)
{
appUserDetail
.
setProvinceCode
(
PROVINCECODE
);
log
.
error
(
"解析地址失败:【{}】"
,
ex
.
getMessage
());
}
}
appUserDetailBiz
.
updateSelectiveByIdRe
(
appUserDetail
);
}
return
ReturnT
.
SUCCESS
;
}
private
void
analyticalIPByWebSiteAndIPAddress
(
String
url
,
String
crtHost
,
AppUserDetail
appUserDetail
)
{
String
ipAddress
=
restTemplate
.
getForObject
(
String
.
format
(
"%s%s&app_id=%s&app_secret=%s"
,
url
,
crtHost
,
appId
,
secret
),
String
.
class
);
String
data
=
JSONObject
.
parseObject
(
ipAddress
).
getString
(
IPAddress
.
BASE_DATA
);
JSONObject
ipJsonObject
=
JSONObject
.
parseObject
(
data
);
String
cityName
=
ipJsonObject
.
getString
(
IPAddress
.
CITY_NAME
);
RegionDTO
regionDTO
=
regionFeign
.
getRegionByCityName
(
StringUtils
.
isEmpty
(
cityName
)
?
"东莞"
:
cityName
);
if
(
null
!=
regionDTO
)
{
appUserDetail
.
setProvinceCode
(
Integer
.
valueOf
(
String
.
valueOf
(
regionDTO
.
getParentId
())));
appUserDetail
.
setCityCode
(
Integer
.
valueOf
(
String
.
valueOf
(
regionDTO
.
getId
())));
}
else
{
if
(
StringUtils
.
isNotEmpty
(
cityName
)){
appUserDetail
.
setProvinceCode
(
Integer
.
valueOf
(
ipJsonObject
.
get
(
IPAddress
.
RPOINCE_ID
).
toString
()));
appUserDetail
.
setCityCode
(
Integer
.
valueOf
(
ipJsonObject
.
get
(
IPAddress
.
CITY_ID
).
toString
()));
}
}
}
/**
* @author libin
* @version 1.0.0
* @dec ip 解析返回的地址信息
*/
private
static
class
IPAddress
{
public
static
final
String
BASE_IP_PARSING_URL1
=
"http://ip.taobao.com/service/getIpInfo.php?ip="
;
public
static
final
String
BASE_IP_PARSING_URL2
=
"https://www.mxnzp.com/api/ip/aim_ip?ip="
;
public
static
final
String
BASE_DATA
=
"data"
;
public
static
final
String
CITY_NAME
=
"city"
;
public
static
final
String
RPOINCE_ID
=
"provinceId"
;
public
static
final
String
CITY_ID
=
"cityId"
;
}
}
ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/admin/mapper/AppUserDetailMapper.java
View file @
31d1ca15
...
@@ -38,4 +38,7 @@ public interface AppUserDetailMapper extends Mapper<AppUserDetail> {
...
@@ -38,4 +38,7 @@ public interface AppUserDetailMapper extends Mapper<AppUserDetail> {
AppUserVo
getUser
(
Integer
userId
);
AppUserVo
getUser
(
Integer
userId
);
List
<
UserBo
>
findUserBosByPhones
(
@Param
(
"phones"
)
List
<
String
>
phones
);
List
<
UserBo
>
findUserBosByPhones
(
@Param
(
"phones"
)
List
<
String
>
phones
);
List
<
AppUserDetail
>
selectAllWithNoProviinceCode
();
}
}
\ No newline at end of file
ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/admin/rpc/service/AppPermissionService.java
View file @
31d1ca15
...
@@ -26,7 +26,6 @@ import com.github.wxiaoqi.security.common.util.process.SystemConfig;
...
@@ -26,7 +26,6 @@ import com.github.wxiaoqi.security.common.util.process.SystemConfig;
import
com.github.wxiaoqi.security.common.util.result.JsonResultUtil
;
import
com.github.wxiaoqi.security.common.util.result.JsonResultUtil
;
import
com.xxfc.platform.activity.feign.ActivityFeign
;
import
com.xxfc.platform.activity.feign.ActivityFeign
;
import
com.xxfc.platform.im.feign.ImFeign
;
import
com.xxfc.platform.im.feign.ImFeign
;
import
com.xxfc.platform.universal.dto.RegionDTO
;
import
com.xxfc.platform.universal.dto.SmsTemplateDTO
;
import
com.xxfc.platform.universal.dto.SmsTemplateDTO
;
import
com.xxfc.platform.universal.feign.MQSenderFeign
;
import
com.xxfc.platform.universal.feign.MQSenderFeign
;
import
com.xxfc.platform.universal.feign.RegionFeign
;
import
com.xxfc.platform.universal.feign.RegionFeign
;
...
@@ -1208,55 +1207,6 @@ public class AppPermissionService {
...
@@ -1208,55 +1207,6 @@ public class AppPermissionService {
}
}
}
}
/**
* ip地址 信息解析
*
* @param appUserDetail
*/
public
void
setCreateIPInfo
(
AppUserDetail
appUserDetail
)
{
String
crtHost
=
appUserDetail
.
getCrtHost
();
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"解析的地址:【{}】"
,
crtHost
+
"---time==="
+
System
.
currentTimeMillis
()/
1000L
);
}
try
{
analyticalIPByWebSiteAndIPAddress
(
IPAddress
.
BASE_IP_PARSING_URL2
,
crtHost
,
appUserDetail
);
}
catch
(
Exception
e
)
{
try
{
analyticalIPByWebSiteAndIPAddress
(
IPAddress
.
BASE_IP_PARSING_URL1
,
crtHost
,
appUserDetail
);
}
catch
(
Exception
ex
)
{
log
.
error
(
"解析地址失败:【{}】"
,
ex
.
getMessage
());
}
}
}
private
void
analyticalIPByWebSiteAndIPAddress
(
String
url
,
String
crtHost
,
AppUserDetail
appUserDetail
)
{
String
ipAddress
=
restTemplate
.
getForObject
(
String
.
format
(
"%s%s"
,
url
,
crtHost
),
String
.
class
);
log
.
debug
(
"解析的调用网站后:【{}】"
,
crtHost
+
"---time==="
+
System
.
currentTimeMillis
()/
1000L
);
String
data
=
JSONObject
.
parseObject
(
ipAddress
).
getString
(
IPAddress
.
BASE_DATA
);
JSONObject
ipJsonObject
=
JSONObject
.
parseObject
(
data
);
String
cityName
=
ipJsonObject
.
getString
(
IPAddress
.
CITY_NAME
);
RegionDTO
regionDTO
=
regionFeign
.
getRegionByCityName
(
StringUtils
.
isEmpty
(
cityName
)
?
"东莞"
:
cityName
);
log
.
debug
(
"解析的调用服务后:【{}】"
,
crtHost
+
"---time==="
+
System
.
currentTimeMillis
()/
1000L
);
if
(
null
!=
regionDTO
)
{
appUserDetail
.
setProvinceCode
(
Integer
.
valueOf
(
String
.
valueOf
(
regionDTO
.
getParentId
())));
appUserDetail
.
setCityCode
(
Integer
.
valueOf
(
String
.
valueOf
(
regionDTO
.
getId
())));
}
}
/**
* @author libin
* @version 1.0.0
* @dec ip 解析返回的地址信息
*/
private
static
class
IPAddress
{
public
static
final
String
BASE_IP_PARSING_URL1
=
"http://ip.taobao.com/service/getIpInfo.php?ip="
;
public
static
final
String
BASE_IP_PARSING_URL2
=
"https://www.mxnzp.com/api/ip/aim_ip?ip="
;
public
static
final
String
BASE_DATA
=
"data"
;
public
static
final
String
CITY_NAME
=
"city"
;
}
//修改手机号码
//修改手机号码
public
ObjectRestResponse
updUsername
(
Integer
userId
,
String
username
,
String
mobileCode
){
public
ObjectRestResponse
updUsername
(
Integer
userId
,
String
username
,
String
mobileCode
){
if
(
StringUtils
.
isBlank
(
username
)||
StringUtils
.
isBlank
(
mobileCode
)||
userId
==
0
||
userId
==
null
){
if
(
StringUtils
.
isBlank
(
username
)||
StringUtils
.
isBlank
(
mobileCode
)||
userId
==
0
||
userId
==
null
){
...
...
ace-modules/ace-admin/src/main/resources/mapper/AppUserDetailMapper.xml
View file @
31d1ca15
...
@@ -338,4 +338,9 @@ from `app_user_detail` as `aud` left join `app_user_login` as `aul` on aul.id=
...
@@ -338,4 +338,9 @@ from `app_user_detail` as `aud` left join `app_user_login` as `aul` on aul.id=
</foreach>
</foreach>
</if>
) as aul inner join `app_user_detail` as aud on aud.userid=aul.id
</if>
) as aul inner join `app_user_detail` as aud on aud.userid=aul.id
</select>
</select>
<select
id=
"selectAllWithNoProviinceCode"
resultType=
"com.github.wxiaoqi.security.admin.entity.AppUserDetail"
>
select `id`,`crt_host` from `app_user_detail` where crt_host is not null and ( province_code = 0 or province_code is null)
</select>
</mapper>
</mapper>
\ No newline at end of file
xx-activity/xx-activity-server/src/main/java/com/xxfc/platform/activity/biz/ActivityLuckyDrawBiz.java
View file @
31d1ca15
...
@@ -65,14 +65,14 @@ public class ActivityLuckyDrawBiz extends BaseBiz<ActivityLuckyDrawMapper, Activ
...
@@ -65,14 +65,14 @@ public class ActivityLuckyDrawBiz extends BaseBiz<ActivityLuckyDrawMapper, Activ
}
}
public
void
exportActivityLuckDrawData
(
ActivityLuckDrawFindDTO
activityLuckDrawFindDTO
,
ServletOutputStream
outputStream
)
throws
IOException
{
public
void
exportActivityLuckDrawData
(
ActivityLuckDrawFindDTO
activityLuckDrawFindDTO
,
ServletOutputStream
outputStream
)
throws
IOException
{
List
<
ActivityLuckyDraw
>
activityLuckyDraws
=
listActivityLuckDraw
(
activityLuckDrawFindDTO
);
List
<
ActivityLuckyDraw
ListVo
>
activityLuckyDraws
=
listActivityLuckDraw
(
activityLuckDrawFindDTO
);
ExcelUtils
excelUtils
=
new
ExcelUtils
(
"报名列表"
);
ExcelUtils
excelUtils
=
new
ExcelUtils
(
"报名列表"
);
XSSFWorkbook
hssfWorkbook
=
excelUtils
.
getHssfWorkbook
();
XSSFWorkbook
hssfWorkbook
=
excelUtils
.
getHssfWorkbook
();
XSSFSheet
sheet
=
excelUtils
.
getSheet
();
XSSFSheet
sheet
=
excelUtils
.
getSheet
();
Row
headerRow
=
sheet
.
createRow
(
0
);
Row
headerRow
=
sheet
.
createRow
(
0
);
CellStyle
headerCellStyle
=
excelUtils
.
createHeaderCellStyle
();
CellStyle
headerCellStyle
=
excelUtils
.
createHeaderCellStyle
();
String
[]
headers
=
{
"姓名"
,
"电话"
,
"人数"
,
"报名时间"
};
String
[]
headers
=
{
"姓名"
,
"电话"
,
"
身份"
,
"上级姓名"
,
"上级电话"
,
"
人数"
,
"报名时间"
};
excelUtils
.
createHeader
(
headerRow
,
0
,
headers
,
headerCellStyle
);
excelUtils
.
createHeader
(
headerRow
,
0
,
headers
,
headerCellStyle
);
CellStyle
generalCellStyle
=
excelUtils
.
createGeneralCellStyle
();
CellStyle
generalCellStyle
=
excelUtils
.
createGeneralCellStyle
();
...
@@ -85,23 +85,24 @@ public class ActivityLuckyDrawBiz extends BaseBiz<ActivityLuckyDrawMapper, Activ
...
@@ -85,23 +85,24 @@ public class ActivityLuckyDrawBiz extends BaseBiz<ActivityLuckyDrawMapper, Activ
}
}
private
List
<
String
[]>
getActivityLuckDrawDataList
(
List
<
ActivityLuckyDraw
>
activityLuckyDraws
){
private
List
<
String
[]>
getActivityLuckDrawDataList
(
List
<
ActivityLuckyDraw
ListVo
>
activityLuckyDraws
){
List
<
String
[]>
activityLuckDrawDataList
=
new
ArrayList
<>(
activityLuckyDraws
.
size
());
List
<
String
[]>
activityLuckDrawDataList
=
new
ArrayList
<>(
activityLuckyDraws
.
size
());
for
(
ActivityLuckyDraw
activityLuckyDraw
:
activityLuckyDraws
)
{
for
(
ActivityLuckyDraw
ListVo
activityLuckyDraw
:
activityLuckyDraws
)
{
String
[]
activityLuckDrawData
=
getActivityLuckDrawData
(
activityLuckyDraw
);
String
[]
activityLuckDrawData
=
getActivityLuckDrawData
(
activityLuckyDraw
);
activityLuckDrawDataList
.
add
(
activityLuckDrawData
);
activityLuckDrawDataList
.
add
(
activityLuckDrawData
);
}
}
return
activityLuckDrawDataList
;
return
activityLuckDrawDataList
;
}
}
private
String
[]
getActivityLuckDrawData
(
ActivityLuckyDraw
activityLuckyDraw
){
private
String
[]
getActivityLuckDrawData
(
ActivityLuckyDraw
ListVo
activityLuckyDraw
){
Date
crtTime
=
activityLuckyDraw
.
getCrtTime
();
Date
crtTime
=
activityLuckyDraw
.
getCrtTime
();
String
timeStr
=
DateUtil
.
format
(
crtTime
,
"yyyy-MM-dd HH:mm:ss"
);
String
timeStr
=
DateUtil
.
format
(
crtTime
,
"yyyy-MM-dd HH:mm:ss"
);
return
new
String
[]{
activityLuckyDraw
.
getUserName
(),
activityLuckyDraw
.
getPhone
(),
activityLuckyDraw
.
getTicketNum
()+
""
,
timeStr
};
return
new
String
[]{
activityLuckyDraw
.
getUserName
(),
activityLuckyDraw
.
getPhone
(),
activityLuckyDraw
.
get
PositionName
(),
activityLuckyDraw
.
getParentName
(),
activityLuckyDraw
.
getParentPhone
(),
activityLuckyDraw
.
get
TicketNum
()+
""
,
timeStr
};
}
}
public
List
<
ActivityLuckyDraw
>
listActivityLuckDraw
(
ActivityLuckDrawFindDTO
activityLuckDrawFindDTO
){
public
List
<
ActivityLuckyDrawListVo
>
listActivityLuckDraw
(
ActivityLuckDrawFindDTO
activityLuckDrawFindDTO
){
List
<
ActivityLuckyDraw
>
activityLuckyDraws
=
mapper
.
listLuckDrawWithPage
(
activityLuckDrawFindDTO
);
Query
query
=
new
Query
(
activityLuckDrawFindDTO
);
List
<
ActivityLuckyDrawListVo
>
activityLuckyDraws
=
mapper
.
getAllByPage
(
query
.
getSuper
());
if
(
CollectionUtils
.
isEmpty
(
activityLuckyDraws
)){
if
(
CollectionUtils
.
isEmpty
(
activityLuckyDraws
)){
return
Collections
.
EMPTY_LIST
;
return
Collections
.
EMPTY_LIST
;
}
}
...
...
xx-activity/xx-activity-server/src/main/java/com/xxfc/platform/activity/rest/admin/ActivityLuckyDrawAdminController.java
View file @
31d1ca15
...
@@ -8,10 +8,8 @@ import com.xxfc.platform.activity.dto.ActivityLuckDrawFindDTO;
...
@@ -8,10 +8,8 @@ import com.xxfc.platform.activity.dto.ActivityLuckDrawFindDTO;
import
com.xxfc.platform.activity.vo.ActivityLuckyDrawListVo
;
import
com.xxfc.platform.activity.vo.ActivityLuckyDrawListVo
;
import
lombok.RequiredArgsConstructor
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
javax.servlet.ServletOutputStream
;
import
javax.servlet.ServletOutputStream
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpServletResponse
;
...
@@ -25,7 +23,7 @@ import java.time.format.DateTimeFormatter;
...
@@ -25,7 +23,7 @@ import java.time.format.DateTimeFormatter;
* @data 2019/12/3 16:51
* @data 2019/12/3 16:51
*/
*/
@
Rest
Controller
@Controller
@RequestMapping
(
"admin/activityLuckyDraw"
)
@RequestMapping
(
"admin/activityLuckyDraw"
)
@RequiredArgsConstructor
(
onConstructor
=
@__
(
@Autowired
))
@RequiredArgsConstructor
(
onConstructor
=
@__
(
@Autowired
))
public
class
ActivityLuckyDrawAdminController
{
public
class
ActivityLuckyDrawAdminController
{
...
@@ -38,6 +36,7 @@ public class ActivityLuckyDrawAdminController {
...
@@ -38,6 +36,7 @@ public class ActivityLuckyDrawAdminController {
* @return
* @return
*/
*/
@PostMapping
(
"/page"
)
@PostMapping
(
"/page"
)
@ResponseBody
public
ObjectRestResponse
<
PageDataVO
<
ActivityLuckyDrawListVo
>>
listActivtyLuckyDrawWithPage
(
@RequestBody
ActivityLuckDrawFindDTO
activityLuckDrawFindDTO
)
{
public
ObjectRestResponse
<
PageDataVO
<
ActivityLuckyDrawListVo
>>
listActivtyLuckyDrawWithPage
(
@RequestBody
ActivityLuckDrawFindDTO
activityLuckDrawFindDTO
)
{
return
activityLuckyDrawBiz
.
getAll
(
activityLuckDrawFindDTO
);
return
activityLuckyDrawBiz
.
getAll
(
activityLuckDrawFindDTO
);
}
}
...
...
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