Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 

113 wiersze
4.8 KiB

  1. <template>
  2. <Teleport to="body">
  3. <Transition name="invite-modal">
  4. <div
  5. v-if="open"
  6. class="fixed inset-0 z-[1000] flex items-end justify-center bg-[var(--c-0b1a2b)]/45 p-0 backdrop-blur-sm sm:items-center sm:p-5"
  7. role="dialog"
  8. aria-modal="true"
  9. aria-labelledby="invite-share-title"
  10. @click.self="$emit('close')"
  11. >
  12. <div class="relative w-full rounded-t-3xl bg-[var(--c-ffffff)] px-5 pb-[calc(24px+env(safe-area-inset-bottom))] pt-5 shadow-2xl sm:max-w-md sm:rounded-3xl sm:p-6">
  13. <div class="flex items-start justify-between gap-4">
  14. <div>
  15. <h2 id="invite-share-title" class="text-lg font-extrabold text-[var(--c-172033)]">微信扫码接受邀请</h2>
  16. <p class="mt-1 text-xs leading-5 text-[var(--c-7b8797)]">好友使用微信扫描小程序码,即可进入邀请落地页。</p>
  17. </div>
  18. <button
  19. type="button"
  20. aria-label="关闭"
  21. class="flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-full bg-[var(--c-f3f6fa)] text-[var(--c-66758a)] transition-colors hover:bg-[var(--c-e8eef7)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--c-0b8cff)]"
  22. @click="$emit('close')"
  23. >
  24. <UIcon name="i-lucide-x" class="size-4.5" />
  25. </button>
  26. </div>
  27. <div class="mx-auto mt-5 flex aspect-square w-full max-w-[260px] items-center justify-center rounded-3xl border border-[var(--c-e8eef7)] bg-[var(--c-f8fbff)] p-4">
  28. <div v-if="loading" class="flex flex-col items-center gap-3 text-xs font-bold text-[var(--c-8a97a8)]" role="status">
  29. <span class="size-7 animate-spin rounded-full border-[3px] border-[var(--c-0b8cff)]/20 border-t-[var(--c-0b8cff)] motion-reduce:animate-none" />
  30. 正在生成小程序码
  31. </div>
  32. <img
  33. v-else-if="qrcodeUrl"
  34. :src="qrcodeUrl"
  35. alt="邀请好友微信小程序码"
  36. class="size-full rounded-2xl bg-[var(--c-ffffff)] object-contain"
  37. >
  38. <div v-else class="text-center">
  39. <UIcon name="i-lucide-qr-code" class="mx-auto size-9 text-[var(--c-a0aabb)]" />
  40. <p class="mt-2 text-xs text-[var(--c-8a97a8)]">小程序码生成失败,请稍后重试</p>
  41. </div>
  42. </div>
  43. <div class="mt-5 rounded-2xl bg-[var(--c-f6f9fd)] p-3">
  44. <div class="text-[11px] font-bold text-[var(--c-8a97a8)]">网页邀请链接</div>
  45. <div class="mt-1.5 truncate text-xs text-[var(--c-4b5b70)]">{{ inviteUrl }}</div>
  46. </div>
  47. <div class="mt-4 grid grid-cols-2 gap-3">
  48. <button
  49. type="button"
  50. class="flex h-11 cursor-pointer items-center justify-center gap-1.5 rounded-full bg-[var(--c-eef7ff)] text-sm font-bold text-[var(--c-0b8cff)] transition-colors hover:bg-[var(--c-e0f0ff)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--c-0b8cff)] focus-visible:ring-offset-2"
  51. @click="$emit('copy')"
  52. >
  53. <UIcon name="i-lucide-copy" class="size-4" />
  54. 复制链接
  55. </button>
  56. <a
  57. v-if="qrcodeUrl"
  58. :href="qrcodeUrl"
  59. target="_blank"
  60. rel="noopener"
  61. class="flex h-11 items-center justify-center gap-1.5 rounded-full bg-[var(--c-0b8cff)] text-sm font-bold text-white transition-colors hover:bg-[var(--c-087dde)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--c-0b8cff)] focus-visible:ring-offset-2"
  62. >
  63. <UIcon name="i-lucide-maximize-2" class="size-4" />
  64. 查看大图
  65. </a>
  66. <button
  67. v-else
  68. type="button"
  69. disabled
  70. class="flex h-11 cursor-not-allowed items-center justify-center rounded-full bg-[var(--c-e7edf5)] text-sm font-bold text-[var(--c-9aa5b5)]"
  71. >
  72. 查看大图
  73. </button>
  74. </div>
  75. </div>
  76. </div>
  77. </Transition>
  78. </Teleport>
  79. </template>
  80. <script setup>
  81. defineProps({
  82. open: { type: Boolean, default: false },
  83. qrcodeUrl: { type: String, default: '' },
  84. inviteUrl: { type: String, default: '' },
  85. loading: { type: Boolean, default: false },
  86. })
  87. const emit = defineEmits(['close', 'copy'])
  88. function onKeydown(event) {
  89. if (event.key === 'Escape') emit('close')
  90. }
  91. onMounted(() => document.addEventListener('keydown', onKeydown))
  92. onUnmounted(() => document.removeEventListener('keydown', onKeydown))
  93. </script>
  94. <style scoped>
  95. .invite-modal-enter-active,
  96. .invite-modal-leave-active {
  97. transition: opacity 0.2s ease;
  98. }
  99. .invite-modal-enter-from,
  100. .invite-modal-leave-to {
  101. opacity: 0;
  102. }
  103. </style>