爱山东pc端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

315 lines
12 KiB

<template>
<div class="w-full min-h-screen pt-16 pb-7 bg-gradient-to-b from-[#1974ff] to-[#f8faff] to-50%">
<Crumbs :breadcrumbs="[
{ title: '看房', path: '/Showings' },
{ title: '公寓详情', path: '/apartmentDetail', query: { deptId: deptId } },
{ title: '公寓房型', path: '/roomTypeList', query: { apartmentId: deptId } },
{ title: '房型详情', path: '' },
]" :width="1678" />
<div class="w-[1310px] mx-auto mt-10 bg-white pb-9 px-14 pt-6 rounded relative">
<div class="title ">
<h3 class="font-bold text-2xl">房型详情</h3>
</div>
<div class="flex">
<div class="flex-col w-full pt-2 ">
<div class=" pr-10 w-[592px]">
<div class=" w-full relative">
<!-- <div v-if="activeTab === 'video'" class="w-full h-72">
<video :src="houseDetail.videos[0] ? houseDetail.videos[0].url : ''" controls
class="w-full h-full object-cover rounded-md" />
</div> -->
<el-carousel v-if="activeTab === 'img'" height="290px">
<el-carousel-item v-for="(img, idx) in houseDetail.images" :key="idx">
<img :src="img.url" class="w-full h-72 object-cover rounded-md" />
</el-carousel-item>
</el-carousel>
<div v-if="activeTab === 'vr'" class="relative h-[290px]">
<img class="w-full h-[290px] object-cover rounded-md" :src="houseDetail.coverImg" alt="VR封面图" />
<a :href="houseDetail.vrUrl" target="_blank">
<div class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-30 cursor-pointer">
</div>
</a>
</div>
<div
class="mt-4 flex justify-center border rounded-full overflow-hidden w-fit absolute bottom-10 left-1/2 -translate-x-1/2">
<button class="px-4 py-1 text-sm font-medium"
:class="activeTab === 'vr' ? 'bg-blue-500 text-white' : 'bg-white text-gray-800'"
@click="activeTab = 'vr'">
VR
</button>
<button class="px-4 py-1 text-sm font-medium"
:class="activeTab === 'img' ? 'bg-blue-500 text-white' : 'bg-white text-gray-800'"
@click="activeTab = 'img'">
图片
</button>
<!-- <button class="px-4 py-1 text-sm font-medium"
:class="activeTab === 'video' ? 'bg-blue-500 text-white' : 'bg-white text-gray-800'"
@click="activeTab = 'video'">
视频
</button> -->
</div>
<div v-if="activeTab === 'vr'" class=" mt-4 flex justify-center border rounded-full overflow-hidden w-fit
absolute bottom-24 left-1/2 -translate-x-1/2" @click="handleVr">
<img class="opacity-10" src="@/assets/images/ar.png">
</div>
</div>
<div class="pt-3">
<div class="text-xl font-bold ">{{ houseDetail.apartmentName }} I {{ houseDetail.typeName }}</div>
</div>
<div class="pt-3 text-base flex">
<div class=" ">房型:</div>
<div class=" font-bold text-red-400 ">
<span class="">{{ houseDetail.roomCount }}</span>室<span>{{ houseDetail.livingRoomCount
}}</span>厅<span>{{ houseDetail.bathroomCount }}</span>卫
</div>
<div class=" pl-7">面积:</div>
<div class="font-bold text-red-400 ">{{ houseDetail.area }}m²</div>
</div>
<el-divider direction="horizontal" />
<div class="pt-3">
<div class="text-xl font-bold ">房屋设施</div>
</div>
<div class="flex pt-3 flex-wrap gap-2">
<div v-for="(item, index) in houseDetail.facilityOptions" :key="index">
<img class="w-33 h-5 pl-7" style="width: 50px; height: 20px;" :src="item.url" />
<div class="text-center w-20 h-7">{{ item.name }}</div>
</div>
</div>
</div>
</div>
<div class="w-px bg-gray-200 border-dashed h-auto mx-4"></div>
<div class="flex-col w-full justify-between pl-10">
<!-- <div class=" pr-10">
<div>
<div class="text-xl font-bold ">入住评价</div>
</div>
<div class="max-h-[600px] overflow-y-auto pr-2">
<div class="items-start gap-4 py-4 border-gray-200 border-dashed"
:class="{ 'border-b': index !== houseDetail.roomTypes.length - 1 }"
v-for="(item, index) in houseDetail.roomTypes" :key="index">
<div class="flex justify-between w-full">
<div class="flex">
<img class="w-16 h-16 object-cover rounded-full" :src="item.coverImg" alt="封面" />
<div class="flex flex-col pl-3">
<div class="flex flex-wrap items-center text-sm text-gray-600 mt-2 space-x-3">
<div>{{ item.roomTypeName }}</div>
</div>
<div class="text-xs text-gray-500 mt-2 leading-snug">{{ houseDetail.createTime }}</div>
</div>
</div>
<el-rate disabled v-model="starRating" colors="['#13c2c2']" size="large" />
</div>
<div class="flex gap-x-0.5">
<div v-for="(item, index) in houseDetail.facilityIcon" :key="index" class="flex">
<img class="w-28" src="../../assets/images/ewm1.png">
</div>
</div>
</div>
</div>
</div> -->
<div class=" pr-10 ">
<div class="text-xl font-bold">房间详情</div>
<div class="overflow-y-auto max-h-[600px]">
<div class="flex items-start gap-4 py-4 border-gray-200 border-dashed"
:class="{ 'border-b': index !== houseDetail.roomTypes.length - 1 }"
v-for="(item, index) in houseDetail.roomTypes" :key="index">
<!-- 封面图 -->
<img class=" w-44 h-28 object-cover rounded-md" :src="item.images[0].url" alt="封面" />
<!-- 文字信息 -->
<div class="flex flex-col justify-between">
<div class="text-lg font-bold">{{ item.roomTypeName }}</div>
<div class="flex flex-wrap items-center text-sm text-gray-600 mt-2 space-x-3">
<div>{{ item.area }}</div>
<div>{{ item.roomTypeName }}</div>
<div>{{ item.hasWindow ? '有窗' : '无窗' }}</div>
</div>
<div class="text-xs text-gray-900 mt-2 leading-snug">
<div :class="item.isExpanded ? '' : 'line-clamp-2'" class="transition-all duration-300">
{{ item.description }}
</div>
<div v-if="item.description && item.description.length > 50"
class="text-blue-600 cursor-pointer mt-1 hover:text-blue-800 transition-colors"
@click="toggleDescription(item)">
查看
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { getHouseDetail, getDict, getDeptInfo, getHouseTypeList } from "@/api/index";
import { useRouter, useRoute } from 'vue-router';
import { onMounted } from 'vue';
import AMapLoader from "@amap/amap-jsapi-loader";
import Crumbs from '@/components/Crumbs.vue';
const route = useRoute();
const router = useRouter();
const activeTab = ref('vr')
const deptId = route.query.deptId;
const houseId = route.query.id;
const imgList = ref([
'https://example.com/img1.jpg',
'https://example.com/img2.jpg',
'https://example.com/img3.jpg',
])
const houseDetail = ref({}); // 存储房屋详情数据
const residentialDetail = ref({}); // 存储小区详情数据
const dictList = ref([]); // 存储字典数据
const deptInfo = ref({}); // 存储部门信息数据
const getDictTab = ref([])
const getRoomList = ref([])
let map = null;
const starRating = ref(3.7)
const mapContainer = ref(null);
const handerReturn = async () => {
router.go(-1) // 返回上一页
}
const handleVr = () => {
window.open(houseDetail.value.vrUrl, '_blank')
}
// 切换描述展开/收起状态
const toggleDescription = (item) => {
item.isExpanded = !item.isExpanded;
}
const getHouseType = async () => {
try {
console.log(houseId, "sfdjksdlk;");
const parms = {
id: houseId
}
const res = await getHouseDetail(parms);
console.log(res, "sfdjksdlk;");
houseDetail.value = res.data;
// 合并 facilityIcon 和 facilityNames 为数组对象
if (res.data.facilityIcon && res.data.facilityNames) {
houseDetail.value.facilityOptions = res.data.facilityIcon.map((icon, index) => ({
url: icon,
name: res.data.facilityNames[index] || ''
}));
} else {
houseDetail.value.facilityOptions = [];
}
// 这里可以处理res,比如赋值给响应式变量
} catch (error) {
}
};
const getRoom = async () => {
try {
console.log(houseId, "sfdjksdlk;");
const parms = {
apartmentId: deptId
}
const res = await getHouseTypeList(parms);
getRoomList.value = res.data
} catch (error) {
}
};
const getdeptDetails = async () => {
try {
const tagColors = ['primary', 'success', 'info', 'warning', 'danger'];
const parms = {
deptId: deptId
}
const res = await getDeptInfo(parms);
console.log(res, getDictTab.value, "sfdjk111sdlk;");
residentialDetail.value = res.data;
initMap()
residentialDetail.value.labels = res.data.labels.map((item, index) => {
const match = Object.values(getDictTab.value[0]).find(
item2 => item === item2.dictValue
);
return {
label: item,
dictLabel: match ? match.dictLabel : '',
tagType: tagColors[index]
};
});
console.log(residentialDetail.value, "edwfw");
} catch (error) {
console.error("获取房屋详情失败", error);
}
};
const getDictList = async () => {
const res = await getDict({ dictType: "apartment_label" });
getDictTab.value = Object.values(res.rows)
getHouseType();
getdeptDetails();
getRoom();
try {
dict.value = res.rows[0];
} catch (error) { }
};
const initMap = async () => {
try {
const AMap = await AMapLoader.load({
key: import.meta.env.VITE_AMAP_KEY,
version: "2.0",
plugins: ['AMap.Geolocation']
});
map = new AMap.Map(mapContainer.value, {
viewMode: '2D',
zoom: 13,
center: [residentialDetail.value.longtitude, residentialDetail.value.latitude],
});
const geolocation = new AMap.Geolocation({
enableHighAccuracy: true,
timeout: 10000,
buttonPosition: 'RB',
buttonOffset: new AMap.Pixel(10, 20),
zoomToAccuracy: true,
});
map.addControl(geolocation);
geolocation.getCurrentPosition();
geolocation.on('complete', (result) => {
console.log('定位成功', result.position);
map.setCenter(result.position);
});
geolocation.on('error', (error) => {
console.error('定位失败', error);
});
} catch (err) {
console.error('地图加载失败', err);
}
}
onMounted(() => {
getDictList();
});
</script>
<style scoped>
.map-container {
width: 100%;
height: 300px;
}
</style>