94 lines
2.8 KiB
Vue
94 lines
2.8 KiB
Vue
<template>
|
||
<view class="store-picker">
|
||
<view class="picker-row" @click="openPicker">
|
||
<text class="label">所属诊所</text>
|
||
<text class="value" :class="{ placeholder: !selectedLabel }">{{ selectedLabel || '请选择诊所' }}</text>
|
||
<u-icon name="arrow-right" size="28" color="#999" />
|
||
</view>
|
||
<u-popup v-model="visible" mode="bottom" border-radius="24" height="70%">
|
||
<view class="popup-inner">
|
||
<view class="popup-title">选择诊所</view>
|
||
<input class="search-input" v-model="keyword" placeholder="搜索诊所名称" @input="onSearch" />
|
||
<scroll-view scroll-y class="option-list">
|
||
<view
|
||
v-for="item in options"
|
||
:key="item.id"
|
||
class="option-item"
|
||
@click="select(item)"
|
||
>
|
||
<text>{{ item.name }}</text>
|
||
<text v-if="item.position" class="sub">{{ item.position }}</text>
|
||
</view>
|
||
<view v-if="!loading && !options.length" class="empty">暂无诊所</view>
|
||
</scroll-view>
|
||
</view>
|
||
</u-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'StoreSearchPicker',
|
||
props: {
|
||
value: { type: [Number, String], default: 0 },
|
||
api: { type: Object, required: true },
|
||
},
|
||
data() {
|
||
return {
|
||
visible: false,
|
||
keyword: '',
|
||
options: [],
|
||
loading: false,
|
||
selectedLabel: '',
|
||
searchTimer: null,
|
||
};
|
||
},
|
||
methods: {
|
||
openPicker() {
|
||
this.visible = true;
|
||
this.fetchOptions('');
|
||
},
|
||
onSearch() {
|
||
if (this.searchTimer) clearTimeout(this.searchTimer);
|
||
this.searchTimer = setTimeout(() => this.fetchOptions(this.keyword.trim()), 300);
|
||
},
|
||
async fetchOptions(keyword) {
|
||
this.loading = true;
|
||
try {
|
||
const wrap = await this.api.getPlatformStoreOptions(keyword);
|
||
this.options = (wrap && wrap.ok && wrap.data) ? wrap.data : [];
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
select(item) {
|
||
this.selectedLabel = item.position ? `${item.name}(${item.position})` : item.name;
|
||
this.$emit('input', item.id);
|
||
this.visible = false;
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.picker-row {
|
||
display: flex; align-items: center; padding: 24rpx 0;
|
||
border-bottom: 1rpx solid #f0f0f0;
|
||
}
|
||
.label { width: 180rpx; font-size: 28rpx; color: #333; }
|
||
.value { flex: 1; font-size: 28rpx; text-align: right; margin-right: 8rpx; }
|
||
.placeholder { color: #bbb; }
|
||
.popup-inner { padding: 32rpx; height: 100%; display: flex; flex-direction: column; }
|
||
.popup-title { font-size: 32rpx; font-weight: 600; margin-bottom: 24rpx; }
|
||
.search-input {
|
||
background: #f5f5f5; border-radius: 12rpx; padding: 16rpx 24rpx; margin-bottom: 16rpx;
|
||
}
|
||
.option-list { flex: 1; }
|
||
.option-item {
|
||
padding: 24rpx 0; border-bottom: 1rpx solid #f0f0f0;
|
||
display: flex; flex-direction: column;
|
||
}
|
||
.sub { font-size: 24rpx; color: #999; margin-top: 8rpx; }
|
||
.empty { text-align: center; color: #999; padding: 60rpx 0; }
|
||
</style>
|