head-image.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <template>
  2. <view class="head-image none-pointer-events" @click="showUserInfo($event)" :title="name">
  3. <image class="avatar-image" v-if="url" :src="url" :style="avatarImageStyle" lazy-load="true"
  4. mode="aspectFill" />
  5. <view class="avatar-text" v-if="!url" :style="avatarTextStyle">
  6. {{ name?.substring(0, 1).toUpperCase() }}
  7. </view>
  8. <view v-if="online" class="online" title="用户当前在线">
  9. </view>
  10. </view>
  11. </template>
  12. <script>
  13. export default {
  14. name: "head-image",
  15. data() {
  16. return {
  17. colors: ["#5daa31", "#c7515a", "#e03697", "#85029b",
  18. "#c9b455", "#326eb6"
  19. ]
  20. }
  21. },
  22. props: {
  23. id: {
  24. type: Number
  25. },
  26. size: {
  27. type: [Number, String],
  28. default: 'default'
  29. },
  30. url: {
  31. type: String
  32. },
  33. name: {
  34. type: String,
  35. default: null
  36. },
  37. radius: {
  38. type: String,
  39. default: "50%"
  40. },
  41. online: {
  42. type: Boolean,
  43. default: false
  44. },
  45. },
  46. methods: {
  47. showUserInfo(e) {
  48. if (this.id && this.id > 0) {
  49. uni.navigateTo({
  50. url: "/pages/common/user-info?id=" + this.id
  51. })
  52. }
  53. }
  54. },
  55. computed: {
  56. _size() {
  57. if (typeof this.size === 'number') {
  58. return this.size;
  59. } else if (typeof this.size === 'string') {
  60. return {
  61. 'default': 96,
  62. 'small': 84,
  63. 'smaller': 72,
  64. 'mini': 60,
  65. 'minier': 48,
  66. 'lage': 108,
  67. 'lager': 120,
  68. } [this.size]
  69. }
  70. },
  71. avatarImageStyle() {
  72. return `width:${this._size}rpx;
  73. height:${this._size}rpx;`
  74. },
  75. avatarTextStyle() {
  76. return `width: ${this._size}rpx;
  77. height:${this._size}rpx;
  78. background: linear-gradient(145deg,#ffffff20 25%,#00000060),${this.textColor};
  79. font-size:${this._size * 0.45}rpx;
  80. border-radius: ${this.radius};
  81. `
  82. },
  83. textColor() {
  84. if (!this.name) {
  85. return '#fff';
  86. }
  87. let hash = 0;
  88. for (var i = 0; i < this.name.length; i++) {
  89. hash += this.name.charCodeAt(i);
  90. }
  91. return this.colors[hash % this.colors.length];
  92. }
  93. }
  94. }
  95. </script>
  96. <style scoped lang="scss">
  97. .head-image {
  98. position: relative;
  99. cursor: pointer;
  100. .avatar-image {
  101. position: relative;
  102. overflow: hidden;
  103. border-radius: 50%;
  104. vertical-align: bottom;
  105. }
  106. .avatar-text {
  107. color: white;
  108. border-radius: 50%;
  109. display: flex;
  110. align-items: center;
  111. justify-content: center;
  112. }
  113. .online {
  114. position: absolute;
  115. right: -10%;
  116. bottom: 0;
  117. width: 24rpx;
  118. height: 24rpx;
  119. background: limegreen;
  120. border-radius: 50%;
  121. border: 6rpx solid white;
  122. }
  123. }
  124. </style>