index.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <template>
  2. <view
  3. :style="!showMax ? styles : maxStyles"
  4. :class="classes"
  5. @click="activeAvatar(e)"
  6. ref="avatarRef"
  7. v-if="showMax || !avatarGroup?.props?.maxCount || index <= avatarGroup?.props?.maxCount"
  8. >
  9. <template v-if="!avatarGroup?.props?.maxCount || index <= avatarGroup?.props?.maxCount">
  10. <template v-if="url">
  11. <img :src="url" :alt="alt" @error="onError" />
  12. </template>
  13. <template v-else-if="icon">
  14. <nut-icon class="icon" :name="iconStyles"></nut-icon>
  15. </template>
  16. <view class="text" v-if="isShowText">
  17. <slot></slot>
  18. </view>
  19. </template>
  20. <!-- 折叠头像 -->
  21. <template v-if="showMax">
  22. <view class="text">
  23. {{
  24. avatarGroup?.props?.maxContent
  25. ? avatarGroup?.props?.maxContent
  26. : `+ ${maxIndex - avatarGroup?.props?.maxCount}`
  27. }}
  28. </view>
  29. </template>
  30. </view>
  31. </template>
  32. <script lang="ts">
  33. import { toRefs, onMounted, computed, inject, reactive, ref } from 'vue';
  34. import { createComponent } from '@/packages/utils/create';
  35. const { componentName, create } = createComponent('avatar');
  36. export default create({
  37. props: {
  38. size: {
  39. type: String,
  40. default: ''
  41. },
  42. shape: {
  43. type: String,
  44. default: 'round'
  45. },
  46. bgColor: {
  47. type: String,
  48. default: '#eee'
  49. },
  50. color: {
  51. type: String,
  52. default: '#666'
  53. },
  54. url: {
  55. type: String,
  56. default: ''
  57. },
  58. alt: {
  59. type: String,
  60. default: ''
  61. },
  62. icon: {
  63. type: String,
  64. default: ''
  65. }
  66. },
  67. emits: ['active-avatar', 'onError'],
  68. setup(props, { emit, slots }) {
  69. const { size, shape, bgColor, color, icon } = toRefs(props);
  70. const sizeValue = ['large', 'normal', 'small'];
  71. const avatarGroup: any = inject('avatarGroup', null);
  72. const avatarRef = ref(null);
  73. const visible = reactive({
  74. lightTheme: false
  75. });
  76. const state = reactive({
  77. index: 1,
  78. showMax: false, // 是否显示的最大头像个数
  79. maxIndex: 0 // avatarGroup里的avatar的个数
  80. });
  81. onMounted(() => {
  82. const children = avatarGroup?.avatarGroupRef?.value?.children;
  83. if (children) {
  84. // console.log('children', children);
  85. avatarLength(children);
  86. }
  87. });
  88. const classes = computed(() => {
  89. const prefixCls = componentName;
  90. return {
  91. [prefixCls]: true,
  92. [`nut-avatar-${size.value || avatarGroup?.props?.size || 'normal'}`]: true,
  93. [`nut-avatar-${shape.value || avatarGroup?.props?.shape || 'normal'}`]: true
  94. };
  95. });
  96. const styles = computed(() => {
  97. return {
  98. width: sizeValue.indexOf(size.value) > -1 ? '' : `${size.value}px`,
  99. height: sizeValue.indexOf(size.value) > -1 ? '' : `${size.value}px`,
  100. backgroundColor: `${bgColor.value}`,
  101. color: `${color.value}`,
  102. marginLeft: state.index != 1 && (avatarGroup?.props?.span ? `${avatarGroup?.props?.span}px` : ''),
  103. zIndex: avatarGroup?.props?.zIndex == 'right' ? `${Math.abs(state.maxIndex - state.index)}` : ''
  104. };
  105. });
  106. const maxStyles = computed(() => {
  107. return {
  108. backgroundColor: `${avatarGroup?.props?.maxBgColor}`,
  109. color: `${avatarGroup?.props?.maxColor}`
  110. };
  111. });
  112. const iconStyles = computed(() => {
  113. return !!icon.value ? icon.value : '';
  114. });
  115. const isShowText = computed(() => {
  116. return slots.default;
  117. });
  118. const avatarLength = (children: any) => {
  119. state.maxIndex = children.length;
  120. for (let i = 0; i < children.length; i++) {
  121. if (children[i] && children[i].classList && children[i].classList[0] == 'nut-avatar') {
  122. children[i].setAttribute('data-index', i + 1);
  123. }
  124. // console.log('console', i, children[i]);
  125. }
  126. state.index = avatarRef?.value?.dataset?.index;
  127. if (state.index == state.maxIndex && state.index != avatarGroup?.props?.maxCount) {
  128. state.showMax = true;
  129. }
  130. };
  131. const activeAvatar = (event: any) => {
  132. emit('active-avatar', event);
  133. };
  134. const onError = (event: any) => {
  135. emit('onError', event);
  136. };
  137. return {
  138. classes,
  139. styles,
  140. iconStyles,
  141. isShowText,
  142. maxStyles,
  143. activeAvatar,
  144. onError,
  145. avatarGroup,
  146. visible,
  147. avatarRef,
  148. ...toRefs(state)
  149. };
  150. }
  151. });
  152. </script>