Skip to content

Commit

Permalink
update: 优化样式表,新增nAvatar组件单元测试文件
Browse files Browse the repository at this point in the history
  • Loading branch information
ljnMeow committed Aug 25, 2023
1 parent 697d0e3 commit cc0726c
Show file tree
Hide file tree
Showing 24 changed files with 893 additions and 169 deletions.
8 changes: 8 additions & 0 deletions packages/nice2cu-ui-mobile-example/src/router/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,12 @@ export default [
title: '文本省略',
},
},
{
path: '/avatar',
name: 'Avatar',
component: () => import(/* webpackChunkName: "Avatar" */ '@views/componentsViews/Avatar.vue'),
meta: {
title: '头像',
},
},
];
1 change: 1 addition & 0 deletions packages/nice2cu-ui-mobile-example/src/views/HomeIndex.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
<n-cell title="Tab 标签页" link="tabs"></n-cell>
<n-cell title="Swipe 轮播" link="swiper"></n-cell>
<n-cell title="Ellipsis 文本省略" link="ellipsis"></n-cell>
<n-cell title="Avatar 头像" link="avatar"></n-cell>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<template>
<div class="container">
<n-nav-bar title="Avatar 头像" show-left left-text="" :shadow-buttom="true" fixed-top safe-area-inset-top placeholder></n-nav-bar>

<section>
<div class="title">基础用法</div>
<div class="content unflex">
<n-space align="center">
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
</n-space>
</div>
</section>
<section>
<div class="title">尺寸(size)</div>
<div class="content unflex">
<n-space align="center">
<n-avatar size="mini" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
<n-avatar size="small" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
<n-avatar size="large" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
<n-avatar size="80" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
</n-space>
</div>
</section>
<section>
<div class="title">形状(round)</div>
<div class="content unflex">
<n-space align="center">
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
<n-avatar :round="false" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
</n-space>
</div>
</section>
<section>
<div class="title">边框/边框颜色(bordered / borderColor)</div>
<div class="content unflex">
<n-space align="center">
<n-avatar bordered src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
<n-avatar bordered border-color="rgb(33, 150, 243)" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
</n-space>
</div>
</section>
<section>
<div class="title">填充模式(fit)</div>
<div class="content unflex">
<n-space align="center">
<n-space direction="column" align="center">
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp" fit="fill"></n-avatar>
<span>fill</span>
</n-space>
<n-space direction="column" align="center">
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp" fit="contain"></n-avatar>
<span>contain</span>
</n-space>
<n-space direction="column" align="center">
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp" fit="cover"></n-avatar>
<span>cover</span>
</n-space>
<n-space direction="column" align="center">
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp" fit="none"></n-avatar>
<span>none</span>
</n-space>
<n-space direction="column" align="center">
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp" fit="scale-down"></n-avatar>
<span>scale-down</span>
</n-space>
</n-space>
</div>
</section>
<section>
<div class="title">文字模式 / 背景颜色(color)</div>
<div class="content unflex">
<n-space align="center">
<n-avatar color="#e3b4b8">NICE2CU</n-avatar>
<n-avatar color="#c08eaf">卡利斯</n-avatar>
</n-space>
</div>
</section>
<section>
<div class="title">头像分组</div>
<div class="content unflex">
<n-avatar-group>
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
<n-avatar color="#c08eaf">卡利斯</n-avatar>
<n-avatar color="#e3b4b8">NICE2CU</n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadc016afb6.jpg"></n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbffd9ea0.jpg"></n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbff3d163.jpg"></n-avatar>
</n-avatar-group>
</div>
</section>
<section>
<div class="title">最大展示(maxLength)</div>
<div class="content unflex">
<n-avatar-group :max-length="5">
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
<n-avatar color="#c08eaf">卡利斯</n-avatar>
<n-avatar color="#e3b4b8">NICE2CU</n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadc016afb6.jpg"></n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbffd9ea0.jpg"></n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbff3d163.jpg"></n-avatar>
</n-avatar-group>
</div>
</section>
<section>
<div class="title">纵向展示(vertical)</div>
<div class="content unflex">
<n-avatar-group vertical>
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
<n-avatar color="#c08eaf">卡利斯</n-avatar>
<n-avatar color="#e3b4b8">NICE2CU</n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadc016afb6.jpg"></n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbffd9ea0.jpg"></n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbff3d163.jpg"></n-avatar>
</n-avatar-group>
</div>
</section>
<section>
<div class="title">间距(offset)</div>
<div class="content unflex">
<n-avatar-group offset="10">
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar>
<n-avatar color="#c08eaf">卡利斯</n-avatar>
<n-avatar color="#e3b4b8">NICE2CU</n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadc016afb6.jpg"></n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbffd9ea0.jpg"></n-avatar>
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbff3d163.jpg"></n-avatar>
</n-avatar-group>
</div>
</section>
</div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const text = ref('卡利斯');
const clickfun = () => {
text.value = '卡利斯斯特林';
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
</div>
</section>
<section>
<div class="title">原点(dot)</div>
<div class="title">圆点(dot)</div>
<div class="content">
<div class="item">
<n-badge dot />
Expand Down
2 changes: 2 additions & 0 deletions packages/nice2cu-ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ export * from './nTabItem';
export * from './nSwiper';
export * from './nSwiperItem';
export * from './nEllipsis';
export * from './nAvatar';
export * from './nAvatarGroup';
123 changes: 123 additions & 0 deletions packages/nice2cu-ui/src/nAvatar/Avatar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<template>
<div
ref="avatarEle"
:class="[bem.b(), innerSize(size) ? bem.m(size as string) : '', round ? bem.m('round') : '', bordered ? bem.m('bordered') : '']"
:style="{
width: !innerSize(size) ? handleUnit(size) : undefined,
height: !innerSize(size) ? handleUnit(size) : undefined,
borderColor,
backgroundColor: color,
}"
@click="onClick"
>
<template v-if="src">
<img
v-if="lazy"
v-lazy="{ src: src, loading: loading, error: error, onLoadImg: handleImgLoad, onErrorImg: handleImgError }"
:class="bem.e('image')"
:alt="alt"
:style="{ objectFit: fit }"
/>
<img v-else :class="bem.e('image')" :src="imgSrc" :alt="alt" :style="{ objectFit: fit }" />
</template>

<div v-else ref="textEle" :class="bem.e('text')" :style="{ transform: `scale(${scale})` }">
<slot />
</div>
</div>
</template>

<script lang="ts">
import { defineComponent, nextTick, onActivated, onMounted, onUpdated, ref } from 'vue';
import { createNamespace } from '../../utils/create';
import { handleUnit } from '../../utils/tools';
import Lazy from '../../directives/lazy';
import { LazyEventOptions } from '../../directives/lazy';
import { defaultLoadingImg, defaultLoadingError } from '../../directives/lazy/defaultImg';
import { AvatarProps, AvatarPropsType, innerSize } from './AvatarProps';
import './style/avatar.less';
export default defineComponent({
name: 'NAvatar',
directives: { Lazy },
props: AvatarProps,
setup(props: AvatarPropsType) {
const bem = createNamespace('avatar');
const avatarEle = ref<HTMLElement | null>();
const textEle = ref<HTMLElement | null>();
const imgSrc = ref(props.loading ?? defaultLoadingImg);
const scale = ref<number>(1);
let isMounted = false;
const getScale = () => {
if (!avatarEle.value || !textEle.value) {
scale.value = 1;
return;
}
const avatarEleWidth = avatarEle.value.offsetWidth;
const textEleWidth = textEle.value.offsetWidth;
if (avatarEleWidth > textEleWidth) {
scale.value = 1;
} else {
scale.value = avatarEleWidth / textEleWidth;
}
};
const handleImgLoad = (e: Event) => {
const { onLoad } = props;
if ((e as unknown as LazyEventOptions).status === 'success' && onLoad) {
onLoad(e);
}
};
const handleImgError = (e: Event) => {
const { onError } = props;
if ((e as unknown as LazyEventOptions).status === 'error' && onError) {
onError(e);
}
};
const imageLoad = () => {
const { lazy, src, error, onLoad, onError } = props;
if (!lazy) {
let image = new Image();
image.src = src as string;
image.onerror = (e: Event | string) => {
imgSrc.value = error ?? defaultLoadingError;
if (onError) onError(e as Event);
};
image.onload = (e: Event | string) => {
imgSrc.value = src as string;
if (onLoad) onLoad(e as Event);
};
}
};
if (!props.lazy && props.src) {
imageLoad();
}
onMounted(() => {
nextTick(() => {
isMounted = true;
getScale();
});
});
onActivated(() => {
if (!isMounted) return;
getScale();
});
onUpdated(() => {
getScale();
});
return { bem, avatarEle, textEle, imgSrc, innerSize, handleUnit, scale, handleImgLoad, handleImgError };
},
});
</script>
68 changes: 68 additions & 0 deletions packages/nice2cu-ui/src/nAvatar/AvatarProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { ExtractPropTypes, PropType } from 'vue';
import { isString, isNumber } from '../../utils/tools';

export const innerSize = (size: any): boolean => {
return ['mini', 'small', 'normal', 'large'].includes(size);
};

const sizeValidator = (size: any): boolean => {
return innerSize(size) || isString(size) || isNumber(size);
};

const fitValidator = (fit: string): boolean => {
return ['fill', 'contain', 'cover', 'none', 'scale-down'].includes(fit);
};

export const AvatarProps = {
round: {
type: Boolean,
default: true,
},
size: {
type: [String, Number] as PropType<'mini' | 'small' | 'normal' | 'large' | number | string>,
validator: sizeValidator,
default: 'normal',
},
alt: {
type: String,
},
color: {
type: String,
},
src: {
type: String,
},
fit: {
type: String as PropType<'fill' | 'contain' | 'cover' | 'none' | 'scale-down'>,
validator: fitValidator,
default: 'cover',
},
bordered: {
type: Boolean,
default: false,
},
borderColor: {
type: String,
},
loading: {
type: String,
},
error: {
type: String,
},
lazy: {
type: Boolean,
default: false,
},
onLoad: {
type: Function as PropType<(e: Event) => void | Promise<any>>,
},
onError: {
type: Function as PropType<(e: Event) => void | Promise<any>>,
},
onClick: {
type: Function as PropType<(e: Event) => void | Promise<any>>,
},
};

export type AvatarPropsType = ExtractPropTypes<typeof AvatarProps>;
Loading

0 comments on commit cc0726c

Please sign in to comment.