Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sass-admin
Overview
Overview
Details
Activity
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
hqzhdj_app
sass-admin
Commits
82defef6
Commit
82defef6
authored
Nov 25, 2025
by
chengming
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
header增加消息跑马灯
parent
14388ef9
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
316 additions
and
49 deletions
+316
-49
dist.zip
+0
-0
src/common/Layout/Header/Header.less
+208
-0
src/common/Layout/Header/api.js
+2
-0
src/common/Layout/Header/index.js
+93
-47
src/common/Layout/Header/redux/actions.js
+13
-1
src/pages/Login/redux/actions.js
+0
-1
No files found.
dist.zip
0 → 100644
View file @
82defef6
File added
src/common/Layout/Header/Header.less
View file @
82defef6
...
...
@@ -216,3 +216,210 @@
background: #FBB9BC;
}
}
// 跑马灯样式
.marqueeContainer {
display: flex;
align-items: center;
flex: 1;
margin: 0 20px;
height: 100%;
overflow: hidden;
border-radius: 4px;
padding: 0 12px;
.marqueeIcon {
color: #ff6b6b;
font-size: 18px;
margin-right: 12px;
flex-shrink: 0;
animation: bellRing 2s infinite;
}
.marqueeContent {
flex: 1;
height: 100%;
display: flex;
align-items: center;
.marqueeCarousel {
width: 100%;
height: 24px;
line-height: 24px;
:global {
.slick-list {
height: 24px;
}
.slick-track {
height: 24px;
}
.slick-slide {
height: 24px !important;
line-height: 24px !important;
text-align: left;
background: transparent;
border: none;
}
}
}
.marqueeItem {
display: flex;
align-items: center;
height: 24px;
line-height: 24px;
font-size: 14px;
color: #495057;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
.marqueeType {
color: #ffffff;
background: #ff6b6b;
padding: 2px 6px;
border-radius: 3px;
margin-right: 10px;
font-weight: 600;
font-size: 12px;
min-width: 40px;
text-align: center;
}
.marqueeName {
margin-right: 15px;
font-weight: 600;
color: #212529;
max-width: 180px;
overflow: hidden;
text-overflow: ellipsis;
background: linear-gradient(90deg, #212529 0%, #495057 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.marqueeCreator {
margin-right: 15px;
color: #6c757d;
font-weight: 500;
background: #f8f9fa;
padding: 1px 6px;
border-radius: 3px;
border: 1px solid #e9ecef;
}
.marqueeTime {
color: #868e96;
font-weight: 500;
background: linear-gradient(90deg, #868e96 0%, #adb5bd 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
}
}
// 铃铛动画
@keyframes bellRing {
0%, 100% {
transform: rotate(0deg);
}
25% {
transform: rotate(-10deg);
}
75% {
transform: rotate(10deg);
}
}
// 跑马灯悬停效果
.marqueeContainer:hover {
.marqueeIcon {
color: #ff5252;
animation-duration: 1s;
}
}
// 空状态样式
.marqueeItem:only-child {
justify-content: center;
color: #6c757d;
font-style: italic;
width: 100%;
&:before {
content: "📢 ";
margin-right: 5px;
}
}
// 响应式适配
@media (max-width: 1200px) {
.marqueeContainer {
.marqueeContent {
.marqueeItem {
.marqueeName {
max-width: 120px;
}
.marqueeCreator {
display: none;
}
}
}
}
}
@media (max-width: 992px) {
.marqueeContainer {
margin: 0 10px;
padding: 0 8px;
.marqueeContent {
.marqueeItem {
.marqueeTime {
display: none;
}
.marqueeName {
max-width: 100px;
}
}
}
}
}
@media (max-width: 768px) {
.marqueeContainer {
display: none;
}
}
// 特殊类型颜色
.marqueeItem .marqueeType[data-type="考试"] {
background: #4ecdc4;
}
.marqueeItem .marqueeType[data-type="投票"] {
background: #45b7d1;
}
.marqueeItem .marqueeType[data-type="信箱"] {
background: #96ceb4;
}
.marqueeItem .marqueeType[data-type="活动"] {
background: #feca57;
}
.marqueeItem .marqueeType[data-type="投稿"] {
background: #ff9ff3;
}
.marqueeItem .marqueeType[data-type="留言"] {
background: #54a0ff;
}
\ No newline at end of file
src/common/Layout/Header/api.js
View file @
82defef6
...
...
@@ -3,4 +3,5 @@ export default {
siteLanguagePageApi
:
`GET
${
services
.
webManage
}
/siteLanguage/public/page`
,
publicLanguageGetApi
:
`GET
${
services
.
webManage
}
/international/public/language/get`
,
selectLanguageSaveApi
:
`GET
${
services
.
webManage
}
/siteLanguage/record/international/selectLanguage/save`
,
getPromptScrollDataApi
:
`POST
${
services
.
webManage
}
/prompt/scroll/data`
,
};
\ No newline at end of file
src/common/Layout/Header/index.js
View file @
82defef6
import
React
,
{
PureComponent
}
from
"react"
;
import
{
withRouter
}
from
"react-router-dom"
;
import
{
connect
}
from
"react-redux"
;
import
PropTypes
from
"prop-types"
;
import
{
Tooltip
,
Dropdown
,
Menu
,
Icon
,
Layout
,
Avatar
}
from
"antd"
;
import
{
Tooltip
,
Dropdown
,
Menu
,
Icon
,
Layout
,
Avatar
,
Carousel
}
from
"antd"
;
import
classnames
from
"classnames"
;
import
styles
from
"./Header.less"
;
import
SelectLang
from
"./SelectLang"
;
import
{
getPromptScrollData
}
from
"./redux/actions"
;
{
/* bug-11961-cwj暂时注释 2期上 */
}
...
...
@@ -15,13 +17,74 @@ import headerLogo from "../../../static/imgs/1logo.png";
class
Header
extends
PureComponent
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{};
this
.
state
=
{
scrollData
:
{
examList
:
[],
voteManagement
:
[],
mailboxManagement
:
[],
activityManagement
:
[],
submissionManagement
:
[],
messageManagement
:
[]
}
};
}
componentDidMount
()
{}
componentDidMount
()
{
this
.
fetchScrollData
();
}
fetchScrollData
=
()
=>
{
const
{
getPromptScrollData
}
=
this
.
props
;
getPromptScrollData
({},
(
res
)
=>
{
if
(
res
&&
res
.
data
)
{
this
.
setState
({
scrollData
:
res
.
data
});
}
});
};
handleClickMenu
=
e
=>
{
e
.
key
===
"SignOut"
&&
this
.
props
.
onSignOut
();
};
// 渲染跑马灯内容
renderMarqueeContent
=
()
=>
{
const
{
scrollData
}
=
this
.
state
;
const
allItems
=
[
...
scrollData
.
examList
.
map
(
item
=>
({
...
item
,
type
:
'考试'
})),
...
scrollData
.
voteManagement
.
map
(
item
=>
({
...
item
,
type
:
'投票'
})),
...
scrollData
.
mailboxManagement
.
map
(
item
=>
({
...
item
,
type
:
'信箱'
})),
...
scrollData
.
activityManagement
.
map
(
item
=>
({
...
item
,
type
:
'活动'
})),
...
scrollData
.
submissionManagement
.
map
(
item
=>
({
...
item
,
type
:
'投稿'
})),
...
scrollData
.
messageManagement
.
map
(
item
=>
({
...
item
,
type
:
'留言'
}))
];
if
(
allItems
.
length
===
0
)
{
return
(
<
div
className
=
{
styles
.
marqueeItem
}
>
暂无最新消息
<
/div
>
);
}
return
allItems
.
map
((
item
,
index
)
=>
(
<
div
key
=
{
index
}
className
=
{
styles
.
marqueeItem
}
>
<
span
className
=
{
styles
.
marqueeType
}
data
-
type
=
{
item
.
type
}
>
[{
item
.
type
}]
<
/span
>
<
span
className
=
{
styles
.
marqueeName
}
>
{
item
.
name
}
<
/span
>
<
span
className
=
{
styles
.
marqueeCreator
}
>
创建人:
{
item
.
createByName
}
<
/span
>
<
span
className
=
{
styles
.
marqueeTime
}
>
时间:
{
new
Date
(
item
.
createTime
).
toLocaleString
()}
<
/span
>
<
/div
>
));
};
render
()
{
const
{
fixed
,
...
...
@@ -34,6 +97,7 @@ class Header extends PureComponent {
menus
,
onToAss
,
}
=
this
.
props
;
// 站点选择
const
siteMenu
=
(
<
Menu
onClick
=
{
onHandleMenuClick
}
>
...
...
@@ -42,6 +106,7 @@ class Header extends PureComponent {
))}
<
/Menu
>
);
// 个人选择
const
menu
=
(
<
Menu
className
=
{
styles
.
menu
}
>
...
...
@@ -56,6 +121,7 @@ class Header extends PureComponent {
<
/Menu.Item
>
<
/Menu
>
);
// 是否开通了社群
let
associationButton
=
false
;
let
hasAssociation
=
menus
.
filter
(
item
=>
item
.
name
===
"社群"
);
...
...
@@ -71,52 +137,21 @@ class Header extends PureComponent {
})}
id
=
"layoutHeader"
>
<
div
>
{
/* {collapsed && (
<div
className={styles.button}
onClick={onCollapseChange.bind(this, !collapsed)}
<
div
className
=
{
styles
.
marqueeContainer
}
>
<
Icon
type
=
"sound"
className
=
{
styles
.
marqueeIcon
}
/
>
<
div
className
=
{
styles
.
marqueeContent
}
>
<
Carousel
autoplay
vertical
dots
=
{
false
}
className
=
{
styles
.
marqueeCarousel
}
>
<Icon
type={classnames({
"menu-unfold": collapsed,
"menu-fold": !collapsed,
})}
/>
</div>
)} */
}
{
/* <div className={styles.logo}>
<img
className={styles.image}
// src={nav.logo ? nav.logo : headerLogo}
src={headerLogo}
/>
</div> */
}
{
this
.
renderMarqueeContent
()}
<
/Carousel
>
<
/div
>
<
/div
>
<
div
className
=
{
styles
.
rightContainer
}
>
{
/* bug-11961-cwj暂时注释 2期上 */
}
{
/* <Icon type="folder-open" style={{ padding: "0 12px" }} /> */
}
{
/* 语言 */
}
{
/* bug-11961-cwj暂时注释 2期上 */
}
{
/* <SelectLang className={styles.action} /> */
}
{
/* {associationButton && (
<a className={styles.assDiv} onClick={onToAss.bind(this)}>
<div className={styles.iconDiv}>
<Icon style={{ color: "white" }} type="home" />
</div>
<div className={styles.assText}>社群平台</div>
</a>
)} */
}
{
/* <Tooltip title={"使用帮助"}>
<a
target="_blank"
href="http://help.fairyclass.cn/hc/"
rel="noopener noreferrer"
className={styles.action}
>
<Icon type="question-circle-o" />
</a>
</Tooltip> */
}
<
Tooltip
title
=
{
"站点切换"
}
>
<
Dropdown
overlay
=
{
siteMenu
}
...
...
@@ -154,6 +189,16 @@ Header.propTypes = {
collapsed
:
PropTypes
.
bool
,
onSignOut
:
PropTypes
.
func
,
onCollapseChange
:
PropTypes
.
func
,
getPromptScrollData
:
PropTypes
.
func
,
};
// 连接redux
const
mapStateToProps
=
(
state
)
=>
({
// 如果需要从redux state中获取数据,可以在这里添加
});
const
mapDispatchToProps
=
{
getPromptScrollData
,
};
export
default
withRouter
(
Header
);
export
default
connect
(
mapStateToProps
,
mapDispatchToProps
)(
withRouter
(
Header
)
);
\ No newline at end of file
src/common/Layout/Header/redux/actions.js
View file @
82defef6
...
...
@@ -4,7 +4,8 @@ import api from "../api";
const
{
siteLanguagePageApi
,
publicLanguageGetApi
,
selectLanguageSaveApi
selectLanguageSaveApi
,
getPromptScrollDataApi
,
}
=
api
;
// 设置语音
export
function
langageActions
(
parms
)
{
...
...
@@ -55,3 +56,13 @@ export function selectLanguageSave(data, callback) {
});
};
}
export
function
getPromptScrollData
(
data
,
callback
)
{
return
dispath
=>
{
return
request
({
url
:
getPromptScrollDataApi
,
data
:
data
,
}).
then
(
res
=>
{
if
(
callback
)
callback
(
res
);
});
};
}
\ No newline at end of file
src/pages/Login/redux/actions.js
View file @
82defef6
...
...
@@ -55,7 +55,6 @@ export function exfetchR(data, cb, check) {
const
authRole
=
res
?.
data
?.
authRole
||
[];
if
(
authRole
.
length
>
0
)
{
userPermissions
=
JSON
.
stringify
(
authRole
.
map
(
role
=>
role
.
code
));
console
.
log
(
'userPermissions222222222222222222'
,
userPermissions
)
window
.
localStorage
.
setItem
(
"userPermissions"
,
userPermissions
);
}
else
{
window
.
localStorage
.
setItem
(
"userPermissions"
,
userPermissions
);
...
...
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