..
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
<template>
|
||||
<view class="search-picker">
|
||||
<view class="picker-field" @click="openPicker">
|
||||
<input
|
||||
@click="openPicker"
|
||||
class="picker-input"
|
||||
:value="getSelectedLabel()"
|
||||
:placeholder="placeholder"
|
||||
:readonly="true"
|
||||
:disabled="true"
|
||||
/>
|
||||
<text class="arrow" :class="{ 'arrow-up': isPickerOpen }">›</text>
|
||||
</view>
|
||||
|
||||
<view v-if="isPickerOpen" class="dropdown-container">
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-container">
|
||||
<input
|
||||
class="search-input"
|
||||
v-model="searchText"
|
||||
placeholder="搜索"
|
||||
confirm-type="search"
|
||||
@input="onSearch"
|
||||
auto-focus
|
||||
/>
|
||||
</view>
|
||||
|
||||
<scroll-view
|
||||
:scroll-y="true"
|
||||
class="options-list"
|
||||
:style="{ maxHeight: maxHeight + 'rpx' }"
|
||||
>
|
||||
<view
|
||||
v-for="(item, index) in filteredOptions"
|
||||
:key="index"
|
||||
class="option-item"
|
||||
:class="{ 'option-selected': isSelected(item) }"
|
||||
@tap="selectOption(item)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</view>
|
||||
<view v-if="filteredOptions.length === 0" class="no-data">
|
||||
没有找到匹配结果
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 遮罩层,点击关闭下拉框 -->
|
||||
<view v-if="isPickerOpen" class="mask" @tap="closePicker"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
// 选项数据,格式为 [{value: '1', label: '选项1'}, {value: '2', label: '选项2'}]
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 当前选中的值
|
||||
modelValue: {
|
||||
type: [String, Number, Object],
|
||||
default: ''
|
||||
},
|
||||
// 占位文字
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
// 选项列表最大高度(单位rpx)
|
||||
maxHeight: {
|
||||
type: Number,
|
||||
default: 500
|
||||
}
|
||||
});
|
||||
|
||||
// Emits 定义
|
||||
const emit = defineEmits(['update:modelValue', 'change']);
|
||||
|
||||
// 响应式状态
|
||||
const isPickerOpen = ref(false);
|
||||
const searchText = ref('');
|
||||
const selectedValue = ref(props.modelValue);
|
||||
|
||||
// 监听modelValue变化
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
selectedValue.value = newVal;
|
||||
});
|
||||
|
||||
// 根据搜索文本过滤选项
|
||||
const filteredOptions = computed(() => {
|
||||
if (!searchText.value) {
|
||||
return props.options;
|
||||
}
|
||||
return props.options.filter(item =>
|
||||
item.label.toLowerCase().includes(searchText.value.toLowerCase())
|
||||
);
|
||||
});
|
||||
|
||||
// 打开选择器
|
||||
const openPicker = () => {
|
||||
debugger
|
||||
searchText.value = '';
|
||||
isPickerOpen.value = true;
|
||||
};
|
||||
|
||||
// 关闭选择器
|
||||
const closePicker = () => {
|
||||
isPickerOpen.value = false;
|
||||
};
|
||||
|
||||
// 选择选项
|
||||
const selectOption = (item) => {
|
||||
selectedValue.value = item.value;
|
||||
emit('update:modelValue', item.value);
|
||||
emit('change', item.value);
|
||||
closePicker();
|
||||
};
|
||||
|
||||
// 判断选项是否被选中
|
||||
const isSelected = (item) => {
|
||||
return item.value === selectedValue.value;
|
||||
};
|
||||
|
||||
// 搜索处理
|
||||
const onSearch = () => {
|
||||
// 搜索逻辑已通过计算属性 filteredOptions 实现
|
||||
};
|
||||
|
||||
// 获取选中项的标签
|
||||
const getSelectedLabel = () => {
|
||||
const selected = props.options.find(item => item.value === selectedValue.value);
|
||||
return selected ? selected.label : '';
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.search-picker {
|
||||
position: relative;
|
||||
//height: 100rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
//padding: 0 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
//box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.picker-field {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.picker-input {
|
||||
flex: 1;
|
||||
//height: 80rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 36rpx;
|
||||
color: #999;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.arrow-up {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.dropdown-container {
|
||||
position: absolute;
|
||||
top: 110rpx; /* 输入框下方留出一点间距 */
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
|
||||
z-index: 101;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 20rpx;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background-color: #f7f7f7;
|
||||
padding: 0 30rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.options-list {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.option-item {
|
||||
padding: 24rpx 30rpx;
|
||||
font-size: 28rpx;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.option-selected {
|
||||
color: #5c6bc0;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
padding: 40rpx 0;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 99;
|
||||
}
|
||||
</style>
|
||||
@@ -4,21 +4,21 @@
|
||||
<view class="success-content">
|
||||
<!-- 成功图片 -->
|
||||
<view class="success-image">
|
||||
<image src="https://cdn-icons-png.flaticon.com/512/10613/10613684.png" mode="aspectFit"></image>
|
||||
<image src="/static/img/successful.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 成功信息 -->
|
||||
<view class="success-info">
|
||||
<view class="success-title">报名成功</view>
|
||||
<view class="success-subtitle">您已成功报名参加"{{ activityTitle }}"</view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 小提示 -->
|
||||
<view class="success-tips">
|
||||
<t-icon name="info-circle-filled" size="16px" />
|
||||
<text>活动开始前我们将通过短信通知您</text>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="action-buttons">
|
||||
<t-button theme="default" shape="round" @click="navigateToHome">返回首页</t-button>
|
||||
@@ -102,7 +102,7 @@ const viewRegistrationDetails = () => {
|
||||
margin-bottom: 30px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -151,12 +151,12 @@ const viewRegistrationDetails = () => {
|
||||
padding: 10px 20px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 40px;
|
||||
|
||||
|
||||
.t-icon {
|
||||
color: #ff5f5c;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
|
||||
text {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
@@ -170,19 +170,19 @@ const viewRegistrationDetails = () => {
|
||||
width: 100%;
|
||||
padding: 0 20px;
|
||||
margin-top: 20px;
|
||||
|
||||
|
||||
:deep(.t-button) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
|
||||
:deep(.t-button--primary) {
|
||||
background-color: #ff5f5c !important;
|
||||
border-color: #ff5f5c !important;
|
||||
}
|
||||
|
||||
|
||||
:deep(.t-button--default) {
|
||||
border-color: #ff5f5c !important;
|
||||
color: #ff5f5c !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
Reference in New Issue
Block a user