ry_app/pages/BrandSelector/BrandSelector.vue

223 lines
5.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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>
<!-- 搜索框(增加层级隔离+样式重置) -->
<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>
</view>
<!-- 品牌列表 -->
<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>
<!-- 品牌管理入口 -->
<view class="brand-management" @click="handleToBrandManagement">
<text class="management-text"></text>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'BrandSelector',
props: {
visible: { type: Boolean, default: false },
defaultValue: { type: String, default: '默认品牌' },
brandList: { type: Array, default: () => [{ name: '默认品牌' }] }
},
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 =>
item.name.toLowerCase().includes(this.searchKeyword.toLowerCase())
)
}
},
methods: {
selectBrand(brandName) {
this.selectedBrand = brandName
},
handleConfirm() {
this.$emit('confirm', this.selectedBrand)
this.handleClose()
},
handleClose() {
this.$emit('close')
},
handleToBrandManagement() {
this.$emit('toBrandManagement')
},
handleSearchInput(e) {
this.searchKeyword = e.detail.value
}
}
}
</script>
<style lang="scss" scoped>
// 基础遮罩层
.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;
}
// 容器
.brand-selector-container {
width: 100%;
background: #FFFFFF;
border-radius: 16rpx 16rpx 0 0;
max-height: 80vh;
display: flex;
flex-direction: column;
z-index: 1000;
}
// 头部
.selector-header {
display: flex;
align-items: center;
justify-content: space-between;
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; }
}
// 搜索框:终极修复版(解决覆盖+还原视觉)
.search-bar {
padding: 20rpx 32rpx;
background: #FFFFFF;
position: relative;
z-index: 1001; // 确保搜索框在最上层
.search-input {
display: flex;
align-items: center;
background: #FFFFFF !important;
border: 1rpx solid #E8E8E8;
border-radius: 8rpx;
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;
}
}
}
// 品牌列表
.brand-list {
flex: 1;
overflow-y: auto;
.brand-item {
padding: 28rpx 32rpx;
border-bottom: 1rpx solid #F5F5F5;
font-size: 30rpx;
color: #333333;
position: relative;
font-weight: 400;
&.active {
color: #E62429;
&::after {
content: "✓";
position: absolute;
right: 32rpx;
top: 50%;
transform: translateY(-50%);
font-size: 28rpx;
font-weight: 600;
}
}
}
}
// 品牌管理入口
.brand-management {
padding: 28rpx 32rpx;
text-align: center;
color: #1677FF;
font-size: 28rpx;
border-top: 1rpx solid #F5F5F5;
font-weight: 400;
}
</style>