'admin-21.07.01:新增滚动通知栏/公告组件及演示界面'
This commit is contained in:
parent
b2fd7d6010
commit
382454ca0e
@ -45,7 +45,7 @@
|
|||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
"sass": "^1.35.1",
|
"sass": "^1.35.1",
|
||||||
"sass-loader": "^12.1.0",
|
"sass-loader": "^12.1.0",
|
||||||
"typescript": "^4.3.4",
|
"typescript": "^4.3.5",
|
||||||
"vite": "^2.3.8",
|
"vite": "^2.3.8",
|
||||||
"vue-eslint-parser": "^7.6.0"
|
"vue-eslint-parser": "^7.6.0"
|
||||||
},
|
},
|
||||||
|
191
src/components/noticeBar/index.vue
Normal file
191
src/components/noticeBar/index.vue
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
<template>
|
||||||
|
<div class="notice-bar" :style="{ background, height: `${height}px` }" v-show="!isMode">
|
||||||
|
<div class="notice-bar-warp" :style="{ color, fontSize: `${size}px` }">
|
||||||
|
<i v-if="leftIcon" class="notice-bar-warp-left-icon" :class="leftIcon"></i>
|
||||||
|
<div class="notice-bar-warp-text-box" ref="noticeBarWarpRef">
|
||||||
|
<div class="notice-bar-warp-text" ref="noticeBarWarpTextRef">
|
||||||
|
<template v-if="!scrollable">{{ text }}</template>
|
||||||
|
<template v-else><slot /></template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<i v-if="rightIcon" class="notice-bar-warp-right-icon" :class="rightIcon" @click="onRightIconClick"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { toRefs, reactive, defineComponent, ref, onMounted, nextTick } from 'vue';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'noticeBar',
|
||||||
|
props: {
|
||||||
|
// 通知栏模式,可选值为 closeable link
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: () => '',
|
||||||
|
},
|
||||||
|
// 通知文本内容
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
default: () => '',
|
||||||
|
},
|
||||||
|
// 通知文本颜色
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: () => 'var(--color-warning)',
|
||||||
|
},
|
||||||
|
// 通知背景色
|
||||||
|
background: {
|
||||||
|
type: String,
|
||||||
|
default: () => 'var(--color-warning-light-9)',
|
||||||
|
},
|
||||||
|
// 字体大小,单位px
|
||||||
|
size: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: () => 14,
|
||||||
|
},
|
||||||
|
// 通知栏高度,单位px
|
||||||
|
height: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: () => 40,
|
||||||
|
},
|
||||||
|
// 动画延迟时间 (s)
|
||||||
|
delay: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: () => 1,
|
||||||
|
},
|
||||||
|
// 滚动速率 (px/s)
|
||||||
|
speed: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: () => 100,
|
||||||
|
},
|
||||||
|
// 是否开启垂直滚动
|
||||||
|
scrollable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => false,
|
||||||
|
},
|
||||||
|
// 自定义左侧图标
|
||||||
|
leftIcon: {
|
||||||
|
type: String,
|
||||||
|
default: () => '',
|
||||||
|
},
|
||||||
|
// 自定义右侧图标
|
||||||
|
rightIcon: {
|
||||||
|
type: String,
|
||||||
|
default: () => '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const noticeBarWarpRef = ref();
|
||||||
|
const noticeBarWarpTextRef = ref();
|
||||||
|
const state = reactive({
|
||||||
|
order: 1,
|
||||||
|
oneTime: '',
|
||||||
|
twoTime: '',
|
||||||
|
warpOWidth: '',
|
||||||
|
textOWidth: '',
|
||||||
|
isMode: false,
|
||||||
|
});
|
||||||
|
// 初始化 animation 各项参数
|
||||||
|
const initAnimation = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
state.warpOWidth = noticeBarWarpRef.value.offsetWidth;
|
||||||
|
state.textOWidth = noticeBarWarpTextRef.value.offsetWidth;
|
||||||
|
document.styleSheets[0].insertRule(`@keyframes oneAnimation {0% {left: 0px;} 100% {left: -${state.textOWidth}px;}}`);
|
||||||
|
document.styleSheets[0].insertRule(`@keyframes twoAnimation {0% {left: ${state.warpOWidth}px;} 100% {left: -${state.textOWidth}px;}}`);
|
||||||
|
computeAnimationTime();
|
||||||
|
setTimeout(() => {
|
||||||
|
changeAnimation();
|
||||||
|
}, props.delay * 1000);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 计算 animation 滚动时长
|
||||||
|
const computeAnimationTime = () => {
|
||||||
|
state.oneTime = state.textOWidth / props.speed;
|
||||||
|
state.twoTime = (state.textOWidth + state.warpOWidth) / props.speed;
|
||||||
|
};
|
||||||
|
// 改变 animation 动画调用
|
||||||
|
const changeAnimation = () => {
|
||||||
|
if (state.order === 1) {
|
||||||
|
noticeBarWarpTextRef.value.style.animation = `oneAnimation ${state.oneTime}s linear`;
|
||||||
|
state.order = 2;
|
||||||
|
} else {
|
||||||
|
noticeBarWarpTextRef.value.style.animation = `twoAnimation ${state.twoTime}s linear infinite`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 监听 animation 动画的结束
|
||||||
|
const listenerAnimationend = () => {
|
||||||
|
noticeBarWarpTextRef.value.addEventListener(
|
||||||
|
'animationend',
|
||||||
|
() => {
|
||||||
|
changeAnimation();
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
};
|
||||||
|
// 右侧 icon 图标点击
|
||||||
|
const onRightIconClick = () => {
|
||||||
|
if (!props.mode) return false;
|
||||||
|
if (props.mode === 'closeable') {
|
||||||
|
state.isMode = true;
|
||||||
|
emit('close');
|
||||||
|
} else if (props.mode === 'link') {
|
||||||
|
emit('link');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 页面加载时
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.scrollable) return false;
|
||||||
|
initAnimation();
|
||||||
|
listenerAnimationend();
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
noticeBarWarpRef,
|
||||||
|
noticeBarWarpTextRef,
|
||||||
|
onRightIconClick,
|
||||||
|
...toRefs(state),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.notice-bar {
|
||||||
|
padding: 0 15px;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 4px;
|
||||||
|
.notice-bar-warp {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: inherit;
|
||||||
|
.notice-bar-warp-text-box {
|
||||||
|
flex: 1;
|
||||||
|
height: inherit;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
.notice-bar-warp-text {
|
||||||
|
white-space: nowrap;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
::v-deep(.el-carousel__item) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.notice-bar-warp-left-icon {
|
||||||
|
width: 24px;
|
||||||
|
}
|
||||||
|
.notice-bar-warp-right-icon {
|
||||||
|
width: 24px;
|
||||||
|
text-align: right;
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -24,6 +24,7 @@ export default {
|
|||||||
funCountup: 'countup',
|
funCountup: 'countup',
|
||||||
funEchartsTree: 'echartsTree',
|
funEchartsTree: 'echartsTree',
|
||||||
funSelector: 'funSelector',
|
funSelector: 'funSelector',
|
||||||
|
funNoticeBar: 'ScrollingNoticeBar',
|
||||||
funWangEditor: 'wangEditor',
|
funWangEditor: 'wangEditor',
|
||||||
funCropper: 'cropper',
|
funCropper: 'cropper',
|
||||||
funQrcode: 'qrcode',
|
funQrcode: 'qrcode',
|
||||||
|
@ -24,6 +24,7 @@ export default {
|
|||||||
funCountup: 'countup 数字滚动',
|
funCountup: 'countup 数字滚动',
|
||||||
funEchartsTree: 'echartsTree 树图',
|
funEchartsTree: 'echartsTree 树图',
|
||||||
funSelector: '图标选择器',
|
funSelector: '图标选择器',
|
||||||
|
funNoticeBar: '滚动通知栏',
|
||||||
funWangEditor: 'wangEditor 编辑器',
|
funWangEditor: 'wangEditor 编辑器',
|
||||||
funCropper: 'cropper 图片裁剪',
|
funCropper: 'cropper 图片裁剪',
|
||||||
funQrcode: 'qrcode 二维码生成',
|
funQrcode: 'qrcode 二维码生成',
|
||||||
|
@ -24,6 +24,7 @@ export default {
|
|||||||
funCountup: 'countup 數位滾動',
|
funCountup: 'countup 數位滾動',
|
||||||
funEchartsTree: 'echartsTree 樹圖',
|
funEchartsTree: 'echartsTree 樹圖',
|
||||||
funSelector: '圖標選擇器',
|
funSelector: '圖標選擇器',
|
||||||
|
funNoticeBar: '滾動通知欄',
|
||||||
funWangEditor: 'wangEditor 編輯器',
|
funWangEditor: 'wangEditor 編輯器',
|
||||||
funCropper: 'cropper 圖片裁剪',
|
funCropper: 'cropper 圖片裁剪',
|
||||||
funQrcode: 'qrcode 二維碼生成',
|
funQrcode: 'qrcode 二維碼生成',
|
||||||
|
@ -392,6 +392,21 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
|
|||||||
icon: 'iconfont icon-xuanzeqi',
|
icon: 'iconfont icon-xuanzeqi',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/fun/noticeBar',
|
||||||
|
name: 'funNoticeBar',
|
||||||
|
component: () => import('/@/views/fun/noticeBar/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: 'message.router.funNoticeBar',
|
||||||
|
isLink: '',
|
||||||
|
isHide: false,
|
||||||
|
isKeepAlive: true,
|
||||||
|
isAffix: false,
|
||||||
|
isIframe: false,
|
||||||
|
auth: ['admin', 'test'],
|
||||||
|
icon: 'el-icon-bell',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/fun/wangEditor',
|
path: '/fun/wangEditor',
|
||||||
name: 'funWangEditor',
|
name: 'funWangEditor',
|
||||||
|
161
src/views/fun/noticeBar/index.vue
Normal file
161
src/views/fun/noticeBar/index.vue
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<template>
|
||||||
|
<div class="notice-bar-container">
|
||||||
|
<el-card shadow="hover" header="滚动通知栏:默认">
|
||||||
|
<NoticeBar
|
||||||
|
text="🎉🎉🔥基于vue3.x 、Typescript、vite、Element plus等,适配手机、平板、pc
|
||||||
|
的后台开源免费模板库(vue2.x请切换vue-prev-admin分支),仓库地址:https://gitee.com/lyt-top/vue-next-admin"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="hover" header="滚动通知栏:设置样式" class="mt15">
|
||||||
|
<NoticeBar
|
||||||
|
text="🎉🎉🔥基于vue3.x 、Typescript、vite、Element plus等,适配手机、平板、pc
|
||||||
|
的后台开源免费模板库(vue2.x请切换vue-prev-admin分支),仓库地址:https://gitee.com/lyt-top/vue-next-admin"
|
||||||
|
leftIcon="el-icon-bell"
|
||||||
|
background="#ecf5ff"
|
||||||
|
color="#409eff"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="hover" header="滚动通知栏:搭配 NoticeBar 和 Carousel 走马灯 组件可以实现垂直滚动的效果" class="mt15">
|
||||||
|
<NoticeBar :scrollable="true">
|
||||||
|
<el-carousel height="40px" direction="vertical" :autoplay="true" indicator-position="none" :interval="3000">
|
||||||
|
<el-carousel-item v-for="v in noticeList" :key="v">{{ v }} </el-carousel-item>
|
||||||
|
</el-carousel>
|
||||||
|
</NoticeBar>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="hover" header="滚动通知栏:参数" class="mt15">
|
||||||
|
<el-table :data="tableData" style="width: 100%">
|
||||||
|
<el-table-column prop="a1" label="参数"> </el-table-column>
|
||||||
|
<el-table-column prop="a2" label="说明"> </el-table-column>
|
||||||
|
<el-table-column prop="a3" label="类型"> </el-table-column>
|
||||||
|
<el-table-column prop="a4" label="可选值"> </el-table-column>
|
||||||
|
<el-table-column prop="a5" label="默认值"> </el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="hover" header="图标选择器(宽度自动):事件" class="mt15">
|
||||||
|
<el-table :data="tableData1" style="width: 100%">
|
||||||
|
<el-table-column prop="a1" label="事件名称"> </el-table-column>
|
||||||
|
<el-table-column prop="a2" label="说明"> </el-table-column>
|
||||||
|
<el-table-column prop="a3" label="类型"> </el-table-column>
|
||||||
|
<el-table-column prop="a4" label="回调参数"> </el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { toRefs, reactive, defineComponent } from 'vue';
|
||||||
|
import NoticeBar from '/@/components/noticeBar/index.vue';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'funNoticeBar',
|
||||||
|
components: { NoticeBar },
|
||||||
|
setup() {
|
||||||
|
const state = reactive({
|
||||||
|
noticeList: [
|
||||||
|
'🎉🎉🔥基于vue3.x 、Typescript、vite、Element plus等,适配手机、平板、pc的后台开源免费模板库(vue2.x请切换vue-prev-admin分支)',
|
||||||
|
'仓库地址:https://gitee.com/lyt-top/vue-next-admin',
|
||||||
|
'演示地址:vue3.x 版本预览(vue-next-admin)https://lyt-top.gitee.io/vue-next-admin-preview/#/login',
|
||||||
|
],
|
||||||
|
tableData: [
|
||||||
|
{
|
||||||
|
a1: 'mode',
|
||||||
|
a2: '通知栏模式,用于右侧 icon 图标点击',
|
||||||
|
a3: 'string',
|
||||||
|
a4: 'closeable / link',
|
||||||
|
a5: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'text',
|
||||||
|
a2: '通知文本内容,scrollable 为 false 时生效',
|
||||||
|
a3: 'string',
|
||||||
|
a4: '',
|
||||||
|
a5: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'color',
|
||||||
|
a2: '通知文本颜色',
|
||||||
|
a3: 'string',
|
||||||
|
a4: '',
|
||||||
|
a5: '#e6a23c',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'background',
|
||||||
|
a2: '通知背景色',
|
||||||
|
a3: 'string',
|
||||||
|
a4: '',
|
||||||
|
a5: '#fdf6ec',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'size',
|
||||||
|
a2: '字体大小,单位px',
|
||||||
|
a3: 'number / string',
|
||||||
|
a4: '',
|
||||||
|
a5: '14',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'height',
|
||||||
|
a2: '通知栏高度,单位px',
|
||||||
|
a3: 'number / string',
|
||||||
|
a4: '',
|
||||||
|
a5: '40',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'delay',
|
||||||
|
a2: '动画延迟时间 (s)',
|
||||||
|
a3: 'number / string',
|
||||||
|
a4: '',
|
||||||
|
a5: '1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'speed',
|
||||||
|
a2: '滚动速率 (px/s)',
|
||||||
|
a3: 'number / string',
|
||||||
|
a4: '',
|
||||||
|
a5: '100',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'scrollable',
|
||||||
|
a2: '是否开启垂直滚动',
|
||||||
|
a3: 'boolean',
|
||||||
|
a4: '',
|
||||||
|
a5: 'false',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'leftIcon',
|
||||||
|
a2: '自定义左侧图标',
|
||||||
|
a3: 'string',
|
||||||
|
a4: '',
|
||||||
|
a5: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'rightIcon',
|
||||||
|
a2: '自定义右侧图标',
|
||||||
|
a3: 'string',
|
||||||
|
a4: '',
|
||||||
|
a5: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableData1: [
|
||||||
|
{
|
||||||
|
a1: 'close',
|
||||||
|
a2: '通知栏模式(mode)closeable 时回调事件',
|
||||||
|
a3: 'function',
|
||||||
|
a4: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a1: 'link',
|
||||||
|
a2: '通知栏模式(mode)link 时回调事件',
|
||||||
|
a3: 'function',
|
||||||
|
a4: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...toRefs(state),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user