ry_app/pages/BrandSelector/BrandSelector.vue

223 lines
5.3 KiB
Vue
Raw Normal View History

2026-01-22 21:27:11 +08:00
<template>
<view v-if="visible" class="brand-selector-overlay" @click="handleClose">
<view class="brand-selector-container" @click.stop>
<!-- 头部 -->
<view class="selector-header">
<view class="header-left" @click="handleClose">
<text class="close-icon">×</text>
</view>
<view class="header-title">选择品牌</view>
<view class="header-right" @click="handleConfirm">
<text class="confirm-btn">完成</text>
</view>
</view>
2026-01-26 18:58:10 +08:00
<!-- 搜索框增加层级隔离+样式重置 -->
<view class="search-bar">
<view class="search-input">
<uni-icons class="search-icon" type="search" size="20" color="#CCCCCC"></uni-icons>
<input
type="text"
placeholder="搜索品牌名称"
placeholder-class="input-placeholder"
v-model="searchKeyword"
class="input"
@input="handleSearchInput"
/>
</view>
2026-01-22 21:27:11 +08:00
</view>
2026-01-26 18:58:10 +08:00
2026-01-22 21:27:11 +08:00
<!-- 品牌列表 -->
<view class="brand-list">
<view
class="brand-item"
:class="{active: selectedBrand === item.name}"
v-for="item in filteredBrandList"
:key="item.name"
@click="selectBrand(item.name)"
>
{{ item.name }}
</view>
</view>
2026-01-26 18:58:10 +08:00
2026-01-22 21:27:11 +08:00
<!-- 品牌管理入口 -->
<view class="brand-management" @click="handleToBrandManagement">
<text class="management-text">品牌管理</text>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'BrandSelector',
props: {
2026-01-26 18:58:10 +08:00
visible: { type: Boolean, default: false },
defaultValue: { type: String, default: '默认品牌' },
brandList: { type: Array, default: () => [{ name: '默认品牌' }] }
2026-01-22 21:27:11 +08:00
},
data() {
return {
selectedBrand: this.defaultValue,
searchKeyword: ''
}
},
watch: {
defaultValue(newVal) {
this.selectedBrand = newVal
}
},
computed: {
filteredBrandList() {
if (!this.searchKeyword) return this.brandList
return this.brandList.filter(item =>
2026-01-26 18:58:10 +08:00
item.name.toLowerCase().includes(this.searchKeyword.toLowerCase())
2026-01-22 21:27:11 +08:00
)
}
},
methods: {
selectBrand(brandName) {
this.selectedBrand = brandName
},
handleConfirm() {
this.$emit('confirm', this.selectedBrand)
this.handleClose()
},
handleClose() {
this.$emit('close')
},
handleToBrandManagement() {
this.$emit('toBrandManagement')
2026-01-26 18:58:10 +08:00
},
handleSearchInput(e) {
this.searchKeyword = e.detail.value
2026-01-22 21:27:11 +08:00
}
}
}
</script>
<style lang="scss" scoped>
2026-01-26 18:58:10 +08:00
// 基础遮罩层
2026-01-22 21:27:11 +08:00
.brand-selector-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: flex-end;
z-index: 999;
}
2026-01-26 18:58:10 +08:00
// 容器
2026-01-22 21:27:11 +08:00
.brand-selector-container {
width: 100%;
2026-01-26 18:58:10 +08:00
background: #FFFFFF;
2026-01-22 21:27:11 +08:00
border-radius: 16rpx 16rpx 0 0;
max-height: 80vh;
display: flex;
flex-direction: column;
2026-01-26 18:58:10 +08:00
z-index: 1000;
2026-01-22 21:27:11 +08:00
}
2026-01-26 18:58:10 +08:00
// 头部
2026-01-22 21:27:11 +08:00
.selector-header {
display: flex;
align-items: center;
justify-content: space-between;
2026-01-26 18:58:10 +08:00
padding: 24rpx 32rpx;
border-bottom: 1rpx solid #F5F5F5;
.close-icon { font-size: 36rpx; color: #666666; font-weight: 400; }
.header-title { font-size: 32rpx; font-weight: 500; color: #333333; }
.confirm-btn { font-size: 30rpx; color: #E62429; font-weight: 400; }
2026-01-22 21:27:11 +08:00
}
2026-01-26 18:58:10 +08:00
// 搜索框:终极修复版(解决覆盖+还原视觉)
.search-bar {
padding: 20rpx 32rpx;
background: #FFFFFF;
position: relative;
z-index: 1001; // 确保搜索框在最上层
2026-01-22 21:27:11 +08:00
.search-input {
2026-01-26 18:58:10 +08:00
display: flex;
align-items: center;
background: #FFFFFF !important;
border: 1rpx solid #E8E8E8;
2026-01-22 21:27:11 +08:00
border-radius: 8rpx;
2026-01-26 18:58:10 +08:00
height: 76rpx;
padding: 0 24rpx;
position: relative;
z-index: 1002; // 确保输入框容器层级最高
.search-icon {
margin-right: 16rpx;
color: #CCCCCC !important;
flex-shrink: 0;
position: relative;
z-index: 1; // 图标层级低于输入框文字
}
.input {
flex: 1;
font-size: 28rpx;
color: #333333 !important; // 强制文字颜色,防止被全局样式覆盖
border: none !important;
outline: none !important;
background: transparent !important;
padding: 0; // 彻底移除内边距,避免行高冲突
line-height: 76rpx; // 行高与容器高度一致,确保垂直居中
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
position: relative;
z-index: 2; // 确保文字在最上层,不被任何元素遮挡
}
.input-placeholder {
font-size: 28rpx;
color: #CCCCCC !important;
}
2026-01-22 21:27:11 +08:00
}
}
2026-01-26 18:58:10 +08:00
// 品牌列表
2026-01-22 21:27:11 +08:00
.brand-list {
flex: 1;
overflow-y: auto;
2026-01-26 18:58:10 +08:00
2026-01-22 21:27:11 +08:00
.brand-item {
2026-01-26 18:58:10 +08:00
padding: 28rpx 32rpx;
border-bottom: 1rpx solid #F5F5F5;
2026-01-22 21:27:11 +08:00
font-size: 30rpx;
2026-01-26 18:58:10 +08:00
color: #333333;
2026-01-22 21:27:11 +08:00
position: relative;
2026-01-26 18:58:10 +08:00
font-weight: 400;
2026-01-22 21:27:11 +08:00
&.active {
color: #E62429;
&::after {
content: "✓";
position: absolute;
2026-01-26 18:58:10 +08:00
right: 32rpx;
2026-01-22 21:27:11 +08:00
top: 50%;
transform: translateY(-50%);
font-size: 28rpx;
2026-01-26 18:58:10 +08:00
font-weight: 600;
2026-01-22 21:27:11 +08:00
}
}
}
}
2026-01-26 18:58:10 +08:00
// 品牌管理入口
2026-01-22 21:27:11 +08:00
.brand-management {
2026-01-26 18:58:10 +08:00
padding: 28rpx 32rpx;
2026-01-22 21:27:11 +08:00
text-align: center;
color: #1677FF;
font-size: 28rpx;
2026-01-26 18:58:10 +08:00
border-top: 1rpx solid #F5F5F5;
font-weight: 400;
2026-01-22 21:27:11 +08:00
}
</style>