parent
e57344a4ff
commit
27e9234203
@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<span :class="badgeComputedCls.badgeCls">
|
||||
<template v-if="isStatusBadge">
|
||||
<span :class="badgeComputedCls.statusCls"></span>
|
||||
<span :class="[prefixCls+'-status-text']">{{text}}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<slot></slot>
|
||||
<scroll-number
|
||||
v-if="!badgeStatus.isHidden"
|
||||
:prefixCls="scrollNumberPrefixCls"
|
||||
:className="badgeComputedCls.scrollNumberCls"
|
||||
:count="badgeStatus.stateCount"
|
||||
:titleNumber="count"
|
||||
:styleNumber="styles"
|
||||
>
|
||||
</scroll-number>
|
||||
<span
|
||||
v-if="!badgeStatus.isHidden && text"
|
||||
:class="[prefixCls+'-status-text']">
|
||||
{{text}}
|
||||
</span>
|
||||
</template>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../icon'
|
||||
import ScrollNumber from './ScrollNumber'
|
||||
|
||||
export default {
|
||||
name: 'Badge',
|
||||
props: {
|
||||
prefixCls: {
|
||||
type: String,
|
||||
default: 'ant-badge',
|
||||
},
|
||||
scrollNumberPrefixCls: {
|
||||
type: String,
|
||||
default: 'ant-scroll-number',
|
||||
},
|
||||
count: {
|
||||
type: [Number, String],
|
||||
},
|
||||
overflowCount: {
|
||||
type: [Number, String],
|
||||
default: 99,
|
||||
},
|
||||
showZero: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
dot: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
status: {
|
||||
validator: (val) => {
|
||||
if (!val) return true
|
||||
return ['success', 'processing', 'default', 'error', 'warning'].includes(val)
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isHasDefaultSlot: this.$slots && !!this.$slots.default,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isStatusBadge () {
|
||||
const { isHasDefaultSlot, status } = this
|
||||
return !isHasDefaultSlot && status
|
||||
},
|
||||
badgeComputedCls () {
|
||||
const { prefixCls, isHasDefaultSlot, status, dot } = this
|
||||
const isDot = dot || status
|
||||
return {
|
||||
badgeCls: {
|
||||
[`${prefixCls}`]: true,
|
||||
[`${prefixCls}-status`]: !!status,
|
||||
[`${prefixCls}-not-a-wrapper`]: !isHasDefaultSlot,
|
||||
},
|
||||
statusCls: {
|
||||
[`${prefixCls}-status-dot`]: !!status,
|
||||
[`${prefixCls}-status-${status}`]: !isHasDefaultSlot,
|
||||
},
|
||||
scrollNumberCls: {
|
||||
[`${prefixCls}-dot`]: isDot,
|
||||
[`${prefixCls}-count`]: !isDot,
|
||||
},
|
||||
}
|
||||
},
|
||||
badgeStatus () {
|
||||
const { count, overflowCount, showZero, dot, text, status } = this
|
||||
let stateCount = +count > +overflowCount ? `${overflowCount}+` : count
|
||||
const isDot = dot || text
|
||||
if (isDot) {
|
||||
stateCount = ''
|
||||
}
|
||||
const isZero = stateCount === '0' || stateCount === 0
|
||||
const isEmpty = stateCount === null || stateCount === undefined || stateCount === ''
|
||||
const isHidden = (isEmpty || (isZero && !showZero)) && !isDot
|
||||
return {
|
||||
stateCount,
|
||||
isHidden,
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
components: {
|
||||
Icon,
|
||||
ScrollNumber,
|
||||
},
|
||||
}
|
||||
</script>
|
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<sup :class="[prefixCls, className]" :title="titleNumber" :style="styleNumber">
|
||||
<!-- <span v-if="!count || isNaN(count)">{{count}}</span> -->
|
||||
<span>{{count}}</span>
|
||||
</sup>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'ScrollNumber',
|
||||
props: {
|
||||
className: Object,
|
||||
prefixCls: String,
|
||||
count: [Number, String],
|
||||
titleNumber: [Number, String],
|
||||
styleNumber: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
components: {
|
||||
},
|
||||
}
|
||||
</script>
|
@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div>
|
||||
<div>
|
||||
<Badge status="success" />
|
||||
<Badge status="error" />
|
||||
<Badge status="default" />
|
||||
<Badge status="processing" />
|
||||
<Badge :status="currentStatus" />
|
||||
<ant-button @click="changeStatus">改processing</ant-button>
|
||||
<br />
|
||||
<Badge status="success" text="Success" />
|
||||
<br />
|
||||
<Badge status="error" text="Error" />
|
||||
<br />
|
||||
<Badge status="default" text="Default" />
|
||||
<br />
|
||||
<Badge status="processing" text="Processing" />
|
||||
<br />
|
||||
<Badge status="warning" text="Warning" />
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<Badge :count="count">
|
||||
<a href="#" class="head-example" />
|
||||
</Badge>
|
||||
<ant-button @click="changeValue(1)">增加</ant-button>
|
||||
<ant-button @click="changeValue(-1)">减少</ant-button>
|
||||
<br/>
|
||||
<Badge :dot="isShow">
|
||||
<a href="#" class="head-example" />
|
||||
</Badge>
|
||||
<ant-button @click="changeShow()">toggle</ant-button>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import '../style'
|
||||
import { Badge, Button } from 'antd/index'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
currentStatus: 'warning',
|
||||
count: 98,
|
||||
isShow: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeStatus () {
|
||||
this.currentStatus = 'processing'
|
||||
},
|
||||
changeValue (val) {
|
||||
this.count = this.count + val
|
||||
},
|
||||
changeShow () {
|
||||
this.isShow = !this.isShow
|
||||
},
|
||||
},
|
||||
components: {
|
||||
Badge,
|
||||
AntButton: Button,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.head-example {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 6px;
|
||||
background: #eee;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,3 @@
|
||||
import Badge from './Badge'
|
||||
|
||||
export default Badge
|
@ -0,0 +1,2 @@
|
||||
import '../../style/index.less'
|
||||
import './index.less'
|
@ -0,0 +1,160 @@
|
||||
@import "../../style/themes/default";
|
||||
|
||||
@badge-prefix-cls: ~"@{ant-prefix}-badge";
|
||||
@number-prefix-cls: ~"@{ant-prefix}-scroll-number";
|
||||
|
||||
.@{badge-prefix-cls} {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
vertical-align: middle;
|
||||
|
||||
&-count {
|
||||
position: absolute;
|
||||
transform: translateX(50%);
|
||||
top: -@badge-height / 2;
|
||||
right: 0;
|
||||
height: @badge-height;
|
||||
border-radius: @badge-height / 2;
|
||||
min-width: @badge-height;
|
||||
background: @highlight-color;
|
||||
color: #fff;
|
||||
line-height: @badge-height;
|
||||
text-align: center;
|
||||
padding: 0 6px;
|
||||
font-size: @badge-font-size;
|
||||
white-space: nowrap;
|
||||
transform-origin: -10% center;
|
||||
font-family: tahoma;
|
||||
a,
|
||||
a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&-dot {
|
||||
position: absolute;
|
||||
transform: translateX(50%);
|
||||
transform-origin: 0 center;
|
||||
top: -@badge-dot-size / 2;
|
||||
right: 0;
|
||||
height: @badge-dot-size;
|
||||
width: @badge-dot-size;
|
||||
border-radius: 100%;
|
||||
background: @highlight-color;
|
||||
z-index: 10;
|
||||
box-shadow: 0 0 0 1px #fff;
|
||||
}
|
||||
|
||||
&-status {
|
||||
line-height: inherit;
|
||||
vertical-align: baseline;
|
||||
|
||||
&-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
}
|
||||
&-success {
|
||||
background-color: @success-color;
|
||||
}
|
||||
&-processing {
|
||||
background-color: @primary-color;
|
||||
position: relative;
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
border: 1px solid @primary-color;
|
||||
content: '';
|
||||
animation: antStatusProcessing 1.2s infinite ease-in-out;
|
||||
}
|
||||
}
|
||||
&-default {
|
||||
background-color: @normal-color;
|
||||
}
|
||||
&-error {
|
||||
background-color: @error-color;
|
||||
}
|
||||
&-warning {
|
||||
background-color: @warning-color;
|
||||
}
|
||||
&-text {
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&-zoom-appear,
|
||||
&-zoom-enter {
|
||||
animation: antZoomBadgeIn .3s @ease-out-back;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
&-zoom-leave {
|
||||
animation: antZoomBadgeOut .3s @ease-in-back;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
&-not-a-wrapper &-count {
|
||||
top: auto;
|
||||
display: block;
|
||||
position: relative;
|
||||
transform: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antStatusProcessing {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: scale(2.4);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.@{number-prefix-cls} {
|
||||
overflow: hidden;
|
||||
&-only {
|
||||
display: inline-block;
|
||||
transition: all .3s @ease-in-out;
|
||||
height: @badge-height;
|
||||
> p {
|
||||
height: @badge-height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomBadgeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0) translateX(-50%);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1) translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomBadgeOut {
|
||||
0% {
|
||||
transform: scale(1) translateX(-50%);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(0) translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
transition: opacity 3s;
|
||||
}
|
||||
.fade-enter, .fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
Loading…
Reference in new issue