'admin-21.07.01:新增滚动通知栏/公告组件及演示界面'

This commit is contained in:
lyt-Top 2021-07-01 22:33:57 +08:00
parent b2fd7d6010
commit 382454ca0e
7 changed files with 371 additions and 1 deletions

View File

@ -45,7 +45,7 @@
"prettier": "^2.3.2",
"sass": "^1.35.1",
"sass-loader": "^12.1.0",
"typescript": "^4.3.4",
"typescript": "^4.3.5",
"vite": "^2.3.8",
"vue-eslint-parser": "^7.6.0"
},

View 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>

View File

@ -24,6 +24,7 @@ export default {
funCountup: 'countup',
funEchartsTree: 'echartsTree',
funSelector: 'funSelector',
funNoticeBar: 'ScrollingNoticeBar',
funWangEditor: 'wangEditor',
funCropper: 'cropper',
funQrcode: 'qrcode',

View File

@ -24,6 +24,7 @@ export default {
funCountup: 'countup 数字滚动',
funEchartsTree: 'echartsTree 树图',
funSelector: '图标选择器',
funNoticeBar: '滚动通知栏',
funWangEditor: 'wangEditor 编辑器',
funCropper: 'cropper 图片裁剪',
funQrcode: 'qrcode 二维码生成',

View File

@ -24,6 +24,7 @@ export default {
funCountup: 'countup 數位滾動',
funEchartsTree: 'echartsTree 樹圖',
funSelector: '圖標選擇器',
funNoticeBar: '滾動通知欄',
funWangEditor: 'wangEditor 編輯器',
funCropper: 'cropper 圖片裁剪',
funQrcode: 'qrcode 二維碼生成',

View File

@ -392,6 +392,21 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
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',
name: 'funWangEditor',

View File

@ -0,0 +1,161 @@
<template>
<div class="notice-bar-container">
<el-card shadow="hover" header="滚动通知栏:默认">
<NoticeBar
text="🎉🎉🔥基于vue3.x TypescriptviteElement 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 TypescriptviteElement 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-adminhttps://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: '通知栏模式modecloseable 时回调事件',
a3: 'function',
a4: '',
},
{
a1: 'link',
a2: '通知栏模式modelink 时回调事件',
a3: 'function',
a4: '',
},
],
});
return {
...toRefs(state),
};
},
});
</script>