184 lines
3.7 KiB
Vue
184 lines
3.7 KiB
Vue
<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-box">
|
||
<input
|
||
class="search-input"
|
||
type="text"
|
||
placeholder="搜索品牌名称"
|
||
v-model="searchKeyword"
|
||
/>
|
||
</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.includes(this.searchKeyword)
|
||
)
|
||
}
|
||
},
|
||
methods: {
|
||
selectBrand(brandName) {
|
||
this.selectedBrand = brandName
|
||
},
|
||
handleConfirm() {
|
||
this.$emit('confirm', this.selectedBrand)
|
||
this.handleClose()
|
||
},
|
||
handleClose() {
|
||
this.$emit('close')
|
||
},
|
||
handleToBrandManagement() {
|
||
this.$emit('toBrandManagement')
|
||
}
|
||
}
|
||
}
|
||
</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: #fff;
|
||
border-radius: 16rpx 16rpx 0 0;
|
||
max-height: 80vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.selector-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 30rpx;
|
||
border-bottom: 1rpx solid #f0f0f0;
|
||
.close-icon {
|
||
font-size: 36rpx;
|
||
color: #666;
|
||
}
|
||
.header-title {
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
color: #333;
|
||
}
|
||
.confirm-btn {
|
||
font-size: 30rpx;
|
||
color: #E62429;
|
||
}
|
||
}
|
||
|
||
.search-box {
|
||
padding: 20rpx 30rpx;
|
||
.search-input {
|
||
width: 100%;
|
||
padding: 20rpx;
|
||
background: #f5f5f5;
|
||
border-radius: 8rpx;
|
||
font-size: 28rpx;
|
||
}
|
||
}
|
||
|
||
.brand-list {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
.brand-item {
|
||
padding: 30rpx;
|
||
border-bottom: 1rpx solid #f0f0f0;
|
||
font-size: 30rpx;
|
||
color: #333;
|
||
position: relative;
|
||
&.active {
|
||
color: #E62429;
|
||
&::after {
|
||
content: "✓";
|
||
position: absolute;
|
||
right: 30rpx;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
font-size: 28rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.brand-management {
|
||
padding: 30rpx;
|
||
text-align: center;
|
||
color: #1677FF;
|
||
font-size: 28rpx;
|
||
border-top: 1rpx solid #f0f0f0;
|
||
}
|
||
</style> |