SystemAvatar.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <template>
  2. <view class="system-avatar" :style="wrapStyle">
  3. <view class="system-avatar-placeholder" :class="'gradient-' + gradientIndex" :style="placeholderStyle">
  4. <image
  5. class="system-avatar-icon"
  6. src="/static/icons/application.svg"
  7. mode="contain"
  8. :style="iconStyle"
  9. />
  10. </view>
  11. </view>
  12. </template>
  13. <script setup>
  14. import { computed } from 'vue'
  15. /** 渐变色库 [左上深, 右下浅],135deg,共 20 组,与 UserAvatar 保持一致 */
  16. const AVATAR_GRADIENT_PAIRS = [
  17. ['#1e3a8a', '#93c5fd'], ['#166534', '#86efac'], ['#c2410c', '#fdba74'], ['#b91c1c', '#fca5a5'], ['#5b21b6', '#c4b5fd'],
  18. ['#0f766e', '#5eead4'], ['#3730a3', '#a5b4fc'], ['#0d9488', '#2dd4bf'], ['#b45309', '#fcd34d'], ['#be123c', '#fda4af'],
  19. ['#0369a1', '#7dd3fc'], ['#4d7c0f', '#bef264'], ['#86198f', '#e879f9'], ['#475569', '#cbd5e1'], ['#047857', '#6ee7b7'],
  20. ['#6d28d9', '#ddd6fe'], ['#1e40af', '#93c5fd'], ['#ea580c', '#fed7aa'], ['#0e7490', '#99f6e4'], ['#881337', '#fbcfe8'],
  21. ]
  22. /** 仅使用 name 进行哈希,确保同一应用/平台通知保持稳定颜色 */
  23. function getGradientIndexByName(name) {
  24. const s = String(name || '').trim() || 'SYSTEM'
  25. let hash = 0
  26. for (let i = 0; i < s.length; i++) {
  27. hash = ((hash << 5) - hash + s.charCodeAt(i)) | 0
  28. }
  29. return Math.abs(hash) % AVATAR_GRADIENT_PAIRS.length
  30. }
  31. const props = defineProps({
  32. /** 名称/标识,用于确定渐变颜色 */
  33. name: { type: String, default: '' },
  34. /** 尺寸数值,默认 48 */
  35. size: { type: Number, default: 48 },
  36. /** 尺寸单位:'px' | 'rpx',默认 px */
  37. unit: { type: String, default: 'px' },
  38. })
  39. const su = computed(() => props.unit || 'px')
  40. const gradientIndex = computed(() => getGradientIndexByName(props.name))
  41. const wrapStyle = computed(() => {
  42. const u = su.value
  43. const w = props.size + u
  44. return {
  45. width: w,
  46. height: w,
  47. borderRadius: '50%',
  48. overflow: 'hidden',
  49. }
  50. })
  51. const placeholderStyle = computed(() => {
  52. const u = su.value
  53. const w = props.size + u
  54. return {
  55. width: w,
  56. height: w,
  57. borderRadius: '50%',
  58. }
  59. })
  60. const iconStyle = computed(() => {
  61. const u = su.value
  62. const w = (props.size * 0.6) + u
  63. return {
  64. width: w,
  65. height: w,
  66. }
  67. })
  68. </script>
  69. <style scoped>
  70. .system-avatar {
  71. flex-shrink: 0;
  72. }
  73. .system-avatar-placeholder {
  74. display: flex;
  75. align-items: center;
  76. justify-content: center;
  77. }
  78. .system-avatar-icon {
  79. display: block;
  80. /* 如果原图是深色,可通过滤镜统一成白色图标 */
  81. filter: brightness(0) invert(1);
  82. }
  83. </style>
  84. <style>
  85. /* 与 UserAvatar 渐变逻辑保持一致,使用不同前缀避免样式冲突 */
  86. .system-avatar .system-avatar-placeholder.gradient-0 { background-color: #1e3a8a; background-image: linear-gradient(135deg, #1e3a8a, #93c5fd); }
  87. .system-avatar .system-avatar-placeholder.gradient-1 { background-color: #166534; background-image: linear-gradient(135deg, #166534, #86efac); }
  88. .system-avatar .system-avatar-placeholder.gradient-2 { background-color: #c2410c; background-image: linear-gradient(135deg, #c2410c, #fdba74); }
  89. .system-avatar .system-avatar-placeholder.gradient-3 { background-color: #b91c1c; background-image: linear-gradient(135deg, #b91c1c, #fca5a5); }
  90. .system-avatar .system-avatar-placeholder.gradient-4 { background-color: #5b21b6; background-image: linear-gradient(135deg, #5b21b6, #c4b5fd); }
  91. .system-avatar .system-avatar-placeholder.gradient-5 { background-color: #0f766e; background-image: linear-gradient(135deg, #0f766e, #5eead4); }
  92. .system-avatar .system-avatar-placeholder.gradient-6 { background-color: #3730a3; background-image: linear-gradient(135deg, #3730a3, #a5b4fc); }
  93. .system-avatar .system-avatar-placeholder.gradient-7 { background-color: #0d9488; background-image: linear-gradient(135deg, #0d9488, #2dd4bf); }
  94. .system-avatar .system-avatar-placeholder.gradient-8 { background-color: #b45309; background-image: linear-gradient(135deg, #b45309, #fcd34d); }
  95. .system-avatar .system-avatar-placeholder.gradient-9 { background-color: #be123c; background-image: linear-gradient(135deg, #be123c, #fda4af); }
  96. .system-avatar .system-avatar-placeholder.gradient-10 { background-color: #0369a1; background-image: linear-gradient(135deg, #0369a1, #7dd3fc); }
  97. .system-avatar .system-avatar-placeholder.gradient-11 { background-color: #4d7c0f; background-image: linear-gradient(135deg, #4d7c0f, #bef264); }
  98. .system-avatar .system-avatar-placeholder.gradient-12 { background-color: #86198f; background-image: linear-gradient(135deg, #86198f, #e879f9); }
  99. .system-avatar .system-avatar-placeholder.gradient-13 { background-color: #475569; background-image: linear-gradient(135deg, #475569, #cbd5e1); }
  100. .system-avatar .system-avatar-placeholder.gradient-14 { background-color: #047857; background-image: linear-gradient(135deg, #047857, #6ee7b7); }
  101. .system-avatar .system-avatar-placeholder.gradient-15 { background-color: #6d28d9; background-image: linear-gradient(135deg, #6d28d9, #ddd6fe); }
  102. .system-avatar .system-avatar-placeholder.gradient-16 { background-color: #1e40af; background-image: linear-gradient(135deg, #1e40af, #93c5fd); }
  103. .system-avatar .system-avatar-placeholder.gradient-17 { background-color: #ea580c; background-image: linear-gradient(135deg, #ea580c, #fed7aa); }
  104. .system-avatar .system-avatar-placeholder.gradient-18 { background-color: #0e7490; background-image: linear-gradient(135deg, #0e7490, #99f6e4); }
  105. .system-avatar .system-avatar-placeholder.gradient-19 { background-color: #881337; background-image: linear-gradient(135deg, #881337, #fbcfe8); }
  106. </style>