a919781d4f
配载草稿确认生成正式单并优化详情/列表地址市区展示;运单调度等按承运商联系人所属组织筛选司机车辆;统一地图搜索结果与登录默认账号清理。 Co-authored-by: Cursor <cursoragent@cursor.com>
225 lines
4.6 KiB
Vue
225 lines
4.6 KiB
Vue
<template>
|
||
<div v-if="results.length" class="map-search-results">
|
||
<div class="map-search-results__list">
|
||
<div
|
||
v-for="(item, index) in pageResults"
|
||
:key="item.id || `${currentPage}-${index}`"
|
||
class="map-search-results__item"
|
||
:class="{ 'is-active': isActive(item, index) }"
|
||
@click="handleSelect(item, index)"
|
||
>
|
||
<img
|
||
v-if="item.photo || item.image"
|
||
class="map-search-results__thumb"
|
||
:src="item.photo || item.image"
|
||
alt=""
|
||
/>
|
||
<div class="map-search-results__body">
|
||
<div class="map-search-results__name">
|
||
{{ item.name || item.address || '未命名地址' }}
|
||
</div>
|
||
<div class="map-search-results__address">
|
||
地址:{{ item.address || item.name || '-' }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div v-if="totalPages > 1" class="map-search-results__pager">
|
||
<button
|
||
v-for="page in visiblePages"
|
||
:key="page"
|
||
type="button"
|
||
class="map-search-results__page"
|
||
:class="{ 'is-active': page === currentPage }"
|
||
@click="currentPage = page"
|
||
>
|
||
{{ page }}
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="map-search-results__page map-search-results__page--next"
|
||
:disabled="currentPage >= totalPages"
|
||
@click="goNext"
|
||
>
|
||
下一页
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
const PAGE_SIZE = 5;
|
||
|
||
export default {
|
||
props: {
|
||
results: {
|
||
type: Array,
|
||
default: () => [],
|
||
},
|
||
},
|
||
emits: ['select'],
|
||
data() {
|
||
return {
|
||
currentPage: 1,
|
||
activeKey: '',
|
||
};
|
||
},
|
||
computed: {
|
||
totalPages() {
|
||
return Math.max(1, Math.ceil((this.results || []).length / PAGE_SIZE));
|
||
},
|
||
pageResults() {
|
||
const start = (this.currentPage - 1) * PAGE_SIZE;
|
||
return (this.results || []).slice(start, start + PAGE_SIZE);
|
||
},
|
||
visiblePages() {
|
||
const maxButtons = 3;
|
||
let start = Math.max(1, this.currentPage - 1);
|
||
let end = Math.min(this.totalPages, start + maxButtons - 1);
|
||
start = Math.max(1, end - maxButtons + 1);
|
||
const pages = [];
|
||
for (let page = start; page <= end; page += 1) {
|
||
pages.push(page);
|
||
}
|
||
return pages;
|
||
},
|
||
},
|
||
watch: {
|
||
results() {
|
||
this.currentPage = 1;
|
||
this.activeKey = '';
|
||
},
|
||
},
|
||
methods: {
|
||
resultKey(item, index) {
|
||
return item?.id ?? `${this.currentPage}-${index}`;
|
||
},
|
||
isActive(item, index) {
|
||
return this.activeKey === this.resultKey(item, index);
|
||
},
|
||
handleSelect(item, index) {
|
||
this.activeKey = this.resultKey(item, index);
|
||
this.$emit('select', item);
|
||
},
|
||
goNext() {
|
||
if (this.currentPage < this.totalPages) {
|
||
this.currentPage += 1;
|
||
}
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.map-search-results {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
z-index: 2000;
|
||
display: flex;
|
||
flex-direction: column;
|
||
width: 360px;
|
||
max-height: 360px;
|
||
overflow: hidden;
|
||
background: #fff;
|
||
border: 1px solid #dcdfe6;
|
||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.12);
|
||
pointer-events: auto;
|
||
|
||
&__list {
|
||
flex: 1 1 auto;
|
||
min-height: 0;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
&__item {
|
||
display: flex;
|
||
gap: 10px;
|
||
align-items: flex-start;
|
||
padding: 10px 12px;
|
||
cursor: pointer;
|
||
border-bottom: 1px solid #ebeef5;
|
||
}
|
||
|
||
&__item:hover,
|
||
&__item.is-active {
|
||
background: #f5f5f5;
|
||
}
|
||
|
||
&__thumb {
|
||
flex: 0 0 48px;
|
||
width: 48px;
|
||
height: 48px;
|
||
object-fit: cover;
|
||
border: 1px solid #ebeef5;
|
||
background: #fafafa;
|
||
}
|
||
|
||
&__body {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
}
|
||
|
||
&__name {
|
||
overflow: hidden;
|
||
color: #303133;
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
line-height: 1.4;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
&__address {
|
||
margin-top: 4px;
|
||
color: #909399;
|
||
font-size: 12px;
|
||
line-height: 1.5;
|
||
word-break: break-all;
|
||
}
|
||
|
||
&__pager {
|
||
display: flex;
|
||
flex: 0 0 auto;
|
||
flex-wrap: wrap;
|
||
gap: 6px;
|
||
align-items: center;
|
||
padding: 8px 10px;
|
||
border-top: 1px solid #ebeef5;
|
||
background: #fff;
|
||
}
|
||
|
||
&__page {
|
||
min-width: 28px;
|
||
height: 28px;
|
||
padding: 0 8px;
|
||
color: #606266;
|
||
font-size: 13px;
|
||
line-height: 26px;
|
||
text-align: center;
|
||
background: #fff;
|
||
border: 1px solid #dcdfe6;
|
||
cursor: pointer;
|
||
|
||
&:hover:not(:disabled) {
|
||
color: #409eff;
|
||
border-color: #409eff;
|
||
}
|
||
|
||
&.is-active {
|
||
color: #409eff;
|
||
border-color: #409eff;
|
||
}
|
||
|
||
&:disabled {
|
||
color: #c0c4cc;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
&--next {
|
||
min-width: 56px;
|
||
}
|
||
}
|
||
}
|
||
</style>
|