| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- <template>
- <div class="guard-info-board">
- <div class="board-wrap" :style="{ backgroundImage: `url(${boardImg})` }">
- <div class="board-text">
- <div class="board-title">{{ title }}</div>
- <div class="board-sub">{{ subtitle }}</div>
- </div>
- <div class="edit-btn" aria-label="编辑" @click.stop="onEdit">
- <Icon icon="solar:pen-new-square-linear" />
- </div>
- </div>
- <div class="info-cards" :style="{ '--card-border-bg': `url(${borderBgImg})` }">
- <div v-for="(card, index) in cards" :key="index" class="info-card">
- <template v-if="index === 3">
- <img class="badge-icon" :src="resolvedBadgeIcon" alt="" />
- <span class="badge-label">{{ card.bottom }}</span>
- </template>
- <template v-else>
- <div class="card-top">{{ card.top }}</div>
- <div class="card-bottom">{{ card.bottom }}</div>
- </template>
- </div>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { computed } from 'vue'
- import { Icon } from '@iconify/vue'
- import boardImg from '@/assets/img/guard/board.png'
- import borderBgImg from '@/assets/img/guard/border-bg.png'
- import level1Img from '@/assets/img/guard/level-1.png'
- export type GuardInfoCard = {
- top?: string
- bottom: string
- }
- const props = withDefaults(
- defineProps<{
- title?: string
- subtitle?: string
- badgeIcon?: string
- cards?: GuardInfoCard[]
- }>(),
- {
- title: '【茜茜荔荔】',
- subtitle: '用户昵称 2025.06.22',
- cards: () => [
- { top: '2025.05.16', bottom: '从化荔博园' },
- { top: '16年老树', bottom: '妃子笑荔枝' },
- { top: '成熟期', bottom: '温度适宜-梢期杀虫' },
- { top: '', bottom: '润土行者' },
- ],
- },
- )
- const resolvedBadgeIcon = computed(() => props.badgeIcon || level1Img)
- const emit = defineEmits<{ edit: [] }>()
- function onEdit() {
- emit('edit')
- }
- </script>
- <style scoped lang="less">
- .guard-info-board {
- position: relative;
- width: 100%;
- pointer-events: none;
- .board-wrap {
- position: relative;
- z-index: 1;
- width: 200rem;
- height: 335rem;
- background-repeat: no-repeat;
- background-position: center;
- background-size: 100% 100%;
- pointer-events: none;
- .board-text {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 146rem;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- box-sizing: border-box;
- text-align: center;
- color: #fff;
- pointer-events: none;
- .board-title {
- font-family: jiangxizhuokai, 'Songti SC', 'STSong', serif;
- font-size: 26rem;
- text-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.25);
- }
- .board-sub {
- font-family: jiangxizhuokai, 'Songti SC', 'STSong', serif;
- margin-top: 5rem;
- font-size: 10rem;
- }
- }
- .edit-btn {
- position: absolute;
- right: 0rem;
- top: 120rem;
- width: 23rem;
- height: 23rem;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- background: rgba(0, 0, 0, 0.6);
- color: #fff;
- pointer-events: auto;
-
- svg {
- font-size: 10rem;
- }
- }
- }
- .info-cards {
- position: absolute;
- left: 50%;
- bottom: calc(var(--footer-bottom-offset) + var(--footer-height) + 10rem);
- z-index: 2;
- width: calc(100vw - 20rem);
- transform: translateX(-50%);
- display: grid;
- grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1fr);
- gap: 4rem;
- .info-card {
- width: 100%;
- min-width: 0;
- height: 58rem;
- background: var(--card-border-bg) no-repeat center / 100% 100%;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- text-align: center;
- color: #fff;
- .card-top {
- width: 100%;
- font-family: SmileySans, sans-serif;
- font-size: 16rem;
- margin-bottom: 3rem;
- }
- .card-bottom {
- width: 100%;
- font-size: 10rem;
- }
- .badge-icon {
- width: 24rem;
- height: 31rem;
- object-fit: contain;
- margin-bottom: 2rem;
- }
- .badge-label {
- width: 100%;
- font-size: 10rem;
- font-weight: 600;
- color: #ffd2a7;
- }
- }
- }
- }
- </style>
|