buddhism/pages/memorial/compositons/floorSelector.vue
2025-08-08 15:37:47 +08:00

380 lines
8.0 KiB
Vue

<template>
<view class="floor-selector">
<!-- 楼层选择 -->
<view class="floor-section">
<text class="section-label">楼层:</text>
<view class="floor-buttons">
<view
v-for="floor in floors"
:key="floor.id"
class="floor-btn"
:class="{ active: selectedFloor && selectedFloor.id === floor.id }"
@click="selectFloor(floor)"
>
{{ floor.label }}
</view>
</view>
</view>
<!-- 分隔线 -->
<view class="divider"></view>
<view class="content-section">
<!-- 区域选择 -->
<view class="area-section">
<view
v-for="area in areas"
:key="area.id"
class="area-btn"
:class="{ active: selectedArea && selectedArea.id === area.id }"
@click="selectArea(area)"
>
{{ area.label }}
</view>
</view>
<!-- 分隔线 -->
<view class="vertical-divider"></view>
<!-- 单元选择 -->
<view class="unit-section">
<view class="unit-grid">
<view
v-for="unit in units"
:key="unit.id"
class="unit-btn"
:class="{ active: selectedUnit && selectedUnit.id === unit.id }"
@click="selectUnit(unit)"
>
{{ unit.label }}
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { getMemorialTree } from '@/api/memorial/index.js'
export default {
name: 'FloorSelector',
props: {
// 默认选中的楼层ID
defaultFloorId: {
type: String,
default: ''
},
// 默认选中的区域ID
defaultAreaId: {
type: String,
default: ''
},
// 默认选中的单元ID
defaultUnitId: {
type: String,
default: ''
}
},
data() {
return {
treeData: [],
selectedFloor: null,
selectedArea: null,
selectedUnit: null,
loading: false
}
},
computed: {
// 楼层列表
floors() {
if (!this.treeData.length) return []
const memorial = this.treeData[0]
return memorial && memorial.children ? memorial.children : []
},
// 当前选中楼层的区域列表
areas() {
if (!this.selectedFloor) return []
return this.selectedFloor.children ? this.selectedFloor.children : []
},
// 当前选中区域的单元列表
units() {
if (!this.selectedArea) return []
return this.selectedArea.children ? this.selectedArea.children : []
}
},
watch: {
// 监听选中变化,向父组件发送事件
selectedUnit: {
handler(newUnit) {
this.$emit('selection-change', {
floor: this.selectedFloor,
area: this.selectedArea,
unit: newUnit
})
},
deep: true
}
},
mounted() {
this.loadTreeData()
},
methods: {
// 加载树形数据
async loadTreeData() {
this.loading = true
try {
const response = await getMemorialTree()
console.log('楼层树形数据:', response)
if (response && response.code === 200) {
this.treeData = response.data || []
// 设置默认选中项
this.setDefaultSelection()
} else {
console.error('获取楼层数据失败:', response)
uni.showToast({
title: '获取楼层数据失败',
icon: 'none'
})
}
} catch (error) {
console.error('加载楼层数据失败:', error)
uni.showToast({
title: '网络异常,请稍后重试',
icon: 'none'
})
} finally {
this.loading = false
}
},
// 设置默认选中项
setDefaultSelection() {
// 设置默认楼层
if (this.defaultFloorId) {
const floor = this.floors.find(f => f.id === this.defaultFloorId)
if (floor) {
this.selectFloor(floor)
}
} else if (this.floors.length > 0) {
// 默认选中第一个楼层
this.selectFloor(this.floors[0])
}
// 设置默认区域
if (this.defaultAreaId && this.selectedFloor) {
const area = this.areas.find(a => a.id === this.defaultAreaId)
if (area) {
this.selectArea(area)
}
} else if (this.areas.length > 0) {
// 默认选中第一个区域
this.selectArea(this.areas[0])
}
// 设置默认单元
if (this.defaultUnitId && this.selectedArea) {
const unit = this.units.find(u => u.id === this.defaultUnitId)
if (unit) {
this.selectUnit(unit)
}
} else if (this.units.length > 0) {
// 默认选中第一个单元
this.selectUnit(this.units[0])
}
},
// 选择楼层
selectFloor(floor) {
this.selectedFloor = floor
this.selectedArea = null
this.selectedUnit = null
// 自动选中第一个区域
if (this.areas.length > 0) {
this.selectArea(this.areas[0])
}
},
// 选择区域
selectArea(area) {
this.selectedArea = area
this.selectedUnit = null
// 自动选中第一个单元
if (this.units.length > 0) {
this.selectUnit(this.units[0])
}
},
// 选择单元
selectUnit(unit) {
this.selectedUnit = unit
},
// 获取当前选中信息
getCurrentSelection() {
return {
floor: this.selectedFloor,
area: this.selectedArea,
unit: this.selectedUnit
}
},
// 重置选择
resetSelection() {
this.selectedFloor = null
this.selectedArea = null
this.selectedUnit = null
this.setDefaultSelection()
}
}
}
</script>
<style lang="scss" scoped>
.floor-selector {
padding: 42rpx 44rpx 30rpx 44rpx;
width: 750rpx;
background-color: #FFFBF5;
border-radius: 38rpx;
box-sizing: border-box;
}
.floor-section {
display: flex;
align-items: center;
margin-bottom: 26rpx;
//border:1rpx solid #613613;
}
.section-label {
margin-right: 10rpx;
width: 96rpx;
height: 44rpx;
font-weight: 400;
font-size: 32rpx;
color: #3D3D3D;
line-height: 44rpx;
text-align: left;
}
.floor-buttons {
display: flex;
gap: 20rpx;
}
.floor-btn {
padding: 4rpx 49rpx;
color: #A24242;
border-radius: 8rpx;
font-size: 28rpx;
cursor: pointer;
transition: all 0.3s ease;
width: 134rpx;
height: 52rpx;
background: #FFF1DD;
border: 1rpx solid #A24242;
&.active {
background-color: #A24242;
color: #FFF1DD;
}
}
.divider {
height: 1rpx;
background: repeating-linear-gradient(
to right,
#A24242 0,
#A24242 8rpx,
transparent 8rpx,
transparent 16rpx
);
margin: 26rpx 0 30rpx 0;
}
.content-section {
display: flex;
height: calc(100% - 120rpx);
}
.area-section {
width: 180rpx;
display: flex;
flex-direction: column;
gap: 16rpx;
//border: 1rpx solid #f414fb;
}
.area-btn {
padding: 4rpx 40rpx;
color: #A24242;
border-radius: 8rpx;
font-size: 28rpx;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
box-sizing: border-box;
width: 134rpx;
height: 52rpx;
background: #FFF1DD;
border: 1rpx solid #A24242;
&.active {
background-color: #A24242;
color: #FFF1DD;
}
}
.vertical-divider {
width: 1rpx;
background: repeating-linear-gradient(
to bottom,
#C7A26D 0,
#C7A26D 4rpx,
transparent 4rpx,
transparent 8rpx
);
margin: 0 48rpx 0 0;
}
.unit-section {
//border: 1rpx solid #f47fef;
flex: 1;
margin-top: 34rpx;
}
.unit-grid {
//border: 1rpx solid #f47fef;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16rpx;
}
.unit-btn {
padding: 16rpx 12rpx;
color: #A24242;
border-radius: 8rpx;
font-size: 28rpx;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
width: 134rpx;
height: 52rpx;
background: #FFF1DD;
border: 1rpx solid #A24242;
&.active {
background-color: #A24242;
color: #FFF1DD;
border-color: #A24242;
}
}
</style>