Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
safe-campus-bbs
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
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
万成波
safe-campus-bbs
Commits
79e3bfa9
Commit
79e3bfa9
authored
Nov 07, 2025
by
yuwenwen
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
http://gitlab.tangguo.ren/2300064869/safe-campus-bbs
parents
8e6b76a6
3734696e
Changes
29
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
570 additions
and
215 deletions
+570
-215
safe-campus-admin/src/main/java/com/tangguo/web/controller/system/SysLoginController.java
...com/tangguo/web/controller/system/SysLoginController.java
+54
-9
safe-campus-admin/src/main/resources/application-dev.yml
safe-campus-admin/src/main/resources/application-dev.yml
+10
-4
safe-campus-admin/src/main/resources/application-jxfz.yml
safe-campus-admin/src/main/resources/application-jxfz.yml
+9
-4
safe-campus-admin/src/main/resources/application-test.yml
safe-campus-admin/src/main/resources/application-test.yml
+9
-3
safe-campus-admin/src/main/resources/application.yml
safe-campus-admin/src/main/resources/application.yml
+0
-11
safe-campus-admin/src/test/java/com/tangguo/ApplicationTest.java
...mpus-admin/src/test/java/com/tangguo/ApplicationTest.java
+3
-3
safe-campus-bbs-ui/src/api/login.js
safe-campus-bbs-ui/src/api/login.js
+13
-1
safe-campus-bbs-ui/src/permission.js
safe-campus-bbs-ui/src/permission.js
+1
-1
safe-campus-bbs-ui/src/router/index.js
safe-campus-bbs-ui/src/router/index.js
+6
-1
safe-campus-bbs-ui/src/store/modules/user.js
safe-campus-bbs-ui/src/store/modules/user.js
+81
-58
safe-campus-bbs-ui/src/utils/request.js
safe-campus-bbs-ui/src/utils/request.js
+155
-98
safe-campus-bbs-ui/src/views/wechatlogin.vue
safe-campus-bbs-ui/src/views/wechatlogin.vue
+33
-0
safe-campus-bbs-ui/vue.config.js
safe-campus-bbs-ui/vue.config.js
+1
-1
safe-campus-bbs-uniapp/manifest.json
safe-campus-bbs-uniapp/manifest.json
+2
-2
safe-campus-framework/src/main/java/com/tangguo/framework/config/SecurityConfig.java
...ain/java/com/tangguo/framework/config/SecurityConfig.java
+1
-1
safe-campus-framework/src/main/java/com/tangguo/framework/security/handle/AuthenticationEntryPointImpl.java
...amework/security/handle/AuthenticationEntryPointImpl.java
+5
-5
safe-campus-framework/src/main/java/com/tangguo/framework/web/service/SysLoginService.java
...va/com/tangguo/framework/web/service/SysLoginService.java
+1
-1
safe-campus-framework/src/main/java/com/tangguo/framework/wxcp/WxCpConfiguration.java
...in/java/com/tangguo/framework/wxcp/WxCpConfiguration.java
+25
-4
safe-campus-framework/src/main/java/com/tangguo/framework/wxcp/WxCpProperties.java
.../main/java/com/tangguo/framework/wxcp/WxCpProperties.java
+5
-1
safe-campus-moment/src/main/java/com/tangguo/controller/mobile/MBbsMomentController.java
...a/com/tangguo/controller/mobile/MBbsMomentController.java
+14
-0
safe-campus-moment/src/main/java/com/tangguo/controller/pc/BbsMomentCommentController.java
...com/tangguo/controller/pc/BbsMomentCommentController.java
+14
-0
safe-campus-moment/src/main/java/com/tangguo/domain/BbsMomentComment.java
...nt/src/main/java/com/tangguo/domain/BbsMomentComment.java
+9
-0
safe-campus-moment/src/main/java/com/tangguo/domain/bo/BbsCommentTopBO.java
.../src/main/java/com/tangguo/domain/bo/BbsCommentTopBO.java
+34
-0
safe-campus-moment/src/main/java/com/tangguo/service/IBbsMomentCommentService.java
...in/java/com/tangguo/service/IBbsMomentCommentService.java
+9
-0
safe-campus-moment/src/main/java/com/tangguo/service/IBbsMomentService.java
.../src/main/java/com/tangguo/service/IBbsMomentService.java
+8
-0
safe-campus-moment/src/main/java/com/tangguo/service/impl/BbsMomentCommentServiceImpl.java
...com/tangguo/service/impl/BbsMomentCommentServiceImpl.java
+30
-0
safe-campus-moment/src/main/java/com/tangguo/service/impl/BbsMomentServiceImpl.java
...n/java/com/tangguo/service/impl/BbsMomentServiceImpl.java
+23
-2
safe-campus-moment/src/main/resources/mapper/BbsMomentCommentMapper.xml
...ment/src/main/resources/mapper/BbsMomentCommentMapper.xml
+6
-4
safe-campus-moment/src/main/resources/mapper/BbsMomentMapper.xml
...mpus-moment/src/main/resources/mapper/BbsMomentMapper.xml
+9
-1
No files found.
safe-campus-admin/src/main/java/com/tangguo/web/controller/system/SysLoginController.java
View file @
79e3bfa9
...
...
@@ -2,7 +2,6 @@ package com.tangguo.web.controller.system;
import
cn.hutool.core.util.StrUtil
;
import
com.alibaba.fastjson2.JSON
;
import
com.tangguo.common.annotation.Log
;
import
com.tangguo.common.constant.Constants
;
import
com.tangguo.common.core.domain.AjaxResult
;
import
com.tangguo.common.core.domain.entity.SysMenu
;
...
...
@@ -11,10 +10,8 @@ import com.tangguo.common.core.domain.entity.SysUser;
import
com.tangguo.common.core.domain.model.LoginBody
;
import
com.tangguo.common.core.domain.model.LoginUser
;
import
com.tangguo.common.core.domain.model.WxcpCodeLogin
;
import
com.tangguo.common.enums.BusinessType
;
import
com.tangguo.common.exception.ServiceException
;
import
com.tangguo.common.utils.SecurityUtils
;
import
com.tangguo.common.utils.StringUtils
;
import
com.tangguo.framework.config.ServerConfig
;
import
com.tangguo.framework.web.service.SysLoginService
;
import
com.tangguo.framework.web.service.SysPermissionService
;
...
...
@@ -59,7 +56,10 @@ public class SysLoginController {
private
TokenService
tokenService
;
@Autowired
private
WxCpService
wxCpService
;
private
WxCpService
mobileWxCpService
;
@Autowired
private
WxCpService
pcWxCpService
;
@Autowired
private
ServerConfig
serverConfig
;
...
...
@@ -67,8 +67,12 @@ public class SysLoginController {
@Autowired
private
ISysUserService
userService
;
@Value
(
"${wx.cp.redirect-url}"
)
private
String
redirectUrl
;
@Value
(
"${wx.cp.pc-redirect-url}"
)
private
String
pcRedirectUrl
;
@Value
(
"${wx.cp.mobile-redirect-url}"
)
private
String
mobileRedirectUrl
;
...
...
@@ -88,6 +92,47 @@ public class SysLoginController {
return
ajax
;
}
/**
* 企微用户Code登录
*
* @param bo 登录参数
* @return 登录结果
*/
@PostMapping
(
"/pc/code/login"
)
public
AjaxResult
pcCodeLogin
(
@RequestBody
WxcpCodeLogin
bo
)
{
LoginUser
loginUser
=
SecurityUtils
.
getLoginUserNotEx
();
log
.
info
(
"=> 登录请求参数:{}"
,
bo
);
log
.
info
(
"=> 当前登录用户:{}"
,
loginUser
);
// 企微登录认证链接
String
authCode
=
bo
.
getCode
();
WxCpOAuth2Service
oauth2Service
=
this
.
pcWxCpService
.
getOauth2Service
();
if
(
Objects
.
isNull
(
loginUser
)
&&
StrUtil
.
isBlank
(
authCode
))
{
String
oauth2Url
=
oauth2Service
.
buildAuthorizationUrl
(
this
.
pcRedirectUrl
,
null
);
log
.
info
(
"=> 认证失败,返回Oauth2登录链接:{}"
,
oauth2Url
);
return
AjaxResult
.
error
(
401
,
"身份认证失败"
,
oauth2Url
);
}
// 查询企微用户信息
String
token
=
null
;
if
(
Objects
.
isNull
(
loginUser
)
&&
StrUtil
.
isNotBlank
(
authCode
))
{
try
{
WxCpOauth2UserInfo
userInfo
=
oauth2Service
.
getUserInfo
(
authCode
);
log
.
info
(
"=> 查询企微用户信息,返回结果:{},{}"
,
authCode
,
JSON
.
toJSONString
(
userInfo
));
UserDetails
userDetails
=
this
.
userDetailsServiceImpl
.
loadUserByUsername2
(
userInfo
.
getUserId
());
token
=
this
.
tokenService
.
createToken
((
LoginUser
)
userDetails
);
}
catch
(
Exception
e
)
{
log
.
error
(
"=> 查询用户信息失败:"
,
e
);
throw
new
ServiceException
(
"登录失败,查询用户信息失败。"
);
}
}
log
.
info
(
"=> 登录结果:{}"
,
token
);
return
AjaxResult
.
success
(
"登录成功"
,
token
);
}
/**
* 获取用户信息
*
...
...
@@ -129,16 +174,16 @@ public class SysLoginController {
* @return 登录结果
*/
@PostMapping
(
"/bbs/mobile/user/code/login"
)
public
AjaxResult
c
odeLogin
(
@RequestBody
WxcpCodeLogin
bo
)
{
public
AjaxResult
mobileC
odeLogin
(
@RequestBody
WxcpCodeLogin
bo
)
{
LoginUser
loginUser
=
SecurityUtils
.
getLoginUserNotEx
();
log
.
info
(
"=> 登录请求参数:{}"
,
bo
);
log
.
info
(
"=> 当前登录用户:{}"
,
loginUser
);
// 企微登录认证链接
String
authCode
=
bo
.
getCode
();
WxCpOAuth2Service
oauth2Service
=
this
.
w
xCpService
.
getOauth2Service
();
WxCpOAuth2Service
oauth2Service
=
this
.
mobileW
xCpService
.
getOauth2Service
();
if
(
Objects
.
isNull
(
loginUser
)
&&
StrUtil
.
isBlank
(
authCode
))
{
String
oauth2Url
=
oauth2Service
.
buildAuthorizationUrl
(
this
.
r
edirectUrl
,
null
);
String
oauth2Url
=
oauth2Service
.
buildAuthorizationUrl
(
this
.
mobileR
edirectUrl
,
null
);
log
.
info
(
"=> 认证失败,返回Oauth2登录链接:{}"
,
oauth2Url
);
return
AjaxResult
.
error
(
401
,
"身份认证失败"
,
oauth2Url
);
}
...
...
safe-campus-admin/src/main/resources/application-dev.yml
View file @
79e3bfa9
...
...
@@ -92,11 +92,17 @@ spring:
listener
:
max-concurrency
:
3
# 企业微信配置
wx
:
cp
:
redirect-url
:
https://test.tangguo.ren/bbsh5/pages/login/login
pc-redirect-url
:
https://test.tangguo.ren/bbs/pc/wechatlogin
mobile-redirect-url
:
https://test.tangguo.ren/bbsh5/pages/login/login
corp-id
:
ww63ca87d5f8647514
app-config
:
agent-id
:
1000072
secret
:
O2KXf2b9oGG2GBrpzDgf4EFdhGwl2KaS9BWtJQT1I64
app-configs
:
-
name
:
'
移动端应用配置'
agent-id
:
1000072
secret
:
O2KXf2b9oGG2GBrpzDgf4EFdhGwl2KaS9BWtJQT1I64
-
name
:
'
管理端应用配置'
agent-id
:
1000072
secret
:
O2KXf2b9oGG2GBrpzDgf4EFdhGwl2KaS9BWtJQT1I64
safe-campus-admin/src/main/resources/application-jxfz.yml
View file @
79e3bfa9
...
...
@@ -95,8 +95,13 @@ spring:
# 企业微信配置
wx
:
cp
:
redirect-url
:
https://wecom.jift.edu.cn/bbsh5/pages/login/login
pc-redirect-url
:
https://wecom.jift.edu.cn/bbs/pc/wechatlogin
mobile-redirect-url
:
https://wecom.jift.edu.cn/bbs/h5/pages/login/login
corp-id
:
wxd2a84aa7529d3801
app-config
:
agent-id
:
1000218
secret
:
UubIP6xbLBzw3DwcIyOARYf1e4cm5GNJKNFZTlVfgyo
app-configs
:
-
name
:
'
移动端应用配置'
agent-id
:
1000218
secret
:
UubIP6xbLBzw3DwcIyOARYf1e4cm5GNJKNFZTlVfgyo
-
name
:
'
管理端应用配置'
agent-id
:
1000219
secret
:
OEMM3DAd-2FK-9Ggiu3xsD7Sg4SlPuV7os1hAWrTIwk
safe-campus-admin/src/main/resources/application-test.yml
View file @
79e3bfa9
...
...
@@ -95,7 +95,13 @@ spring:
# 企业微信配置
wx
:
cp
:
pc-redirect-url
:
https://test.tangguo.ren/bbs/pc/wechatlogin
mobile-redirect-url
:
https://test.tangguo.ren/bbsh5/pages/login/login
corp-id
:
ww63ca87d5f8647514
app-config
:
agent-id
:
1000072
secret
:
O2KXf2b9oGG2GBrpzDgf4EFdhGwl2KaS9BWtJQT1I64
app-configs
:
-
name
:
'
移动端应用配置'
agent-id
:
1000072
secret
:
O2KXf2b9oGG2GBrpzDgf4EFdhGwl2KaS9BWtJQT1I64
-
name
:
'
管理端应用配置'
agent-id
:
1000072
secret
:
O2KXf2b9oGG2GBrpzDgf4EFdhGwl2KaS9BWtJQT1I64
safe-campus-admin/src/main/resources/application.yml
View file @
79e3bfa9
...
...
@@ -119,14 +119,3 @@ xss:
excludes
:
/system/notice
# 匹配链接
urlPatterns
:
/system/*,/monitor/*,/tool/*
mobile
:
auth
:
res-token-name
:
token
req-token-name
:
Authorization
issuer
:
Mobile-Auth
algorithm-id
:
HS512
sign-key
:
SignKey2025@.
effective-time
:
7d
path-patterns
:
/bbs/mobile/**
safe-campus-admin/src/test/java/com/tangguo/ApplicationTest.java
View file @
79e3bfa9
...
...
@@ -23,14 +23,14 @@ public class ApplicationTest {
private
JmsTemplate
jmsTemplate
;
@Resource
private
WxCpService
w
xCpService
;
private
WxCpService
mobileW
xCpService
;
@Test
public
void
test
()
{
WxCpOAuth2Service
oauth2Service
=
this
.
w
xCpService
.
getOauth2Service
();
System
.
out
.
println
(
oauth2Service
.
buildAuthorizationUrl
(
"https://
test
.tangguo.ren/bbs/h5/pages/login/login/"
,
""
));
WxCpOAuth2Service
oauth2Service
=
this
.
mobileW
xCpService
.
getOauth2Service
();
System
.
out
.
println
(
oauth2Service
.
buildAuthorizationUrl
(
"https://
qywx
.tangguo.ren/bbs/h5/pages/login/login/"
,
""
));
}
...
...
safe-campus-bbs-ui/src/api/login.js
View file @
79e3bfa9
...
...
@@ -56,4 +56,16 @@ export function getCodeImg() {
method
:
'
get
'
,
timeout
:
20000
})
}
\ No newline at end of file
}
// 企业
export
function
loginByWechatWork
(
data
)
{
return
request
({
url
:
'
/pc/code/login
'
,
headers
:
{
isToken
:
false
},
method
:
'
post
'
,
data
:
data
})
}
safe-campus-bbs-ui/src/permission.js
View file @
79e3bfa9
...
...
@@ -8,7 +8,7 @@ import { isRelogin } from '@/utils/request'
NProgress
.
configure
({
showSpinner
:
false
})
const
whiteList
=
[
'
/login
'
,
'
/register
'
]
const
whiteList
=
[
'
/login
'
,
'
/register
'
,
'
/wechatlogin
'
]
router
.
beforeEach
((
to
,
from
,
next
)
=>
{
NProgress
.
start
()
...
...
safe-campus-bbs-ui/src/router/index.js
View file @
79e3bfa9
...
...
@@ -46,6 +46,11 @@ export const constantRoutes = [
component
:
()
=>
import
(
'
@/views/login
'
),
hidden
:
true
},
{
path
:
'
/wechatlogin
'
,
component
:
()
=>
import
(
'
@/views/wechatlogin
'
),
hidden
:
true
},
{
path
:
'
/register
'
,
component
:
()
=>
import
(
'
@/views/register
'
),
...
...
@@ -177,7 +182,7 @@ Router.prototype.replace = function push(location) {
}
export
default
new
Router
({
base
:
'
/bbspc
'
,
base
:
'
/bbs
/
pc
'
,
mode
:
'
history
'
,
// 去掉url中的#
scrollBehavior
:
()
=>
({
y
:
0
}),
routes
:
constantRoutes
...
...
safe-campus-bbs-ui/src/store/modules/user.js
View file @
79e3bfa9
import
{
login
,
logout
,
getInfo
}
from
'
@/api/login
'
import
{
getToken
,
setToken
,
removeToken
}
from
'
@/utils/auth
'
import
{
login
,
logout
,
getInfo
,
loginByWechatWork
}
from
"
@/api/login
"
;
import
{
getToken
,
setToken
,
removeToken
}
from
"
@/utils/auth
"
;
const
user
=
{
state
:
{
token
:
getToken
(),
name
:
''
,
avatar
:
''
,
name
:
""
,
avatar
:
""
,
roles
:
[],
permissions
:
[]
permissions
:
[]
,
},
mutations
:
{
SET_TOKEN
:
(
state
,
token
)
=>
{
state
.
token
=
token
state
.
token
=
token
;
},
SET_NAME
:
(
state
,
name
)
=>
{
state
.
name
=
name
state
.
name
=
name
;
},
SET_AVATAR
:
(
state
,
avatar
)
=>
{
state
.
avatar
=
avatar
state
.
avatar
=
avatar
;
},
SET_ROLES
:
(
state
,
roles
)
=>
{
state
.
roles
=
roles
state
.
roles
=
roles
;
},
SET_PERMISSIONS
:
(
state
,
permissions
)
=>
{
state
.
permissions
=
permissions
}
state
.
permissions
=
permissions
;
}
,
},
actions
:
{
getWechatLogin
({
commit
},
code
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
loginByWechatWork
({
code
})
.
then
((
res
)
=>
{
setToken
(
res
.
data
);
commit
(
"
SET_TOKEN
"
,
res
.
data
);
resolve
(
res
);
})
.
catch
((
error
)
=>
{
reject
(
error
);
});
});
},
// 登录
Login
({
commit
},
userInfo
)
{
const
username
=
userInfo
.
username
.
trim
()
const
password
=
userInfo
.
password
const
code
=
userInfo
.
code
const
uuid
=
userInfo
.
uuid
const
username
=
userInfo
.
username
.
trim
()
;
const
password
=
userInfo
.
password
;
const
code
=
userInfo
.
code
;
const
uuid
=
userInfo
.
uuid
;
return
new
Promise
((
resolve
,
reject
)
=>
{
login
(
username
,
password
,
code
,
uuid
).
then
(
res
=>
{
setToken
(
res
.
token
)
commit
(
'
SET_TOKEN
'
,
res
.
token
)
resolve
()
}).
catch
(
error
=>
{
reject
(
error
)
})
})
login
(
username
,
password
,
code
,
uuid
)
.
then
((
res
)
=>
{
setToken
(
res
.
token
);
commit
(
"
SET_TOKEN
"
,
res
.
token
);
resolve
();
})
.
catch
((
error
)
=>
{
reject
(
error
);
});
});
},
// 获取用户信息
GetInfo
({
commit
,
state
})
{
return
new
Promise
((
resolve
,
reject
)
=>
{
getInfo
().
then
(
res
=>
{
const
user
=
res
.
user
const
avatar
=
(
user
.
avatar
==
""
||
user
.
avatar
==
null
)
?
require
(
"
@/assets/images/profile.jpg
"
)
:
process
.
env
.
VUE_APP_BASE_API
+
user
.
avatar
;
if
(
res
.
roles
&&
res
.
roles
.
length
>
0
)
{
// 验证返回的roles是否是一个非空数组
commit
(
'
SET_ROLES
'
,
res
.
roles
)
commit
(
'
SET_PERMISSIONS
'
,
res
.
permissions
)
}
else
{
commit
(
'
SET_ROLES
'
,
[
'
ROLE_DEFAULT
'
])
}
commit
(
'
SET_NAME
'
,
user
.
userName
)
commit
(
'
SET_AVATAR
'
,
avatar
)
resolve
(
res
)
}).
catch
(
error
=>
{
reject
(
error
)
})
})
getInfo
()
.
then
((
res
)
=>
{
const
user
=
res
.
user
;
const
avatar
=
user
.
avatar
==
""
||
user
.
avatar
==
null
?
require
(
"
@/assets/images/profile.jpg
"
)
:
process
.
env
.
VUE_APP_BASE_API
+
user
.
avatar
;
if
(
res
.
roles
&&
res
.
roles
.
length
>
0
)
{
// 验证返回的roles是否是一个非空数组
commit
(
"
SET_ROLES
"
,
res
.
roles
);
commit
(
"
SET_PERMISSIONS
"
,
res
.
permissions
);
}
else
{
commit
(
"
SET_ROLES
"
,
[
"
ROLE_DEFAULT
"
]);
}
commit
(
"
SET_NAME
"
,
user
.
userName
);
commit
(
"
SET_AVATAR
"
,
avatar
);
resolve
(
res
);
})
.
catch
((
error
)
=>
{
reject
(
error
);
});
});
},
// 退出系统
LogOut
({
commit
,
state
})
{
return
new
Promise
((
resolve
,
reject
)
=>
{
logout
(
state
.
token
).
then
(()
=>
{
commit
(
'
SET_TOKEN
'
,
''
)
commit
(
'
SET_ROLES
'
,
[])
commit
(
'
SET_PERMISSIONS
'
,
[])
removeToken
()
resolve
()
}).
catch
(
error
=>
{
reject
(
error
)
})
})
logout
(
state
.
token
)
.
then
(()
=>
{
commit
(
"
SET_TOKEN
"
,
""
);
commit
(
"
SET_ROLES
"
,
[]);
commit
(
"
SET_PERMISSIONS
"
,
[]);
removeToken
();
resolve
();
})
.
catch
((
error
)
=>
{
reject
(
error
);
});
});
},
// 前端 登出
FedLogOut
({
commit
})
{
return
new
Promise
(
resolve
=>
{
commit
(
'
SET_TOKEN
'
,
''
)
removeToken
()
resolve
()
})
}
}
}
return
new
Promise
(
(
resolve
)
=>
{
commit
(
"
SET_TOKEN
"
,
""
);
removeToken
()
;
resolve
()
;
})
;
}
,
}
,
}
;
export
default
user
export
default
user
;
safe-campus-bbs-ui/src/utils/request.js
View file @
79e3bfa9
This diff is collapsed.
Click to expand it.
safe-campus-bbs-ui/src/views/wechatlogin.vue
0 → 100644
View file @
79e3bfa9
<
template
>
<div>
</div>
</
template
>
<
script
>
import
{
mapActions
}
from
'
vuex
'
export
default
{
mounted
()
{
if
(
this
.
isWeComEnv
())
{
// 企业微信环境处理
const
code
=
this
.
$route
.
query
.
code
this
.
getWechatLogin
(
code
).
then
(()
=>
{
this
.
$router
.
replace
(
'
/
'
)
})
}
else
{
// 非企业微信环境,跳转到普通登录页
this
.
$router
.
replace
(
'
/login
'
)
}
},
methods
:
{
// 判断是否为企业微信环境
isWeComEnv
()
{
// return true
const
userAgent
=
window
.
navigator
.
userAgent
.
toLowerCase
()
return
userAgent
.
includes
(
'
wxwork
'
)
||
(
userAgent
.
includes
(
'
micromessenger
'
)
&&
userAgent
.
includes
(
'
wxwork
'
))
},
// 映射 Vuex 中的 getWechatLogin 方法
...
mapActions
([
'
getWechatLogin
'
])
}
}
</
script
>
safe-campus-bbs-ui/vue.config.js
View file @
79e3bfa9
...
...
@@ -18,7 +18,7 @@ module.exports = {
// 部署生产环境和开发环境下的URL。
// 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
publicPath
:
process
.
env
.
NODE_ENV
===
"
production
"
?
"
/bbspc
"
:
"
/
"
,
publicPath
:
process
.
env
.
NODE_ENV
===
"
production
"
?
"
/bbs
/
pc
"
:
"
/
"
,
// 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist)
outputDir
:
'
dist
'
,
// 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
...
...
safe-campus-bbs-uniapp/manifest.json
View file @
79e3bfa9
{
"name"
:
"社区"
,
"appid"
:
"__UNI__
E3457E1
"
,
"appid"
:
"__UNI__
69A40B9
"
,
"description"
:
""
,
"versionName"
:
"1.0.0"
,
"versionCode"
:
"100"
,
...
...
@@ -72,7 +72,7 @@
"h5"
:
{
"router"
:
{
"mode"
:
"history"
,
"base"
:
"/bbsh5/"
"base"
:
"/bbs
/
h5/"
}
}
}
safe-campus-framework/src/main/java/com/tangguo/framework/config/SecurityConfig.java
View file @
79e3bfa9
...
...
@@ -110,7 +110,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 过滤请求
.
authorizeRequests
()
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
.
antMatchers
(
"/login"
,
"/bbs/mobile/user/code/login"
,
"/register"
,
"/captchaImage"
).
permitAll
()
.
antMatchers
(
"/login"
,
"/bbs/mobile/user/code/login"
,
"/
pc/code/login"
,
"/
register"
,
"/captchaImage"
).
permitAll
()
// 静态资源,可匿名访问
.
antMatchers
(
HttpMethod
.
GET
,
"/"
,
"/*.html"
,
"/**/*.html"
,
"/**/*.css"
,
"/**/*.js"
,
"/profile/**"
).
permitAll
()
.
antMatchers
(
"/swagger-ui.html"
,
"/swagger-resources/**"
,
"/webjars/**"
,
"/*/api-docs"
,
"/druid/**"
).
permitAll
()
...
...
safe-campus-framework/src/main/java/com/tangguo/framework/security/handle/AuthenticationEntryPointImpl.java
View file @
79e3bfa9
...
...
@@ -33,10 +33,10 @@ public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, S
private
static
final
long
serialVersionUID
=
-
8970718410437077606L
;
@Autowired
private
WxCpService
w
xCpService
;
private
WxCpService
mobileW
xCpService
;
@Value
(
"${wx.cp.redirect-url}"
)
private
String
r
edirectUrl
;
@Value
(
"${wx.cp.
mobile-
redirect-url}"
)
private
String
mobileR
edirectUrl
;
@Override
public
void
commence
(
HttpServletRequest
request
,
HttpServletResponse
response
,
AuthenticationException
e
)
...
...
@@ -47,8 +47,8 @@ public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, S
log
.
info
(
"=> 身份认证失败,Token:{}"
,
request
.
getHeader
(
"Authorization"
));
if
(
uri
.
startsWith
(
"/bbs/mobile"
))
{
WxCpOAuth2Service
oauth2Service
=
this
.
w
xCpService
.
getOauth2Service
();
String
oauth2Url
=
oauth2Service
.
buildAuthorizationUrl
(
this
.
r
edirectUrl
,
null
);
WxCpOAuth2Service
oauth2Service
=
this
.
mobileW
xCpService
.
getOauth2Service
();
String
oauth2Url
=
oauth2Service
.
buildAuthorizationUrl
(
this
.
mobileR
edirectUrl
,
null
);
ServletUtils
.
renderString
(
response
,
JSON
.
toJSONString
(
AjaxResult
.
error
(
401
,
"身份认证失败"
,
oauth2Url
)));
}
else
{
String
msg
=
StringUtils
.
format
(
"请求访问:{},认证失败,无法访问系统资源"
,
uri
);
...
...
safe-campus-framework/src/main/java/com/tangguo/framework/web/service/SysLoginService.java
View file @
79e3bfa9
...
...
@@ -65,7 +65,7 @@ public class SysLoginService {
private
UserDetailsServiceImpl
userDetailsServiceImpl
;
@Autowired
private
WxCpService
w
xCpService
;
private
WxCpService
mobileW
xCpService
;
/**
...
...
safe-campus-framework/src/main/java/com/tangguo/framework/wxcp/WxCpConfiguration.java
View file @
79e3bfa9
...
...
@@ -9,6 +9,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
java.util.List
;
import
java.util.Objects
;
...
...
@@ -29,10 +30,11 @@ public class WxCpConfiguration {
/**
* 配置 WxCpService 实例
*/
@Bean
public
WxCpService
wxCpService
()
{
WxCpProperties
.
AppConfig
appConfig
=
this
.
properties
.
getAppConfig
();
WxCpDefaultConfigImpl
configStorage
=
new
WxCpDefaultConfigImpl
();
@Bean
(
"mobileWxCpService"
)
public
WxCpService
mobileWxCpService
()
{
List
<
WxCpProperties
.
AppConfig
>
appConfigs
=
this
.
properties
.
getAppConfigs
();
WxCpProperties
.
AppConfig
appConfig
=
appConfigs
.
get
(
0
);
WxCpDefaultConfigImpl
configStorage
=
new
WxCpDefaultConfigImpl
();
configStorage
.
setCorpId
(
this
.
properties
.
getCorpId
());
configStorage
.
setAgentId
(
appConfig
.
getAgentId
());
configStorage
.
setCorpSecret
(
appConfig
.
getSecret
());
...
...
@@ -43,4 +45,23 @@ public class WxCpConfiguration {
return
service
;
}
/**
* 配置 WxCpService 实例
*/
@Bean
(
"pcWxCpService"
)
public
WxCpService
pcWxCpService
()
{
List
<
WxCpProperties
.
AppConfig
>
appConfigs
=
this
.
properties
.
getAppConfigs
();
WxCpProperties
.
AppConfig
appConfig
=
appConfigs
.
get
(
1
);
WxCpDefaultConfigImpl
configStorage
=
new
WxCpDefaultConfigImpl
();
configStorage
.
setCorpId
(
this
.
properties
.
getCorpId
());
configStorage
.
setAgentId
(
appConfig
.
getAgentId
());
configStorage
.
setCorpSecret
(
appConfig
.
getSecret
());
configStorage
.
setToken
(
appConfig
.
getToken
());
configStorage
.
setAesKey
(
appConfig
.
getAesKey
());
WxCpService
service
=
new
WxCpServiceImpl
();
service
.
setWxCpConfigStorage
(
configStorage
);
return
service
;
}
}
safe-campus-framework/src/main/java/com/tangguo/framework/wxcp/WxCpProperties.java
View file @
79e3bfa9
...
...
@@ -3,6 +3,8 @@ package com.tangguo.framework.wxcp;
import
lombok.Data
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
java.util.List
;
/**
* 企业微信配置类
*
...
...
@@ -21,12 +23,14 @@ public class WxCpProperties {
/**
* 多应用配置
*/
private
AppConfig
appConfig
;
private
List
<
AppConfig
>
appConfigs
;
@Data
public
static
class
AppConfig
{
private
String
name
;
/**
* 设置企业微信应用的AgentId
*/
...
...
safe-campus-moment/src/main/java/com/tangguo/controller/mobile/MBbsMomentController.java
View file @
79e3bfa9
...
...
@@ -14,6 +14,8 @@ import com.tangguo.service.IBbsMomentCommentService;
import
com.tangguo.service.IBbsMomentService
;
import
com.tangguo.service.IBbsMomentVoteOptionService
;
import
com.tangguo.service.IBbsMomentVoteService
;
import
io.swagger.annotations.ApiOperation
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.web.bind.annotation.*
;
import
javax.annotation.Resource
;
...
...
@@ -216,4 +218,16 @@ public class MBbsMomentController {
return
AjaxResult
.
success
();
}
/**
* 置顶评论
*/
@ApiOperation
(
"置顶评论"
)
@PostMapping
(
"/comment/top"
)
public
AjaxResult
topComment
(
@RequestBody
BbsCommentTopBO
bo
)
{
ValidateOperations
.
generalValidate
(
bo
);
this
.
momentService
.
userTopComment
(
bo
);
return
AjaxResult
.
success
();
}
}
safe-campus-moment/src/main/java/com/tangguo/controller/pc/BbsMomentCommentController.java
View file @
79e3bfa9
...
...
@@ -6,9 +6,11 @@ import com.tangguo.common.core.domain.AjaxResult;
import
com.tangguo.common.core.page.TableDataInfo
;
import
com.tangguo.common.enums.BusinessType
;
import
com.tangguo.domain.BbsMomentComment
;
import
com.tangguo.domain.bo.BbsCommentTopBO
;
import
com.tangguo.service.IBbsMomentCommentService
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.checkerframework.checker.units.qual.A
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.web.bind.annotation.*
;
...
...
@@ -79,4 +81,16 @@ public class BbsMomentCommentController extends BaseController {
return
getDataTable
(
list
);
}
/**
* 置顶评论
*/
@ApiOperation
(
"置顶评论"
)
@PreAuthorize
(
"@ss.hasPermi('moment:comment:top')"
)
@PostMapping
(
"/top"
)
public
AjaxResult
topComment
(
@RequestBody
BbsCommentTopBO
bo
)
{
this
.
bbsMomentCommentService
.
topMomentComment
(
bo
);
return
AjaxResult
.
success
();
}
}
safe-campus-moment/src/main/java/com/tangguo/domain/BbsMomentComment.java
View file @
79e3bfa9
...
...
@@ -13,6 +13,7 @@ import lombok.NoArgsConstructor;
import
lombok.ToString
;
import
lombok.experimental.Accessors
;
import
java.util.Date
;
import
java.util.List
;
/**
...
...
@@ -90,6 +91,14 @@ public class BbsMomentComment extends BaseEntity {
@ApiModelProperty
(
"删除评论内容"
)
private
String
deleteComment
;
/** 评论是否置顶:0 否、1 是 */
@ApiModelProperty
(
"评论是否置顶:0 否、1 是"
)
private
Integer
isTop
;
/** 评论置顶时间 */
@ApiModelProperty
(
"评论置顶时间"
)
private
Date
topTime
;
/**
* 动态内容
*/
...
...
safe-campus-moment/src/main/java/com/tangguo/domain/bo/BbsCommentTopBO.java
0 → 100644
View file @
79e3bfa9
package
com
.
tangguo
.
domain
.
bo
;
import
lombok.Data
;
import
javax.validation.constraints.NotNull
;
/**
*
*
* @author 谈笑
* @createTime 2025-11-05 16:12:43 星期三
*/
@Data
public
class
BbsCommentTopBO
{
/**
* 动态Id
*/
@NotNull
(
message
=
"动态Id不能为空"
)
private
Long
momentId
;
/**
* 评论Id
*/
@NotNull
(
message
=
"评论Id不能为空"
)
private
Long
commentId
;
/**
* 置顶状态:0 取消置顶、1 置顶
*/
@NotNull
(
message
=
"置顶状态不能为空"
)
private
Integer
isTop
;
}
safe-campus-moment/src/main/java/com/tangguo/service/IBbsMomentCommentService.java
View file @
79e3bfa9
...
...
@@ -2,6 +2,7 @@ package com.tangguo.service;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.tangguo.domain.BbsMomentComment
;
import
com.tangguo.domain.bo.BbsCommentTopBO
;
import
com.tangguo.domain.vo.BbsCommentDetailVO
;
import
java.util.List
;
...
...
@@ -68,4 +69,12 @@ public interface IBbsMomentCommentService extends IService<BbsMomentComment> {
*/
void
deleteMomentComments
(
Long
momentId
);
/**
* 置顶评论
*
* @param bo 请求参数
*/
void
topMomentComment
(
BbsCommentTopBO
bo
);
}
safe-campus-moment/src/main/java/com/tangguo/service/IBbsMomentService.java
View file @
79e3bfa9
...
...
@@ -133,4 +133,12 @@ public interface IBbsMomentService extends IService<BbsMoment> {
*/
void
userFeaturedComment
(
FeaturedCommentBO
bo
);
/**
* 置顶评论
*
* @param bo 评论
*/
void
userTopComment
(
BbsCommentTopBO
bo
);
}
safe-campus-moment/src/main/java/com/tangguo/service/impl/BbsMomentCommentServiceImpl.java
View file @
79e3bfa9
package
com
.
tangguo
.
service
.
impl
;
import
cn.hutool.core.collection.CollUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.tangguo.common.exception.ServiceException
;
import
com.tangguo.domain.BbsMomentComment
;
import
com.tangguo.domain.bo.BbsCommentTopBO
;
import
com.tangguo.domain.vo.BbsCommentDetailVO
;
import
com.tangguo.mapper.BbsMomentCommentMapper
;
import
com.tangguo.service.IBbsMomentCommentService
;
...
...
@@ -11,6 +15,7 @@ import org.springframework.stereotype.Service;
import
javax.annotation.Resource
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Objects
;
...
...
@@ -110,4 +115,29 @@ public class BbsMomentCommentServiceImpl extends ServiceImpl<BbsMomentCommentMap
);
}
/**
* 置顶评论
*
* @param bo 请求参数
*/
@Override
public
void
topMomentComment
(
BbsCommentTopBO
bo
)
{
BbsMomentComment
dbComment
=
this
.
getById
(
bo
.
getCommentId
());
if
(
Objects
.
isNull
(
dbComment
))
{
throw
new
ServiceException
(
"操作失败,未查询到当前评论数据。"
);
}
LambdaUpdateWrapper
<
BbsMomentComment
>
wrapper
=
new
LambdaUpdateWrapper
<>();
wrapper
.
eq
(
BbsMomentComment:
:
getId
,
dbComment
.
getId
());
if
(
bo
.
getIsTop
()
==
1
)
{
wrapper
.
set
(
BbsMomentComment:
:
getIsTop
,
1
);
wrapper
.
set
(
BbsMomentComment:
:
getTopTime
,
new
Date
());
}
else
{
wrapper
.
set
(
BbsMomentComment:
:
getIsTop
,
0
);
wrapper
.
set
(
BbsMomentComment:
:
getTopTime
,
null
);
}
this
.
update
(
wrapper
);
}
}
safe-campus-moment/src/main/java/com/tangguo/service/impl/BbsMomentServiceImpl.java
View file @
79e3bfa9
...
...
@@ -467,8 +467,29 @@ public class BbsMomentServiceImpl extends ServiceImpl<BbsMomentMapper, BbsMoment
this
.
commentService
.
updateById
(
updComment
);
}
/**
/**
* 置顶评论
*
* @param bo 评论
*/
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Override
public
void
userTopComment
(
BbsCommentTopBO
bo
)
{
BbsMoment
dbMoment
=
this
.
getById
(
bo
.
getMomentId
());
if
(
Objects
.
isNull
(
dbMoment
))
{
throw
new
ServiceException
(
"操作失败,未查询到当前动态数据。"
);
}
String
userName
=
SecurityUtils
.
getUsername
();
if
(!
dbMoment
.
getUserName
().
equals
(
userName
))
{
throw
new
ServiceException
(
"操作失败,没有对当前动态评论的操作权限。"
);
}
this
.
commentService
.
topMomentComment
(
bo
);
}
/**
* 构建动态实体
*
* @param bo 动态
...
...
safe-campus-moment/src/main/resources/mapper/BbsMomentCommentMapper.xml
View file @
79e3bfa9
...
...
@@ -27,7 +27,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if>
</where>
ORDER BY
c.create_time DESC
c.
is_top DESC, c.top_time DESC, c.
create_time DESC
</select>
...
...
@@ -41,7 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE
status = 1 AND FIND_IN_SET(#{commentId}, r.ancestor_path) AND r.id != #{commentId}
ORDER BY
r.create_time
r.is_top DESC, r.top_time DESC,
r.create_time
</select>
...
...
@@ -53,7 +53,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE
status = 1 AND moment_id = #{momentId}
ORDER BY
create_time
is_top DESC, top_time DESC,
create_time
</select>
...
...
@@ -94,6 +94,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
OR m.is_enable_featured_comment = 0
OR (m.is_enable_featured_comment = 1 AND (c.user_name = #{userName} OR c.is_featured = 1))
)
ORDER BY
c.is_top DESC, c.top_time DESC, c.create_time
) AS c
WHERE rn
<
= #{rows};
</select>
...
...
@@ -126,7 +128,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
OR (m.is_enable_featured_comment = 1 AND (c.user_name = #{userName} OR c.is_featured = 1))
)
ORDER BY
c.create_time
c.is_top DESC, c.top_time DESC,
c.create_time
</select>
</mapper>
safe-campus-moment/src/main/resources/mapper/BbsMomentMapper.xml
View file @
79e3bfa9
...
...
@@ -20,6 +20,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"moment.content != null and moment.content != ''"
>
m.content LIKE CONCAT('%', #{moment.content}, '%')
</if>
<if
test=
"moment.userName != null and moment.userName != ''"
>
AND uv.user_name LIKE CONCAT('%', #{moment.userName}, '%')
</if>
<if
test=
"moment.nickName != null and moment.nickName != ''"
>
AND uv.nick_name LIKE CONCAT('%', #{moment.nickName}, '%')
</if>
<if
test=
"moment.topicNames != null and moment.topicNames != ''"
>
AND m.topic_names LIKE CONCAT('%', #{moment.topicNames}, '%')
</if>
...
...
@@ -133,7 +139,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
) v ON v.moment_id = m.id
<where>
<if
test=
"bo.content != null and bo.content != ''"
>
m.content LIKE CONCAT('%', #{bo.content}, '%')
(m.content LIKE CONCAT('%', #{bo.content}, '%')
OR uv.user_name LIKE CONCAT('%', #{bo.content}, '%')
OR uv.nick_name LIKE CONCAT('%', #{bo.content}, '%'))
</if>
<if
test=
"bo.topicName != null and bo.topicName != ''"
>
AND m.topic_names LIKE CONCAT('%', #{bo.topicName}, '%')
...
...
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