Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
cmeeting
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
翟斌
cmeeting
Commits
80e40c16
提交
80e40c16
authored
9月 16, 2025
作者:
洪东保
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
用户登录统计及导出
父级
82f6e4d5
显示空白字符变更
内嵌
并排
正在显示
15 个修改的文件
包含
518 行增加
和
51 行删除
+518
-51
src/main/java/com/cmeeting/ad/config/RobotWebSecurityConfig.java
+1
-1
src/main/java/com/cmeeting/ad/filter/RobotJwtAuthenticationTokenFilter.java
+6
-6
src/main/java/com/cmeeting/ad/service/impl/UserServiceImpl.java
+7
-4
src/main/java/com/cmeeting/ad/util/JwtUtil.java
+0
-3
src/main/java/com/cmeeting/controller/StatisticsController.java
+78
-30
src/main/java/com/cmeeting/controller/SysUseSyncController.java
+2
-2
src/main/java/com/cmeeting/job/CmeetingJob.java
+1
-1
src/main/java/com/cmeeting/mapper/primary/UserAccessRecordMapper.java
+17
-0
src/main/java/com/cmeeting/pojo/UserAccessRecord.java
+23
-0
src/main/java/com/cmeeting/service/IUserAccessRecordService.java
+20
-0
src/main/java/com/cmeeting/service/SysUserSyncService.java
+1
-1
src/main/java/com/cmeeting/service/impl/SysUserSyncServiceImpl.java
+1
-1
src/main/java/com/cmeeting/service/impl/UserAccessRecordServiceImpl.java
+325
-0
src/main/java/com/cmeeting/vo/StatisticVO.java
+4
-2
src/main/resources/mapper/primary/UserAccessRecordMapper.xml
+32
-0
没有找到文件。
src/main/java/com/cmeeting/ad/config/RobotWebSecurityConfig.java
浏览文件 @
80e40c16
...
...
@@ -88,11 +88,11 @@ public class RobotWebSecurityConfig extends WebSecurityConfigurerAdapter {
.
authorizeRequests
()
// 对于登录login 图标 要允许匿名访问
// .antMatchers(customApi).access("@robotJwtCustomTokenFilter.checkToken(request)")
.
antMatchers
(
"/agent/auth/**"
).
anonymous
()
.
antMatchers
(
HttpMethod
.
GET
,
"/*.html"
,
"/**/*.html"
,
"/**/*.css"
,
"/**/*.js"
,
"/**/*.map"
)
.
permitAll
()
.
antMatchers
(
"/error"
).
anonymous
()
.
antMatchers
(
"/agent/auth/**"
).
anonymous
()
.
antMatchers
(
"/user/login"
).
anonymous
()
.
antMatchers
(
"/user/userAuth"
).
anonymous
()
.
antMatchers
(
"/user/tokenAuth"
).
anonymous
()
...
...
src/main/java/com/cmeeting/ad/filter/RobotJwtAuthenticationTokenFilter.java
浏览文件 @
80e40c16
...
...
@@ -59,12 +59,12 @@ public class RobotJwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Override
protected
void
doFilterInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
,
FilterChain
chain
)
throws
ServletException
,
IOException
{
// 检查请求路径是否在白名单中
String
requestURI
=
request
.
getRequestURI
();
if
(
isWhiteListPath
(
requestURI
))
{
chain
.
doFilter
(
request
,
response
);
// 放行,不验证JWT
return
;
}
//
// 检查请求路径是否在白名单中
//
String requestURI = request.getRequestURI();
//
if (isWhiteListPath(requestURI)) {
//
chain.doFilter(request, response); // 放行,不验证JWT
//
return;
//
}
String
token
=
jwtUtil
.
getToken
(
request
);
if
(
StringUtils
.
isNotBlank
(
token
))
{
...
...
src/main/java/com/cmeeting/ad/service/impl/UserServiceImpl.java
浏览文件 @
80e40c16
...
...
@@ -15,6 +15,8 @@ import com.cmeeting.exception.RobotBaseException;
import
com.cmeeting.mapper.primary.AuthMapper
;
import
com.cmeeting.mapper.primary.SysUserSyncMapper
;
import
com.cmeeting.pojo.CoreModulePermissions
;
import
com.cmeeting.pojo.UserAccessRecord
;
import
com.cmeeting.service.IUserAccessRecordService
;
import
com.cmeeting.util.*
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
...
...
@@ -31,10 +33,7 @@ import java.time.Duration;
import
java.time.Instant
;
import
java.time.ZoneId
;
import
java.time.ZonedDateTime
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.*
;
import
java.util.stream.Collectors
;
@Service
...
...
@@ -69,6 +68,8 @@ public class UserServiceImpl implements UserService {
private
AuthMapper
authMapper
;
@Resource
private
SysUserSyncMapper
sysUserSyncMapper
;
@Resource
private
IUserAccessRecordService
iUserAccessRecordService
;
@Override
public
R
login
(
String
agentId
,
String
data
,
String
ip
)
{
...
...
@@ -93,6 +94,8 @@ public class UserServiceImpl implements UserService {
String
token
=
jwtUtil
.
generateToken
(
userDetail
);
redisUtils
.
set
(
token
,
userDetail
,
Long
.
parseLong
(
expireTime
));
// 记录登录日志
iUserAccessRecordService
.
save
(
UserAccessRecord
.
builder
().
userId
(
userId
).
createTime
(
new
Date
()).
build
());
return
token
;
}
...
...
src/main/java/com/cmeeting/ad/util/JwtUtil.java
浏览文件 @
80e40c16
...
...
@@ -78,9 +78,6 @@ public class JwtUtil {
*/
public
String
getToken
(
HttpServletRequest
request
)
{
String
token
=
request
.
getHeader
(
tokenHeader
);
if
(
StrUtil
.
isBlank
(
token
))
{
throw
new
RobotBaseException
(
"认证已过期!"
,
401
);
}
if
(
StrUtil
.
isNotBlank
(
token
)
&&
token
.
length
()
>
authTokenStart
.
length
())
{
token
=
token
.
substring
(
authTokenStart
.
length
()).
trim
();
}
...
...
src/main/java/com/cmeeting/controller/StatisticsController.java
浏览文件 @
80e40c16
package
com
.
cmeeting
.
controller
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.date.DateField
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.util.StrUtil
;
import
c
om.azure.core.annotation.Post
;
import
c
n.hutool.json.JSONUtil
;
import
com.cmeeting.annotation.OperLog
;
import
com.cmeeting.constant.DeptCollect
;
import
com.cmeeting.pojo.SysUserSyncCategory
;
import
com.cmeeting.service.IUserAccessRecordService
;
import
com.cmeeting.service.MeetingInfoService
;
import
com.cmeeting.service.MeetingRecordTemplateService
;
import
com.cmeeting.service.SysUserSyncService
;
import
com.cmeeting.util.R
;
import
com.cmeeting.util.page.PageUtil
;
import
com.sun.javafx.binding.StringFormatter
;
import
com.cmeeting.vo.StatisticVO
;
import
lombok.extern.slf4j.Slf4j
;
import
org.aspectj.weaver.ast.Var
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.annotation.Resource
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.text.ParseException
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
...
...
@@ -32,12 +34,15 @@ import java.util.stream.Collectors;
**/
@RestController
@RequestMapping
(
"/statistics"
)
@Slf4j
public
class
StatisticsController
{
@
Autowired
@
Resource
private
MeetingInfoService
meetingInfoService
;
@
Autowired
@
Resource
private
SysUserSyncService
sysUserSyncService
;
@Resource
private
IUserAccessRecordService
iUserAccessRecordService
;
/**
* 纪要模板使用情况的统计
...
...
@@ -56,9 +61,28 @@ public class StatisticsController {
return
PageUtil
.
getDataTable
(
list
);
}
/**
* 纪要模板使用情况的统计
* @param searchValue 用户部门或工号
* @param createTimeStart 开始时间
* @param createTimeEnd 结束时间
* @return
*/
@OperLog
(
location
=
"统计日志"
,
operation
=
"导出统计日志"
)
@GetMapping
(
"/exportRecordTemplateUsingInfo"
)
public
R
exportRecordTemplateUsingInfo
(
String
searchValue
,
@RequestParam
(
"createTimeStart"
)
Date
createTimeStart
,
@RequestParam
(
"createTimeEnd"
)
Date
createTimeEnd
,
HttpServletResponse
response
)
{
meetingInfoService
.
exportRecordTemplateUsingInfo
(
searchValue
,
createTimeStart
,
createTimeEnd
,
response
);
return
R
.
ok
();
}
@PostMapping
(
"/useInfoByCompany"
)
public
R
useInfoByCompany
(
@Validated
@RequestBody
UseInfoByCompany
VO
vo
)
throws
ParseException
{
List
<
SysUserSyncCategory
>
tree
=
sysUserSyncService
.
getTree
();
public
R
useInfoByCompany
(
@Validated
@RequestBody
Statistic
VO
vo
)
throws
ParseException
{
List
<
SysUserSyncCategory
>
tree
=
sysUserSyncService
.
getTree
List
();
String
search
=
vo
.
getSearch
();
if
(
StrUtil
.
isNotBlank
(
search
))
{
tree
=
tree
.
stream
().
filter
(
e
->
search
.
equals
(
e
.
getDeptId
())
||
e
.
getPath
().
contains
(
search
)).
collect
(
Collectors
.
toList
());
...
...
@@ -73,9 +97,9 @@ public class StatisticsController {
return
PageUtil
.
getDataTable
(
list
);
}
@PostMapping
(
"/exportUseInfoByCompany"
)
public
void
exportUseInfoByCompany
(
@Validated
@RequestBody
UseInfoByCompany
VO
vo
,
HttpServletResponse
response
)
throws
ParseException
,
IOException
{
public
void
exportUseInfoByCompany
(
@Validated
@RequestBody
Statistic
VO
vo
,
HttpServletResponse
response
)
throws
ParseException
,
IOException
{
String
search
=
vo
.
getSearch
();
List
<
SysUserSyncCategory
>
tree
=
sysUserSyncService
.
getTree
();
List
<
SysUserSyncCategory
>
tree
=
sysUserSyncService
.
getTree
List
();
if
(
StrUtil
.
isNotBlank
(
search
))
{
tree
=
tree
.
stream
().
filter
(
e
->
search
.
equals
(
e
.
getDeptId
())
||
e
.
getPath
().
contains
(
search
)).
collect
(
Collectors
.
toList
());
}
...
...
@@ -86,25 +110,49 @@ public class StatisticsController {
String
title
=
"会议纪要推送次数统计.docx"
;
meetingInfoService
.
statisticsEmail
(
title
,
simpleDateFormat1
.
parse
(
simpleDateFormat
.
format
(
vo
.
getStartTime
())
+
" 00:00:00"
),
simpleDateFormat1
.
parse
(
simpleDateFormat
.
format
(
vo
.
getEndTime
())
+
" 23:59:59"
),
response
.
getOutputStream
(),
collect
);
}
/**
* 纪要模板使用情况的统计
* @param searchValue 用户部门或工号
* @param createTimeStart 开始时间
* @param createTimeEnd 结束时间
* @return
*/
@OperLog
(
location
=
"统计日志"
,
operation
=
"导出统计日志"
)
@GetMapping
(
"/exportRecordTemplateUsingInfo"
)
public
R
exportRecordTemplateUsingInfo
(
String
searchValue
,
@RequestParam
(
"createTimeStart"
)
Date
createTimeStart
,
@RequestParam
(
"createTimeEnd"
)
Date
createTimeEnd
,
HttpServletResponse
response
)
{
@PostMapping
(
"/userAccessRecord"
)
public
R
userAccessRecord
(
@Validated
@RequestBody
StatisticVO
vo
){
return
R
.
ok
(
iUserAccessRecordService
.
statistics
(
vo
.
getSearch
(),
vo
.
getStartTime
(),
vo
.
getEndTime
(),
vo
.
getCurrent
(),
vo
.
getSize
()));
}
@PostMapping
(
"/exportUserAccessRecord"
)
public
void
exportUserAccessRecord
(
@Validated
@RequestBody
StatisticVO
vo
,
HttpServletResponse
response
){
List
<
Map
<
String
,
String
>>
statistics
=
iUserAccessRecordService
.
statistics
(
vo
.
getSearch
(),
vo
.
getStartTime
(),
vo
.
getEndTime
(),
vo
.
getCurrent
(),
vo
.
getSize
());
List
<
String
>
dateList
=
DateUtil
.
rangeToList
(
vo
.
getStartTime
(),
vo
.
getEndTime
(),
DateField
.
DAY_OF_YEAR
).
stream
()
.
map
(
date
->
DateUtil
.
format
(
date
,
"yyyy-MM-dd"
))
.
collect
(
Collectors
.
toList
());
iUserAccessRecordService
.
exportUserAccessRecord
(
statistics
,
dateList
,
response
);
}
@PostMapping
(
"/userAccessRecordByCompany"
)
public
R
userAccessRecordByCompany
(
@Validated
@RequestBody
StatisticVO
vo
){
String
search
=
vo
.
getSearch
();
List
<
SysUserSyncCategory
>
treeList
=
sysUserSyncService
.
getTreeList
();
if
(
StrUtil
.
isNotBlank
(
search
))
{
treeList
=
treeList
.
stream
().
filter
(
e
->
search
.
equals
(
e
.
getDeptId
())
||
e
.
getPath
().
contains
(
search
)).
collect
(
Collectors
.
toList
());
}
List
<
String
>
collect
=
treeList
.
stream
().
map
(
SysUserSyncCategory:
:
getPath
).
collect
(
Collectors
.
toList
());
meetingInfoService
.
exportRecordTemplateUsingInfo
(
searchValue
,
createTimeStart
,
createTimeEnd
,
response
);
if
(
CollUtil
.
isEmpty
(
collect
))
{
return
R
.
ok
(
new
ArrayList
<>());
}
return
R
.
ok
(
iUserAccessRecordService
.
statisticsByCompany
(
vo
.
getStartTime
(),
vo
.
getEndTime
(),
collect
));
}
@PostMapping
(
"/exportUserAccessRecordByCompany"
)
public
void
exportUserAccessRecordByCompany
(
@Validated
@RequestBody
StatisticVO
vo
,
HttpServletResponse
response
)
throws
IOException
{
String
search
=
vo
.
getSearch
();
List
<
SysUserSyncCategory
>
treeList
=
sysUserSyncService
.
getTreeList
();
if
(
StrUtil
.
isNotBlank
(
search
))
{
treeList
=
treeList
.
stream
().
filter
(
e
->
search
.
equals
(
e
.
getDeptId
())
||
e
.
getPath
().
contains
(
search
)).
collect
(
Collectors
.
toList
());
}
List
<
String
>
collect
=
treeList
.
stream
().
map
(
SysUserSyncCategory:
:
getPath
).
collect
(
Collectors
.
toList
());
return
R
.
ok
();
List
<
String
>
dateList
=
DateUtil
.
rangeToList
(
vo
.
getStartTime
(),
vo
.
getEndTime
(),
DateField
.
DAY_OF_YEAR
).
stream
()
.
map
(
date
->
DateUtil
.
format
(
date
,
"yyyy-MM-dd"
))
.
collect
(
Collectors
.
toList
());
List
<
Map
<
String
,
String
>>
data
=
iUserAccessRecordService
.
statisticsByCompany
(
vo
.
getStartTime
(),
vo
.
getEndTime
(),
collect
);
iUserAccessRecordService
.
exportUserAccessRecordByCompany
(
data
,
dateList
,
response
);
}
}
src/main/java/com/cmeeting/controller/SysUseSyncController.java
浏览文件 @
80e40c16
...
...
@@ -34,12 +34,12 @@ public class SysUseSyncController {
@GetMapping
(
"/getTree"
)
public
R
getTree
(){
return
R
.
ok
(
iSysUserSyncService
.
getTree
());
return
R
.
ok
(
iSysUserSyncService
.
getTree
List
());
}
@GetMapping
(
"/downloadTree"
)
public
void
downloadTree
(
HttpServletResponse
response
){
iSysUserSyncService
.
downloadTree
(
iSysUserSyncService
.
getTree
(),
response
);
iSysUserSyncService
.
downloadTree
(
iSysUserSyncService
.
getTree
List
(),
response
);
}
}
src/main/java/com/cmeeting/job/CmeetingJob.java
浏览文件 @
80e40c16
...
...
@@ -322,7 +322,7 @@ public class CmeetingJob {
SimpleDateFormat
simpleDateFormat
=
new
SimpleDateFormat
(
"yyyy-MM-dd"
);
SimpleDateFormat
simpleDateFormat1
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
List
<
SysUserSyncCategory
>
tree
=
sysUserSyncService
.
getTree
();
List
<
SysUserSyncCategory
>
tree
=
sysUserSyncService
.
getTree
List
();
try
{
boolean
b
=
meetingInfoService
.
statisticsEmail
(
subject
,
simpleDateFormat1
.
parse
(
simpleDateFormat
.
format
(
date
)
+
" 00:00:00"
),
...
...
src/main/java/com/cmeeting/mapper/primary/UserAccessRecordMapper.java
0 → 100644
浏览文件 @
80e40c16
package
com
.
cmeeting
.
mapper
.
primary
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.cmeeting.pojo.UserAccessRecord
;
import
org.apache.ibatis.annotations.MapKey
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
import
java.util.Map
;
public
interface
UserAccessRecordMapper
extends
BaseMapper
<
UserAccessRecord
>
{
@MapKey
(
"userId"
)
Page
<
Map
<
String
,
String
>>
statisticsByDate
(
@Param
(
"page"
)
Page
page
,
@Param
(
"search"
)
String
search
,
@Param
(
"startTime"
)
String
startTime
,
@Param
(
"endTime"
)
String
endTime
,
@Param
(
"dateList"
)
List
<
String
>
dateList
);
}
src/main/java/com/cmeeting/pojo/UserAccessRecord.java
0 → 100644
浏览文件 @
80e40c16
package
com
.
cmeeting
.
pojo
;
import
com.baomidou.mybatisplus.annotation.FieldFill
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
lombok.*
;
import
lombok.experimental.Accessors
;
import
java.util.Date
;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@EqualsAndHashCode
(
callSuper
=
false
)
@Accessors
(
chain
=
true
)
@TableName
(
"user_access_record"
)
public
class
UserAccessRecord
{
private
String
id
;
private
String
userId
;
@TableField
(
fill
=
FieldFill
.
INSERT
)
private
Date
createTime
;
}
src/main/java/com/cmeeting/service/IUserAccessRecordService.java
0 → 100644
浏览文件 @
80e40c16
package
com
.
cmeeting
.
service
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.cmeeting.pojo.UserAccessRecord
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
public
interface
IUserAccessRecordService
extends
IService
<
UserAccessRecord
>
{
List
<
Map
<
String
,
String
>>
statistics
(
String
search
,
Date
startTime
,
Date
endTime
,
Integer
current
,
Integer
size
);
List
<
Map
<
String
,
String
>>
statisticsByCompany
(
Date
startTime
,
Date
endTime
,
List
<
String
>
deptMap
);
void
exportUserAccessRecord
(
List
<
Map
<
String
,
String
>>
statistics
,
List
<
String
>
dateList
,
HttpServletResponse
response
);
void
exportUserAccessRecordByCompany
(
List
<
Map
<
String
,
String
>>
data
,
List
<
String
>
dateList
,
HttpServletResponse
response
)
throws
IOException
;
}
src/main/java/com/cmeeting/service/SysUserSyncService.java
浏览文件 @
80e40c16
...
...
@@ -47,7 +47,7 @@ public interface SysUserSyncService extends IService<SysUserSync> {
List
<
SysUserSync
>
listByUserIds
(
List
<
String
>
userIdList
,
String
search
);
List
<
SysUserSyncCategory
>
getTree
();
List
<
SysUserSyncCategory
>
getTree
List
();
void
downloadTree
(
List
<
SysUserSyncCategory
>
list
,
HttpServletResponse
response
);
}
src/main/java/com/cmeeting/service/impl/SysUserSyncServiceImpl.java
浏览文件 @
80e40c16
...
...
@@ -267,7 +267,7 @@ public class SysUserSyncServiceImpl extends ServiceImpl<SysUserSyncMapper, SysUs
}
@Override
public
List
<
SysUserSyncCategory
>
getTree
()
{
public
List
<
SysUserSyncCategory
>
getTree
List
()
{
int
companyIndex
=
2
;
List
<
Tree
<
String
>>
list
=
iSysUserSyncCategoryService
.
tree
();
Tree
<
String
>
tree
=
list
.
get
(
0
);
...
...
src/main/java/com/cmeeting/service/impl/UserAccessRecordServiceImpl.java
0 → 100644
浏览文件 @
80e40c16
package
com
.
cmeeting
.
service
.
impl
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.date.DateField
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.io.IoUtil
;
import
cn.hutool.core.util.NumberUtil
;
import
cn.hutool.poi.excel.ExcelUtil
;
import
cn.hutool.poi.excel.ExcelWriter
;
import
cn.hutool.poi.excel.StyleSet
;
import
cn.hutool.poi.excel.style.StyleUtil
;
import
com.alibaba.fastjson.JSONArray
;
import
com.alibaba.fastjson.JSONObject
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.cmeeting.mapper.primary.SysUserSyncMapper
;
import
com.cmeeting.mapper.primary.UserAccessRecordMapper
;
import
com.cmeeting.pojo.SysUserSyncCategory
;
import
com.cmeeting.pojo.UserAccessRecord
;
import
com.cmeeting.service.ISysUserSyncCategoryService
;
import
com.cmeeting.service.IUserAccessRecordService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.poi.ss.usermodel.CellStyle
;
import
org.apache.poi.ss.usermodel.Font
;
import
org.apache.poi.ss.usermodel.HorizontalAlignment
;
import
org.apache.poi.ss.usermodel.VerticalAlignment
;
import
org.springframework.stereotype.Service
;
import
javax.annotation.Resource
;
import
javax.servlet.ServletOutputStream
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.net.URLEncoder
;
import
java.time.LocalDate
;
import
java.time.format.DateTimeFormatter
;
import
java.time.format.DateTimeParseException
;
import
java.util.*
;
import
java.util.stream.Collectors
;
@Service
@Slf4j
public
class
UserAccessRecordServiceImpl
extends
ServiceImpl
<
UserAccessRecordMapper
,
UserAccessRecord
>
implements
IUserAccessRecordService
{
@Resource
private
ISysUserSyncCategoryService
iSysUserSyncCategoryService
;
@Override
public
List
<
Map
<
String
,
String
>>
statistics
(
String
search
,
Date
startTime
,
Date
endTime
,
Integer
current
,
Integer
size
)
{
List
<
String
>
dateList
=
DateUtil
.
rangeToList
(
startTime
,
endTime
,
DateField
.
DAY_OF_YEAR
).
stream
()
.
map
(
date
->
DateUtil
.
format
(
date
,
"yyyy-MM-dd"
))
.
collect
(
Collectors
.
toList
());
String
start
=
DateUtil
.
format
(
startTime
,
"yyyy-MM-dd"
);
String
end
=
DateUtil
.
format
(
endTime
,
"yyyy-MM-dd"
);
Page
<
Map
<
String
,
String
>>
page
=
baseMapper
.
statisticsByDate
(
new
Page
<>(
current
,
size
),
search
,
start
,
end
,
dateList
);
List
<
Map
<
String
,
String
>>
records
=
page
.
getRecords
();
if
(
CollUtil
.
isNotEmpty
(
records
))
{
List
<
SysUserSyncCategory
>
categoryList
=
iSysUserSyncCategoryService
.
list
(
new
LambdaQueryWrapper
<
SysUserSyncCategory
>().
select
(
SysUserSyncCategory:
:
getDeptId
,
SysUserSyncCategory:
:
getParentId
,
SysUserSyncCategory:
:
getName
));
Map
<
String
,
String
>
parentIdMap
=
categoryList
.
stream
().
collect
(
Collectors
.
toMap
(
SysUserSyncCategory:
:
getDeptId
,
SysUserSyncCategory:
:
getParentId
));
Map
<
String
,
String
>
nameMap
=
categoryList
.
stream
().
collect
(
Collectors
.
toMap
(
SysUserSyncCategory:
:
getDeptId
,
SysUserSyncCategory:
:
getName
));
for
(
Map
<
String
,
String
>
map
:
records
)
{
String
deptId
=
map
.
get
(
"deptId"
);
String
pathName
=
iSysUserSyncCategoryService
.
getPathName
(
deptId
,
parentIdMap
,
nameMap
);
map
.
put
(
"deptName"
,
pathName
);
}
}
for
(
Map
<
String
,
String
>
userInfo
:
records
)
{
// 横向加法
Integer
sum
=
userInfo
.
values
().
stream
()
// 小于4是为了和用户编号区分开
.
filter
(
value
->
NumberUtil
.
isNumber
(
value
)
&&
value
.
length
()
<
4
)
.
map
(
Integer:
:
parseInt
)
.
reduce
(
Integer:
:
sum
)
.
orElse
(
0
);
userInfo
.
put
(
"sum"
,
sum
.
toString
());
}
if
(
records
.
isEmpty
())
{
return
new
ArrayList
<>();
}
// 初始化一行用来纵向加和
Map
<
String
,
String
>
lastRowMap
=
new
LinkedHashMap
<>();
for
(
String
key
:
records
.
get
(
0
).
keySet
())
{
lastRowMap
.
put
(
key
,
""
);
}
for
(
Map
<
String
,
String
>
stringMap
:
records
)
{
for
(
Map
.
Entry
<
String
,
String
>
entry
:
stringMap
.
entrySet
())
{
String
key
=
entry
.
getKey
();
String
value
=
entry
.
getValue
();
if
(
NumberUtil
.
isNumber
(
value
)
&&
value
.
length
()
<
4
)
{
lastRowMap
.
put
(
key
,
String
.
valueOf
(
NumberUtil
.
add
(
lastRowMap
.
get
(
key
),
value
)));
}
}
}
lastRowMap
.
put
(
"userId"
,
"总计"
);
records
.
add
(
lastRowMap
);
return
records
;
}
@Override
public
List
<
Map
<
String
,
String
>>
statisticsByCompany
(
Date
startTime
,
Date
endTime
,
List
<
String
>
deptMap
)
{
List
<
String
>
dateList
=
DateUtil
.
rangeToList
(
startTime
,
endTime
,
DateField
.
DAY_OF_YEAR
).
stream
()
.
map
(
date
->
DateUtil
.
format
(
date
,
"yyyy-MM-dd"
))
.
collect
(
Collectors
.
toList
());
String
start
=
DateUtil
.
format
(
startTime
,
"yyyy-MM-dd"
);
String
end
=
DateUtil
.
format
(
endTime
,
"yyyy-MM-dd"
);
Page
<
Map
<
String
,
String
>>
page
=
baseMapper
.
statisticsByDate
(
new
Page
<>(
1
,
-
1
),
null
,
start
,
end
,
dateList
);
List
<
Map
<
String
,
String
>>
records
=
page
.
getRecords
();
if
(
CollUtil
.
isNotEmpty
(
records
))
{
List
<
SysUserSyncCategory
>
categoryList
=
iSysUserSyncCategoryService
.
list
(
new
LambdaQueryWrapper
<
SysUserSyncCategory
>().
select
(
SysUserSyncCategory:
:
getDeptId
,
SysUserSyncCategory:
:
getParentId
,
SysUserSyncCategory:
:
getName
));
Map
<
String
,
String
>
parentIdMap
=
categoryList
.
stream
().
collect
(
Collectors
.
toMap
(
SysUserSyncCategory:
:
getDeptId
,
SysUserSyncCategory:
:
getParentId
));
Map
<
String
,
String
>
nameMap
=
categoryList
.
stream
().
collect
(
Collectors
.
toMap
(
SysUserSyncCategory:
:
getDeptId
,
SysUserSyncCategory:
:
getName
));
for
(
Map
<
String
,
String
>
map
:
records
)
{
String
deptId
=
map
.
get
(
"deptId"
);
String
pathName
=
iSysUserSyncCategoryService
.
getPathName
(
deptId
,
parentIdMap
,
nameMap
);
map
.
put
(
"deptName"
,
pathName
);
}
}
Map
<
String
,
List
<
Map
<
String
,
String
>>>
groupList
=
new
LinkedHashMap
<>();
for
(
Map
<
String
,
String
>
record
:
records
)
{
String
deptName
=
record
.
get
(
"deptName"
);
if
(
CollUtil
.
isNotEmpty
(
deptMap
))
{
for
(
String
s
:
deptMap
)
{
if
((
deptName
+
"/"
).
contains
(
s
+
"/"
))
{
List
<
Map
<
String
,
String
>>
maps
=
groupList
.
get
(
deptName
);
if
(
maps
==
null
)
{
maps
=
new
ArrayList
<>();
}
maps
.
add
(
record
);
log
.
info
(
"deptName: {}, size: {}"
,
deptName
,
maps
.
size
());
groupList
.
put
(
s
,
maps
);
}
}
}
}
List
<
Map
<
String
,
String
>>
ret
=
new
ArrayList
<>();
for
(
Map
.
Entry
<
String
,
List
<
Map
<
String
,
String
>>>
entry
:
groupList
.
entrySet
())
{
for
(
Map
<
String
,
String
>
map
:
entry
.
getValue
())
{
Map
<
String
,
String
>
temp
=
new
LinkedHashMap
<>();
temp
.
put
(
"deptName"
,
entry
.
getKey
());
for
(
Map
.
Entry
<
String
,
String
>
mapEntry
:
map
.
entrySet
())
{
String
key
=
mapEntry
.
getKey
();
String
value
=
mapEntry
.
getValue
();
if
(
NumberUtil
.
isNumber
(
value
)
&&
value
.
length
()
<
4
)
{
temp
.
put
(
key
,
String
.
valueOf
(
NumberUtil
.
add
(
temp
.
get
(
key
),
value
)));
}
}
ret
.
add
(
temp
);
}
}
for
(
Map
<
String
,
String
>
userInfo
:
ret
)
{
// 横向加法
Integer
sum
=
userInfo
.
values
().
stream
()
// 小于4是为了和用户编号区分开
.
filter
(
value
->
NumberUtil
.
isNumber
(
value
)
&&
value
.
length
()
<
4
)
.
map
(
Integer:
:
parseInt
)
.
reduce
(
Integer:
:
sum
)
.
orElse
(
0
);
userInfo
.
put
(
"sum"
,
sum
.
toString
());
}
if
(
ret
.
isEmpty
())
{
return
new
ArrayList
<>();
}
// 初始化一行用来纵向加和
Map
<
String
,
String
>
lastRowMap
=
new
LinkedHashMap
<>();
lastRowMap
.
put
(
"userId"
,
"总计"
);
for
(
String
key
:
ret
.
get
(
0
).
keySet
())
{
lastRowMap
.
put
(
key
,
""
);
}
for
(
Map
<
String
,
String
>
stringMap
:
ret
)
{
for
(
Map
.
Entry
<
String
,
String
>
entry
:
stringMap
.
entrySet
())
{
String
key
=
entry
.
getKey
();
String
value
=
entry
.
getValue
();
if
(
NumberUtil
.
isNumber
(
value
)
&&
value
.
length
()
<
4
)
{
lastRowMap
.
put
(
key
,
String
.
valueOf
(
NumberUtil
.
add
(
lastRowMap
.
get
(
key
),
value
)));
}
}
}
ret
.
add
(
lastRowMap
);
return
ret
;
}
@Override
public
void
exportUserAccessRecord
(
List
<
Map
<
String
,
String
>>
statistics
,
List
<
String
>
dateList
,
HttpServletResponse
response
)
{
ExcelWriter
writer
=
ExcelUtil
.
getWriter
(
Boolean
.
TRUE
);
ServletOutputStream
out
=
null
;
try
{
List
<
List
<
String
>>
rows
=
new
ArrayList
<>();
for
(
Map
<
String
,
String
>
statistic
:
statistics
)
{
List
<
String
>
row
=
CollUtil
.
newArrayList
(
statistic
.
get
(
"deptName"
),
statistic
.
get
(
"userId"
),
statistic
.
get
(
"name"
));
List
<
String
>
validSortedValues
=
getValidSortedValues
(
statistic
);
row
.
addAll
(
validSortedValues
);
row
.
add
(
statistic
.
get
(
"sum"
));
rows
.
add
(
row
);
}
CellStyle
headCellStyle
=
writer
.
getHeadCellStyle
();
Font
headFont
=
writer
.
createFont
();
headFont
.
setFontName
(
"微软雅黑"
);
headFont
.
setFontHeightInPoints
((
short
)
10
);
headCellStyle
.
setFont
(
headFont
);
List
<
String
>
head
=
CollUtil
.
newArrayList
(
"所属部门"
,
"工号"
,
"姓名"
);
head
.
addAll
(
dateList
);
head
.
add
(
"总计"
);
writer
.
writeHeadRow
(
head
);
writer
.
write
(
rows
,
true
);
String
fileName
=
String
.
format
(
"会议助手访问次数%s.xlsx"
,
DateUtil
.
today
());
response
.
setContentType
(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"
);
response
.
setHeader
(
"Content-Disposition"
,
"attachment;filename="
+
URLEncoder
.
encode
(
fileName
,
"utf8"
));
System
.
out
.
println
(
"exportExecute==ing====================="
);
out
=
response
.
getOutputStream
();
writer
.
flush
(
out
,
true
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
new
RuntimeException
(
e
.
getMessage
());
}
finally
{
writer
.
close
();
IoUtil
.
close
(
out
);
}
}
@Override
public
void
exportUserAccessRecordByCompany
(
List
<
Map
<
String
,
String
>>
data
,
List
<
String
>
dateList
,
HttpServletResponse
response
)
throws
IOException
{
ExcelWriter
writer
=
ExcelUtil
.
getWriter
(
Boolean
.
TRUE
);
ServletOutputStream
out
=
null
;
// try {
List
<
List
<
String
>>
rows
=
new
ArrayList
<>();
for
(
Map
<
String
,
String
>
statistic
:
data
)
{
String
deptName
=
statistic
.
get
(
"deptName"
);
String
[]
split
=
deptName
.
trim
().
split
(
"/"
);
log
.
info
(
"deptName: {}"
,
deptName
);
List
<
String
>
row
;
if
(
split
.
length
>=
4
)
{
row
=
CollUtil
.
newArrayList
(
split
[
2
],
split
[
3
],
split
.
length
>=
5
?
split
[
4
]
:
""
);
}
else
{
row
=
CollUtil
.
newArrayList
(
"总计"
,
""
,
""
);
}
List
<
String
>
validSortedValues
=
getValidSortedValues
(
statistic
);
row
.
addAll
(
validSortedValues
);
row
.
add
(
statistic
.
get
(
"sum"
));
rows
.
add
(
row
);
}
CellStyle
headCellStyle
=
writer
.
getHeadCellStyle
();
Font
headFont
=
writer
.
createFont
();
headFont
.
setFontName
(
"微软雅黑"
);
headFont
.
setFontHeightInPoints
((
short
)
10
);
headCellStyle
.
setFont
(
headFont
);
List
<
String
>
head
=
CollUtil
.
newArrayList
(
"模块"
,
"二级"
,
"三级"
);
head
.
addAll
(
dateList
);
head
.
add
(
"总计"
);
writer
.
writeHeadRow
(
head
);
writer
.
write
(
rows
,
true
);
String
fileName
=
String
.
format
(
"会议助手访问次数(按部门统计)%s.xlsx"
,
DateUtil
.
today
());
response
.
setContentType
(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"
);
response
.
setHeader
(
"Content-Disposition"
,
"attachment;filename="
+
URLEncoder
.
encode
(
fileName
,
"utf8"
));
System
.
out
.
println
(
"exportExecute==ing====================="
);
out
=
response
.
getOutputStream
();
writer
.
flush
(
out
,
true
);
// } catch (Exception e) {
// e.printStackTrace();
// throw new RuntimeException(e.getMessage());
// } finally {
writer
.
close
();
IoUtil
.
close
(
out
);
// }
}
public
static
List
<
String
>
getValidSortedValues
(
Map
<
String
,
String
>
map
)
{
// 定义日期格式器
DateTimeFormatter
formatter
=
DateTimeFormatter
.
ofPattern
(
"yyyy-MM-dd"
);
return
map
.
entrySet
().
stream
()
// 过滤掉格式不正确的日期key
.
filter
(
entry
->
{
try
{
// 尝试解析日期,解析成功则保留,失败则过滤
LocalDate
.
parse
(
entry
.
getKey
(),
formatter
);
return
true
;
}
catch
(
DateTimeParseException
e
)
{
// 日期格式不正确,过滤该条目
return
false
;
}
})
// 按日期升序排序
.
sorted
((
entry1
,
entry2
)
->
{
LocalDate
date1
=
LocalDate
.
parse
(
entry1
.
getKey
(),
formatter
);
LocalDate
date2
=
LocalDate
.
parse
(
entry2
.
getKey
(),
formatter
);
return
date1
.
compareTo
(
date2
);
})
// 提取排序后的value
.
map
(
Map
.
Entry
::
getValue
)
// 收集到List中
.
collect
(
Collectors
.
toList
());
}
public
static
void
main
(
String
[]
args
)
{
String
name
=
"/1/2/3/4"
;
String
[]
split
=
name
.
split
(
"/"
);
for
(
String
s
:
split
)
{
System
.
out
.
println
(
s
);
}
System
.
out
.
println
(
split
.
length
);
}
}
src/main/java/com/cmeeting/
controller/UseInfoByCompany
VO.java
→
src/main/java/com/cmeeting/
vo/Statistic
VO.java
浏览文件 @
80e40c16
package
com
.
cmeeting
.
controller
;
package
com
.
cmeeting
.
vo
;
import
com.fasterxml.jackson.annotation.JsonFormat
;
import
lombok.AllArgsConstructor
;
...
...
@@ -15,7 +15,7 @@ import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public
class
UseInfoByCompany
VO
{
public
class
Statistic
VO
{
private
String
search
;
@NotNull
@DateTimeFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
...
...
@@ -25,4 +25,6 @@ public class UseInfoByCompanyVO {
@DateTimeFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
,
timezone
=
"GMT+8"
)
private
Date
endTime
;
private
Integer
current
;
private
Integer
size
;
}
src/main/resources/mapper/primary/UserAccessRecordMapper.xml
0 → 100644
浏览文件 @
80e40c16
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.cmeeting.mapper.primary.UserAccessRecordMapper"
>
<select
id=
"statisticsByDate"
resultType=
"java.util.Map"
>
SELECT
c.user_id as userId,
s.name,
sc.dept_id as deptId,
<foreach
collection=
"dateList"
item=
"d"
separator=
","
>
cast(MAX(CASE WHEN time = #{d} THEN c.cnt ELSE 0 END) as char) AS `${d}`
</foreach>
FROM (
SELECT
user_id,
date_format(create_time, '%Y-%m-%d') as time,
count(user_id) AS cnt
FROM
user_access_record
WHERE
date_format(create_time, '%Y-%m-%d') BETWEEN #{startTime} AND #{endTime}
GROUP BY user_id, date_format(create_time, '%Y-%m-%d')
) AS c
inner join sys_user_sync as s on s.user_id = c.user_id
<if
test=
"search != null and search != ''"
>
and (s.name like concat('%',#{search},'%') or s.user_id like concat('%',#{search},'%'))
</if>
inner join sys_user_sync_category as sc on sc.dept_id = s.dept_id
GROUP BY c.user_id
</select>
</mapper>
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论