front/src/views/login/components/LoginHero.vue
zzh 696adf7684 feat: 新增 H5 轨迹查询页并优化角色权限分配
- 新增 /track/query 移动端轨迹查询页,登录页 Hero 可跳转查询

- 角色权限分配支持父子级联勾选与已选计数修正

- nginx/vite 放行 H5 轨迹路由

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-04 17:59:20 +08:00

229 lines
4.5 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.

<template>
<div :class="['login-hero', { 'login-hero--light': light }]">
<div class="login-hero__inner">
<div class="login-hero__content">
<div class="login-hero__heading">
<h2 class="login-hero__title">{{ t('login.hero.title') }}</h2>
<span class="login-hero__tagline">|{{ t('login.hero.tagline') }}</span>
</div>
<p class="login-hero__desc">{{ t('login.hero.desc') }}</p>
<form class="login-hero__search" @submit.prevent="onTrackSubmit">
<input
v-model="trackingNo"
type="text"
class="login-hero__search-input"
:placeholder="t('login.hero.trackPlaceholder')"
autocomplete="off"
/>
<button type="submit" class="login-hero__search-btn">
{{ t('login.hero.track') }}
</button>
</form>
</div>
<div class="login-hero__visual">
<img class="login-hero__plane" src="/login-assets/hero-plane.png" alt="" />
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { Message } from '@arco-design/web-vue';
defineOptions({ name: 'LoginHero' });
defineProps<{
light?: boolean;
}>();
const { t } = useI18n();
const router = useRouter();
const trackingNo = ref('');
function onTrackSubmit() {
const no = trackingNo.value.trim();
if (!no) {
Message.info(t('login.hero.trackPlaceholder'));
return;
}
router.push({ path: '/track/query', query: { no } });
}
</script>
<style lang="less" scoped>
.login-hero {
width: 100%;
color: rgba(255, 255, 255, 0.88);
}
.login-hero__inner {
display: flex;
align-items: center;
justify-content: center;
gap: 24px;
width: 100%;
margin: 0 auto;
padding: 0 8px;
}
.login-hero__content {
flex: 1 1 auto;
min-width: 0;
max-width: 520px;
}
.login-hero__heading {
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 0;
margin: 0 0 20px;
}
.login-hero__title {
margin: 0;
font-size: clamp(2rem, 3.6vw, 4.5rem);
font-weight: 700;
letter-spacing: -0.02em;
line-height: 1.08;
color: #fff;
}
.login-hero__tagline {
font-size: 30px;
font-weight: 600;
line-height: 1.08;
color: #fff;
}
.login-hero__desc {
margin: 0 0 32px;
font-size: 15px;
line-height: 1.7;
color: rgba(255, 255, 255, 0.82);
max-width: 520px;
}
.login-hero__search {
display: flex;
align-items: stretch;
gap: 10px;
max-width: 480px;
margin-bottom: 28px;
padding: 10px;
background: #fff;
border-radius: 10px;
}
.login-hero__search-input {
flex: 1;
min-width: 0;
padding: 14px 16px;
border: none;
background: transparent;
font-size: 14px;
color: #1a2d4a;
outline: none;
}
.login-hero__search-btn {
flex-shrink: 0;
min-width: 110px;
padding: 0 24px;
border: none;
border-radius: 6px;
background: var(--app-primary-color, #007979);
color: #fff;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: background 0.2s;
}
.login-hero__search-btn:hover {
background: #006868;
}
.login-hero__visual {
flex: 0 1 42%;
min-width: 0;
display: flex;
justify-content: center;
align-items: center;
margin-top: -1000px;
margin-left: -200px;
}
.login-hero__plane {
width: 100%;
max-width: 420px;
height: auto;
margin-top: 200px;
margin-left: -200px;
transform-origin: 70% 50%;
animation: loginHeroPlane3D 3.6s linear 1 forwards;
will-change: transform, opacity;
}
.login-hero--light {
color: rgba(26, 45, 74, 0.88);
}
.login-hero--light .login-hero__title,
.login-hero--light .login-hero__tagline {
color: #1a2d4a;
}
.login-hero--light .login-hero__desc {
color: rgba(26, 45, 74, 0.78);
}
@keyframes loginHeroPlane3D {
0% {
transform: translate3d(-280px, 180px, 0) scale(0.32) rotate(-2deg);
opacity: 0.2;
}
25% {
transform: translate3d(-150px, 150px, 0) scale(0.95) rotate(-1.5deg);
opacity: 0.8;
}
50% {
transform: translate3d(-20px, 125px, 0) scale(1.58) rotate(-1deg);
opacity: 0.95;
}
75% {
transform: translate3d(115px, 102px, 0) scale(2.22) rotate(-0.5deg);
opacity: 1;
}
100% {
transform: translate3d(245px, 87px, 0) scale(2.85) rotate(0deg);
opacity: 1;
}
}
@media screen and (max-width: 1250px) {
.login-hero__visual {
display: none;
}
.login-hero__content {
flex: 1 1 100%;
}
}
@media screen and (max-width: 768px) {
.login-hero__title {
font-size: 2rem;
}
.login-hero__tagline {
font-size: 22px;
}
}
</style>