Files
hzdyjs/mobile/src/components/ServiceItem.vue
T
2025-08-07 13:19:12 +08:00

214 lines
4.1 KiB
Vue

<template>
<view
class="service-item touchable"
@click="handleClick"
:aria-label="`${title}服务`"
role="button"
tabindex="0"
>
<view class="service-icon">
<slot name="icon">
<text class="icon" v-if="icon">{{ icon }}</text>
</slot>
</view>
<text class="service-title">{{ title }}</text>
<view v-if="badge" class="service-badge">
<text class="badge-text">{{ badge }}</text>
</view>
</view>
</template>
<script>
export default {
name: 'ServiceItem',
props: {
title: {
type: String,
required: true,
},
icon: {
type: String,
default: '',
},
badge: {
type: [String, Number],
default: '',
},
},
methods: {
handleClick() {
this.$emit('click', { title: this.title });
uni.vibrateShort();
},
},
};
</script>
<style lang="scss" scoped>
.service-item {
background: #ffffff;
border-radius: 12px;
padding: 9px 16px;
text-align: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
cursor: pointer;
border: 1px solid transparent;
position: relative;
&:hover {
transform: translateY(-3px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
border-color: #007aff;
}
&:focus {
outline: 2px solid #007aff;
outline-offset: 2px;
}
}
.service-icon {
width: 48px;
height: 48px;
background: rgba(0, 122, 255, 0.1);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 12px;
color: #007aff;
transition: all 0.3s ease;
.icon {
font-size: 24px;
}
// 支持u-icon组件 - uview-plus图标
:deep(.u-icon) {
font-size: 24px !important;
color: inherit !important;
width: 24px;
height: 24px;
line-height: 1;
}
// 支持uview内置图标
:deep(.uview-icon) {
font-size: 24px !important;
color: inherit !important;
}
// 支持普通文本图标
.text-icon {
width: 24px;
height: 24px;
font-size: 24px;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
}
}
.service-item:hover .service-icon {
background: rgba(0, 122, 255, 0.2);
transform: scale(1.1);
}
.service-title {
font-size: 14px;
font-weight: 500;
color: #333333;
display: block;
margin-top: 8px;
word-break: break-all;
line-height: 1.4;
}
.service-badge {
position: absolute;
top: -6px;
right: -6px;
background: #ff3b30;
border-radius: 12px;
min-width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 6px;
box-shadow: 0 2px 4px rgba(255, 59, 48, 0.3);
}
.badge-text {
color: #ffffff;
font-size: 11px;
font-weight: 600;
line-height: 1;
white-space: nowrap;
}
/* 响应式设计 */
@media (max-width: 375px) {
.service-item {
padding: 20px 12px;
}
.service-icon {
width: 40px;
height: 40px;
margin-bottom: 8px;
.icon,
:deep(.u-icon) {
font-size: 20px !important;
}
}
.service-title {
font-size: 13px;
}
}
/* 小屏幕设备适配 */
@media (max-width: 320px) {
.service-item {
padding: 16px 8px;
}
.service-icon {
width: 36px;
height: 36px;
.icon,
:deep(.u-icon) {
font-size: 18px !important;
}
}
.service-title {
font-size: 12px;
margin-top: 6px;
}
}
/* 活跃状态动画 */
.service-item:active {
transform: scale(0.95);
transition: transform 0.1s ease;
}
/* 无障碍访问增强 */
@media (prefers-reduced-motion: reduce) {
.service-item,
.service-icon {
transition: none;
}
.service-item:hover {
transform: none;
}
}
</style>