card-websdkLink.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <template>
  2. <!-- <u-modal v-model:show="dialogVisible" :show-cancel-button="false" :show-confirm-button="false"
  3. class="dialog_header_w" :close-on-click-overlay="false" @close="handleClose">
  4. <view class="dia-content">
  5. <view class="icon">
  6. <image class="imgs" src="/static/images/success.png" alt="" />
  7. </view>
  8. <view v-if="responseCode === 200 && qrCodeUrl" v-t="'card.New2.v1'" class="des1"></view>
  9. <view v-if="responseCode === 200 && !qrCodeUrl" v-t="'card.Info.s43'" class="des1"></view>
  10. <view v-if="responseCode === 201" v-t="'card.Info.s7'" class="des1"></view>
  11. <view v-if="responseCode === 201" v-t="'card.Info.s5'" class="des2"></view>
  12. <view v-if="loading" class="loading-text">{{ t("common.loading") }}</view>
  13. <QrCode v-if="showQrCode && qrCodeUrl" :text="qrCodeUrl"></QrCode>
  14. <view v-if="responseCode === 200 && qrCodeUrl" v-t="'card.New2.v2'" class="des2"></view>
  15. <view class="dialog-footer">
  16. <u-button v-t="'card.Btn.Confirm'" block :loading="loading" @click="handleClose"></u-button>
  17. </view>
  18. </view>
  19. </u-modal> -->
  20. <web-view class="aaa" v-if="qrCodeUrl" :src="qrCodeUrl" style="height: 100vh;"></web-view>
  21. </template>
  22. <script setup lang="ts">
  23. import { ref } from "vue";
  24. import { useI18n } from "vue-i18n";
  25. import useRouter from "@/hooks/useRouter";
  26. import { ucardApi } from "@/api/ucard";
  27. import QrCode from "@/components/QrCode.vue";
  28. const { t } = useI18n();
  29. const router = useRouter();
  30. // 弹窗显示状态
  31. const dialogVisible = ref(false);
  32. // 二维码链接
  33. const qrCodeUrl = ref("");
  34. // API 响应码
  35. const responseCode = ref(200);
  36. // 是否显示二维码
  37. const showQrCode = ref(false);
  38. // 加载状态
  39. const loading = ref(false);
  40. // 设备元信息
  41. const metaInfo = ref<Record<string, any> | null>(null);
  42. /**
  43. * 获取设备元信息
  44. */
  45. function getMetaInfo() {
  46. try {
  47. // 安全获取 metaInfo,兼容不同环境
  48. if (typeof window !== "undefined" && (window as any).getMetaInfo) {
  49. metaInfo.value = (window as any).getMetaInfo();
  50. metaInfo.value = { ...metaInfo.value, deviceType: "h5" };
  51. } else {
  52. // 默认值
  53. metaInfo.value = { deviceType: "h5" };
  54. }
  55. } catch (error) {
  56. // console.warn("获取设备信息失败:", error);
  57. metaInfo.value = { deviceType: "h5" };
  58. }
  59. }
  60. /**
  61. * 重置组件状态
  62. */
  63. function resetState() {
  64. qrCodeUrl.value = "";
  65. responseCode.value = 200;
  66. showQrCode.value = false;
  67. loading.value = false;
  68. }
  69. /**
  70. * 关闭弹窗
  71. */
  72. function handleClose() {
  73. dialogVisible.value = false;
  74. resetState();
  75. // 跳转到我的页面
  76. router.replace("/pages/mine/index");
  77. }
  78. /**
  79. * 获取 WebSDK 链接
  80. * @param cardId 卡片ID
  81. */
  82. async function getWebsdkLink(cardId?: string | number) {
  83. if (!cardId) {
  84. // console.warn("cardId 为空,无法获取 WebSDK 链接");
  85. responseCode.value = 201;
  86. dialogVisible.value = true;
  87. return;
  88. }
  89. dialogVisible.value = true;
  90. loading.value = true;
  91. resetState();
  92. try {
  93. // 获取设备信息
  94. getMetaInfo();
  95. // 调用 API
  96. const res = await ucardApi.getWebsdkLink({
  97. cardId: String(cardId),
  98. metaInfo: metaInfo.value,
  99. });
  100. responseCode.value = res.code || 201;
  101. if (res.code === 200 && res.data) {
  102. try {
  103. // 安全解析 JSON
  104. const data = typeof res.data === "string" ? JSON.parse(res.data) : res.data;
  105. qrCodeUrl.value = data.url || data.link || "";
  106. showQrCode.value = !!qrCodeUrl.value;
  107. } catch (parseError) {
  108. // console.error("解析响应数据失败:", parseError);
  109. responseCode.value = 201;
  110. showQrCode.value = false;
  111. }
  112. } else {
  113. showQrCode.value = false;
  114. qrCodeUrl.value = "";
  115. }
  116. } catch (error: any) {
  117. // console.error("获取 WebSDK 链接失败:", error);
  118. responseCode.value = 201;
  119. showQrCode.value = false;
  120. qrCodeUrl.value = "";
  121. // 可选:显示错误提示
  122. // uni.showToast({
  123. // title: error.message || t("common.error"),
  124. // icon: "none",
  125. // });
  126. } finally {
  127. loading.value = false;
  128. }
  129. }
  130. // 暴露方法给父组件使用
  131. defineExpose({
  132. getWebsdkLink,
  133. });
  134. </script>
  135. <style scoped lang="scss">
  136. @import "@/uni.scss";
  137. .dialog_header_w {
  138. :deep(.u-popup__content) {
  139. width: 90% !important;
  140. }
  141. :deep(.u-modal) {
  142. width: 100% !important;
  143. }
  144. .dia-content {
  145. padding: px2rpx(20) px2rpx(10);
  146. text-align: center;
  147. .icon .imgs {
  148. width: px2rpx(80);
  149. height: px2rpx(80);
  150. }
  151. .des1 {
  152. font-weight: bold;
  153. font-size: px2rpx(14);
  154. color: #000;
  155. margin: px2rpx(30) 0 px2rpx(20);
  156. }
  157. .des2 {
  158. font-size: px2rpx(12);
  159. color: #000;
  160. margin: px2rpx(20) 0;
  161. line-height: px2rpx(20);
  162. }
  163. .dialog-footer {
  164. margin-top: px2rpx(20);
  165. }
  166. .loading-text {
  167. font-size: px2rpx(14);
  168. color: var(--bs-heading-color);
  169. margin: px2rpx(20) 0;
  170. }
  171. }
  172. }
  173. .aaa {
  174. background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
  175. padding-top: env(safe-area-inset-top);
  176. }
  177. </style>