公寓详情加收藏和附近学校

This commit is contained in:
A1300399510 2024-04-16 19:12:36 +08:00
parent 3f2f641be0
commit 5a4e6e79cd
8 changed files with 653 additions and 91 deletions

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="item flexflex" @click="goapArtmentDetails"> <div class="item flexflex" @click="goapArtmentDetails">
<div class="collect-box flexcenter" @click.stop="handleCollect1(item)" v-if="false"> <div class="collect-box flexcenter" @click.stop="handleCollect1(item.uniqid)">
<img v-if="item.iscollect == 0" class="collect-icon" style="width: 30px; height: 30px;" src="@/assets/img/apartmentDetail/collecting-shadows.svg" /> <img v-if="item.iscollect == 0" class="collect-icon" style="width: 30px; height: 30px;" src="@/assets/img/apartmentDetail/collecting-shadows.svg" />
<img v-else class="collect-icon" src="@/assets/img/apartmentDetail/collecting-yellow-shadows.svg" /> <img v-else class="collect-icon" src="@/assets/img/apartmentDetail/collecting-yellow-shadows.svg" />
</div> </div>
@ -48,12 +48,16 @@ const props = defineProps({
const emit = defineEmits(["handlecollect"]) const emit = defineEmits(["handlecollect"])
const goapArtmentDetails = () => redirectToExternalWebsite(`/apartmentDetail?uniqid=${props["item"].uniqid}`) const goapArtmentDetails = () => {
let url = `/apartmentDetail?uniqid=${props["item"].uniqid}`
if (props.pitchValue['school']) url += `&school=${props.pitchValue['school']}`
redirectToExternalWebsite(url)
}
// //
const handleCollect1 = item => { const handleCollect1 = uniqid => emit("handlecollect", uniqid)
emit("handlecollect", item)
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -128,7 +128,7 @@ const showPop = () => {
width: 816px; width: 816px;
height: 180px; height: 180px;
margin-top: 20px; margin-top: 20px;
margin-bottom: 40px; // margin-bottom: 40px;
border-radius: 10px; border-radius: 10px;
position: relative; position: relative;
overflow: hidden; overflow: hidden;

View File

@ -42,6 +42,9 @@ export default{
}, },
detailsDistance:(params={})=>{//详情页 - 距离学校距离 detailsDistance:(params={})=>{//详情页 - 距离学校距离
return axios.get('/tenement/pc/api/details/distance',params) return axios.get('/tenement/pc/api/details/distance',params)
},
apartmentCollection:(params={})=>{// 公寓列表 - 收藏
return axios.get('/tenement/pc/api/user/apartmentCollection',params)
} }
} }

View File

@ -21,7 +21,7 @@ axios.interceptors.request.use(
if (config.url != "/tenement/pc/api/user/operation" && !noMask) showFullScreenLoading() if (config.url != "/tenement/pc/api/user/operation" && !noMask) showFullScreenLoading()
// 开发时登录用的,可以直接替换小程序的 authorization // 开发时登录用的,可以直接替换小程序的 authorization
// if (process.env.NODE_ENV == "development") config['headers']['authorization'] = "x2mmnl9grt51bpplj2k6ioiuummzhnw3" // if (process.env.NODE_ENV == "development") config['headers']['authorization'] = "x2mmnl9grt51bpplj2k6ioiuummzhnw3"
if (process.env.NODE_ENV == "development") config["headers"]["authorization"] = "gifqtoiomgb2efu7tcr16kcgs2" if (process.env.NODE_ENV == "development") config["headers"]["authorization"] = "mx25rp0q99x3sis8hidugttty80c5qum"
// 当 noMask == true 和 confing.method == 'get' 时,删除 config.params['noMask'] // 当 noMask == true 和 confing.method == 'get' 时,删除 config.params['noMask']
if (noMask && config.method == "get") delete config.params["noMask"] if (noMask && config.method == "get") delete config.params["noMask"]

View File

@ -1,51 +1,80 @@
function setSeoTitle(title) { function setSeoTitle(title) {
document.title = '港校租房-' + title document.title = "港校租房-" + title
} }
// 跳转 url // 跳转 url
function redirectToExternalWebsite(url) { function redirectToExternalWebsite(url) {
const link = document.createElement('a'); const link = document.createElement("a")
link.href = url; link.href = url
link.target = '_blank'; link.target = "_blank"
link.click(); link.click()
} }
// 跳转登录 // 跳转登录
function goTologin() { function goTologin() {
let url = encodeURIComponent(location.href); let url = encodeURIComponent(location.href)
redirectToExternalWebsite(`https://passport.gter.net/?referer=${url}`); redirectToExternalWebsite(`https://passport.gter.net/?referer=${url}`)
} }
// 复制方法 // 复制方法
function copyToClipboard(text) { function copyToClipboard(text) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const textareaEle = document.createElement("textarea"); const textareaEle = document.createElement("textarea")
document.body.appendChild(textareaEle); document.body.appendChild(textareaEle)
// 2. 将需要复制的文本传入输入框, 并调用 select 方法, 选中输入框中文本 // 2. 将需要复制的文本传入输入框, 并调用 select 方法, 选中输入框中文本
textareaEle.value = text; textareaEle.value = text
textareaEle.select(); textareaEle.select()
textareaEle.readOnly = 'readOnly'; textareaEle.readOnly = "readOnly"
// 3. 调用复制选中文本的方法 // 3. 调用复制选中文本的方法
document.execCommand('copy'); document.execCommand("copy")
// 4. 销毁输入框 // 4. 销毁输入框
document.body.removeChild(textareaEle); document.body.removeChild(textareaEle)
resolve() resolve()
// navigator.clipboard.writeText(text).then(() => { // navigator.clipboard.writeText(text).then(() => {
// resolve() // resolve()
// }).catch((err) => { // }).catch((err) => {
// reject() // reject()
// }); // });
}); })
} }
// 转换 秒数
function secondsToHoursMinutes(seconds, type) {
// 计算小时数
const hours = Math.floor(seconds / 3600)
// 计算剩余的秒数
const remainingSecondsAfterHours = seconds % 3600
// 计算分钟数
const minutes = Math.floor(remainingSecondsAfterHours / 60)
// 计算剩余的秒数
const remainingSeconds = remainingSecondsAfterHours % 60
let text = ""
if (type == "chinese") {
if (hours != 0) text += hours + "小时"
if (minutes != 0) text += minutes + "分钟"
if (remainingSeconds != 0 && minutes == 0) text += remainingSeconds + "秒"
} else {
if (hours != 0) text += hours + "h"
if (minutes != 0) text += minutes + "min"
if (remainingSeconds != 0 && minutes == 0) text += remainingSeconds + "s"
}
return text
}
// 转换 米数
function metersToKilometers(input, type) {
let text = ""
if (input >= 1000) text = (input / 1000).toFixed(1) + (type == "chinese" ? "公里" : "km")
else text = input + (type == "chinese" ? "米" : "m")
return text
}
module.exports = { module.exports = {
setSeoTitle, setSeoTitle,
redirectToExternalWebsite, redirectToExternalWebsite,
goTologin, goTologin,
copyToClipboard, copyToClipboard,
} secondsToHoursMinutes,
metersToKilometers,
}

View File

@ -26,11 +26,11 @@
</el-carousel-item> </el-carousel-item>
</el-carousel> </el-carousel>
<div class="indicate-type flexacenter" v-if="indicateTypeState()"> <div class="indicate-type flexacenter" v-if="indicateTypeState()">
<div class="indicate-item" :class="{pitch: allCarouselsData[carouselIndex]['type'] == 'lives'}" v-if="info['lives'] && info['lives'].length != 0" @click="slideshowType('lives')"> <div class="indicate-item" :class="{ pitch: allCarouselsData[carouselIndex]['type'] == 'lives' }" v-if="info['lives'] && info['lives'].length != 0" @click="slideshowType('lives')">
直播 直播
</div> </div>
<div class="indicate-item" :class="{pitch: allCarouselsData[carouselIndex]['type'] == 'videos'}" v-if="info['videos'] && info['videos'].length != 0" @click="slideshowType('videos')">视频</div> <div class="indicate-item" :class="{ pitch: allCarouselsData[carouselIndex]['type'] == 'videos' }" v-if="info['videos'] && info['videos'].length != 0" @click="slideshowType('videos')">视频</div>
<div class="indicate-item" :class="{pitch: allCarouselsData[carouselIndex]['type'] == 'attachment'}" v-if="info['attachment'] && info['attachment'].length != 0" @click="slideshowType('attachment')">图片</div> <div class="indicate-item" :class="{ pitch: allCarouselsData[carouselIndex]['type'] == 'attachment' }" v-if="info['attachment'] && info['attachment'].length != 0" @click="slideshowType('attachment')">图片</div>
</div> </div>
<div class="indicate" v-if="allCarouselsData.length != 0">{{ carouselIndex - carouselsconfig[allCarouselsData[carouselIndex]["type"]]["index"] + 1 }}/{{ carouselsconfig[allCarouselsData[carouselIndex]["type"]]["amount"] }}</div> <div class="indicate" v-if="allCarouselsData.length != 0">{{ carouselIndex - carouselsconfig[allCarouselsData[carouselIndex]["type"]]["index"] + 1 }}/{{ carouselsconfig[allCarouselsData[carouselIndex]["type"]]["amount"] }}</div>
@ -87,7 +87,7 @@
<div class="operate-box-bj flexcenter"> <div class="operate-box-bj flexcenter">
<div class="operate-box flexacenter" aria-label="详情的导航栏"> <div class="operate-box flexacenter" aria-label="详情的导航栏">
<div class="nav-box flexacenter"> <div class="nav-box flexacenter">
<div class="nav-item flexcenter" :class="{pitch: navTab == item.value}" :aria-label="`${item['name']}-按钮`" v-for="(item, index) in navList" :key="index" @click="handleClickNav(item.value)">{{ item["value"] == "roomEle" ? `${item["name"]} ${roomList.length}` : item["name"] }}</div> <div class="nav-item flexcenter" :class="{ pitch: navTab == item.value }" :aria-label="`${item['name']}-按钮`" v-for="(item, index) in navList" :key="index" @click="handleClickNav(item.value)">{{ item["value"] == "roomEle" ? `${item["name"]} ${roomList.length}` : item["name"] }}</div>
</div> </div>
<div class="btn-box flexacenter"> <div class="btn-box flexacenter">
<div class="btn-item transmit-btn flexcenter" @click="handleTransmit"> <div class="btn-item transmit-btn flexcenter" @click="handleTransmit">
@ -102,7 +102,7 @@
<div class="details-box flexflex"> <div class="details-box flexflex">
<div class="details-left flex1" ref="detailsLeft"> <div class="details-left flex1" ref="detailsLeft">
<!-- 房间类型 --> <!-- 房间类型 -->
<div class="type-box" v-if="roomList.length != 0" ref="roomEle"> <div class="type-box" v-if="roomList.length !== 0" ref="roomEle">
<div class="type-item flexacenter" v-for="(item, index) in roomList" :key="index"> <div class="type-item flexacenter" v-for="(item, index) in roomList" :key="index">
<!-- <img class="type-icon" alt="房间类型-角图片" v-if="item['status'] == 1" src="@/assets/img/apartmentDetail/apartment-have.svg" /> --> <!-- <img class="type-icon" alt="房间类型-角图片" v-if="item['status'] == 1" src="@/assets/img/apartmentDetail/apartment-have.svg" /> -->
<!-- <img class="type-icon" v-else src="@/assets/img/apartmentDetail/apartment-not.svg" /> --> <!-- <img class="type-icon" v-else src="@/assets/img/apartmentDetail/apartment-not.svg" /> -->
@ -166,7 +166,106 @@
<img class="icon" src="@/assets/img/apartmentDetail/location-icon.png" /> <img class="icon" src="@/assets/img/apartmentDetail/location-icon.png" />
{{ info.location || "位置" }} {{ info.location || "位置" }}
</div> </div>
<view-map :latlng="{latitude: info['coordinate'][0], longitude: info['coordinate'][1]}" :name="info['address']"></view-map> <view-map :latlng="{ latitude: info['coordinate'][0], longitude: info['coordinate'][1] }" :name="info['address']"></view-map>
<el-popover :width="814" trigger="click" popper-style="padding: 0" :show-arrow="false" v-model:visible="showDistance">
<template #reference>
<div class="annex-school-box flexacenter">
<div class="annex-left flex1 flexacenter">
<div class="annex-school-item flexflex flex1" @click="selectIndex()" v-if="specialSchoolDistance">
<div class="distance-item-value special flexacenter">
<div class="mileage">{{ specialSchoolDistance.distanceText }}</div>
<img v-if="specialSchoolDistance.toolText == '步行'" class="tool-icon" src="@/assets/img/detail/walk-icon.png" />
<img v-else class="tool-icon" src="@/assets/img/detail/subway-icon.png" />
<div class="tool-time">{{ specialSchoolDistance?.durationText2 }}</div>
</div>
<div class="flexcenter">
<img src="@/assets/img/detail/markIcon.svg" class="marker-icon" alt="" />
</div>
<div class="alias-text flexcenter">{{ specialSchoolDistance.alias || "都大" }}</div>
</div>
<div class="annex-school-item flexflex flex1" v-for="(item, index) in annexSchoolOmit" :key="index" @click="selectIndex(item.id)">
<div class="distance-item-value flexacenter">
<div class="mileage">{{ item.distanceText || "2.0km" }}</div>
<img v-if="!item.list[0].publictransport" class="tool-icon" src="@/assets/img/detail/walk-icon.png" />
<img v-else class="tool-icon" src="@/assets/img/detail/subway-icon.png" />
<div class="tool-time">{{ item.list[0]?.publictransport?.durationText2 || item.list[0]?.durationText2 || "41min" }}</div>
<!-- <div class="tool-time">{{ "41min" }}</div> -->
</div>
<div class="flexcenter">
<img src="@/assets/img/detail/markIcon.svg" class="marker-icon" alt="" />
</div>
<div class="alias-text flexcenter">{{ item.alias || "都大" }}</div>
</div>
<div class="line-img"></div>
</div>
<div class="annex-btn flexcenter">
<img class="annex-btn-bj" src="@/assets/img/detail/infoBtnBg.svg" />
更多
<img class="annex-btn-icon" src="@/assets/img/detail/arrowIcon.svg" />
</div>
</div>
</template>
<div class="distance-info-box pos-r" :style="{ height: `${50 * annexSchoolList.length + 70}px` }">
<div class="title-box dis-f al-item jus-x">
房源
<img class="distance-arrow" src="@/assets/img/detail/arrow-circle-blue.svg" />
院校
<img src="../assets/img/detail/close.png" class="close-icon" @click="showDistance = false" alt="" />
</div>
<div class="distance-info-data dis-f">
<div class="distance-info-left">
<div class="distance-info-left-item flexcenter" :class="{ 'pitch': index == academyPitchIndex }" v-for="(item, index) in annexSchoolList" :key="index" @click="selectAcademyIndex(index)">{{ item.alias }}</div>
</div>
<el-scrollbar :style="{ height: 50 * annexSchoolList.length + 'px' }">
<div class="distance-info-right flex1">
<div class="distance-header-box flexacenter">
<div class="flexacenter">
<div class="distance-header-icon flexcenter">
<img src="@/assets/img/detail/home.png" alt="" class="distance-header-img" />
</div>
{{ targetAcademyPitch.school }}
</div>
<div class="distance-header-hint">本数据来自高德地图仅供参考</div>
</div>
<div class="academy-school-item" v-for="(item, index) in targetAcademyPitch.list" :key="index">
<div class="academy-school-item-header flexacenter">
<div class="academy-school-item-left flexacenter">
<div class="academy-school-item-name">{{ item.title }}</div>
<div class="academy-school-item-number">{{ item.distanceText || "1km" }}</div>
</div>
<div class="academy-school-item-right flexacenter">
<img v-if="item.publictransport" class="academy-school-item-icon" src="@/assets/img/detail/subway-icon.png" mode="widthFix" />
<img v-else class="academy-school-item-icon" src="@/assets/img/detail/walk-icon.png" mode="widthFix" />
<div class="academy-school-item-time">{{ item?.publictransport?.durationText || item.durationText || "1分钟" }}</div>
</div>
<img class="arrow-green" mode="widthFix" src="@/assets/img/detail/arrow-green.svg" />
</div>
<div class="academy-school-item-journey" v-if="item.publictransport">
<div class="journey-item flexacenter" v-for="(item, index) in item.publictransport.segments" :key="index">
<div class="circle"></div>
<!-- 步行 骑行 -->
<div v-if="item.type == 'walking'" class="journey-value flex1">步行{{ item.distanceText }}</div>
<!-- 地铁 -->
<div v-else-if="item.type == 'bus' && item.bustype == '地铁线路'" class="journey-value flex1 subway flexacenter">
<div class="subway-name flexcenter">{{ item.name }}</div>
<div class="flex1" style="white-space: nowrap;">{{ item.via_num }}·{{ item.durationText }}</div>
</div>
<!-- 公交 -->
<div v-else-if="item.type == 'bus' && item.bustype == '普通公交线路'" class="journey-value flex1 bus flexacenter">
<div class="bus-name flexcenter">{{ item.name }}</div>
<div class="flex1" style="white-space: nowrap;">{{ item.via_num }}·{{ item.durationText }}</div>
</div>
</div>
</div>
</div>
</div>
</el-scrollbar>
</div>
</div>
</el-popover>
<!-- 交通 --> <!-- 交通 -->
<div class="traffic-box" v-if="info['traffic']"> <div class="traffic-box" v-if="info['traffic']">
@ -281,7 +380,7 @@
<!-- 添加客服 - 弹窗 --> <!-- 添加客服 - 弹窗 -->
<div class="add-customer-mask flexcenter" v-if="contactReservationState"> <div class="add-customer-mask flexcenter" v-if="contactReservationState">
<div class="add-customer-box flexcenter" :class="{two: customerservicelist.length != 1}"> <div class="add-customer-box flexcenter" :class="{ two: customerservicelist.length != 1 }">
<img class="close" @click="modificationContact" src="@/assets/img/publicImage/circle-close.png" /> <img class="close" @click="modificationContact" src="@/assets/img/publicImage/circle-close.png" />
<img class="add-customer-violet" src="@/assets/img/apartmentDetail/add-customer-violet.svg" /> <img class="add-customer-violet" src="@/assets/img/apartmentDetail/add-customer-violet.svg" />
<img class="add-customer-violet violet2" src="@/assets/img/apartmentDetail/add-customer-violet2.svg" /> <img class="add-customer-violet violet2" src="@/assets/img/apartmentDetail/add-customer-violet2.svg" />
@ -316,9 +415,9 @@
</template> </template>
<script setup> <script setup>
import {ref, onMounted, onUnmounted, toRefs, watch, getCurrentInstance, nextTick} from "vue" import { ref, onMounted, onUnmounted, toRefs, watch, getCurrentInstance, nextTick } from "vue"
import {ElMessage, valueEquals} from "element-plus" import { ElMessage, valueEquals } from "element-plus"
import {useStore} from "vuex" import { useStore } from "vuex"
import pageTopBar from "../components/pageTopBar/pageTopBar.vue" import pageTopBar from "../components/pageTopBar/pageTopBar.vue"
import footerpage from "@/components/footer/footer.vue" import footerpage from "@/components/footer/footer.vue"
@ -328,17 +427,19 @@ import backToTop from "@/components/public/backToTop.vue"
import imageWatch from "@/components/detail/imageWatch.vue" import imageWatch from "@/components/detail/imageWatch.vue"
import phoneqrcode from "@/components/public/phoneQRcode.vue" import phoneqrcode from "@/components/public/phoneQRcode.vue"
import groupqrcode from "@/components/public/group-QRcode.vue" import groupqrcode from "@/components/public/group-QRcode.vue"
import api from "@/utils/api"
import {useRouter, useRoute} from "vue-router" import { useRouter, useRoute } from "vue-router"
let router = useRouter() let router = useRouter()
const route = useRoute() const route = useRoute()
watch(route, () => { watch(route, () => {
uniqid = router.currentRoute.value.query["uniqid"] uniqid = router.currentRoute.value.query["uniqid"]
pitchSchool = router.currentRoute.value.query["school"] || ""
info.value = {} info.value = {}
roomList.value = [] roomList.value = []
carouselsconfig.value = {lives: {}, videos: {}, attachment: {}} carouselsconfig.value = { lives: {}, videos: {}, attachment: {} }
navList.value = [] navList.value = []
navTab.value = "roomEle" navTab.value = "roomEle"
dualBrandList.value = [] dualBrandList.value = []
@ -353,15 +454,16 @@ watch(route, () => {
carouselIndex.value = 0 carouselIndex.value = 0
allCarouselsData.value = [] allCarouselsData.value = []
// mediaBtnstate.value = {} // mediaBtnstate.value = {}
init() init()
distanceSchool()
}) })
let {uniqid} = router.currentRoute.value.query let { uniqid } = router.currentRoute.value.query
let pitchSchool = router.currentRoute.value.school || 0
import {copyToClipboard} from "@/utils/util.js" import { copyToClipboard, metersToKilometers, secondsToHoursMinutes } from "@/utils/util.js"
const {proxy} = getCurrentInstance() const { proxy } = getCurrentInstance()
const store = useStore() const store = useStore()
let imageShow = ref(false) // let imageShow = ref(false) //
@ -399,10 +501,11 @@ let allCarouselsData = ref([])
onMounted(() => { onMounted(() => {
init() init()
distanceSchool()
}) })
const init = () => { const init = () => {
proxy.$get("/tenement/pc/api/apartment/details", {uniqid}).then(res => { proxy.$get("/tenement/pc/api/apartment/details", { uniqid }).then(res => {
if (res.code != 200) { if (res.code != 200) {
ElMessage.error(res["message"]) ElMessage.error(res["message"])
return return
@ -431,8 +534,8 @@ const init = () => {
qrcode.value = data["qrcode"] qrcode.value = data["qrcode"]
handleAllCarouselsData() handleAllCarouselsData()
document.title = data?.info?.title || '港校租房-品牌公寓详情' document.title = data?.info?.title || "港校租房-品牌公寓详情"
nextTick(() => handleNavData()) nextTick(() => handleNavData())
@ -440,11 +543,11 @@ const init = () => {
}) })
} }
let carouselsconfig = ref({lives: {}, videos: {}, attachment: {}}) let carouselsconfig = ref({ lives: {}, videos: {}, attachment: {} })
// tab // tab
const handleAllCarouselsData = () => { const handleAllCarouselsData = () => {
let targetInfo = {...info.value} let targetInfo = { ...info.value }
let accumulativeTotal = 0 // let accumulativeTotal = 0 //
for (const key in carouselsconfig.value) { for (const key in carouselsconfig.value) {
@ -530,13 +633,13 @@ const handleNavData = () => {
// nav // nav
const handleClickNav = value => { const handleClickNav = value => {
let scrollTop = eval(value).value.offsetTop + 136 let scrollTop = eval(value).value.offsetTop + 136
window.scrollTo({top: scrollTop, behavior: "smooth"}) window.scrollTo({ top: scrollTop, behavior: "smooth" })
} }
let dualBrandList = ref([]) // let dualBrandList = ref([]) //
// //
const dualBrandData = () => { const dualBrandData = () => {
proxy.$get("/tenement/pc/api/apartment", {token}).then(res => { proxy.$get("/tenement/pc/api/apartment", { token }).then(res => {
if (res.code != 200) return if (res.code != 200) return
let data = res.data let data = res.data
dualBrandList.value = data.data dualBrandList.value = data.data
@ -670,6 +773,95 @@ const indicateTypeState = () => {
// //
const publicJump = path => router.push(path) const publicJump = path => router.push(path)
//
const distanceSchool = () => {
api.detailsDistance({
uniqid,
istype: 2,
}).then(res => {
const data = res.data
if (res.code != 200) return
let specialSchoolDistanceTarget = null
let academyPitchIndexTarget = 0
const school = pitchSchool || ""
let annexSchoolOmitTarget = []
data.forEach((element, index) => {
element["distanceText"] = metersToKilometers(element.distance)
element.list.forEach(ele => {
ele["durationText"] = secondsToHoursMinutes(ele.duration, "chinese")
ele["durationText2"] = secondsToHoursMinutes(ele.duration)
ele["distanceText"] = metersToKilometers(ele.distance)
if (Object.prototype.toString.call(ele.publictransport) === "[object Object]") {
ele.publictransport["durationText"] = secondsToHoursMinutes(ele?.publictransport?.duration || 0, "chinese")
ele.publictransport["durationText2"] = secondsToHoursMinutes(ele?.publictransport?.duration || 0)
const segments = ele.publictransport["segments"]
if (Array.isArray(segments)) {
segments.forEach(e => {
e["via_num"] = 1 + Math.floor(e.via_num)
e["durationText"] = secondsToHoursMinutes(e.duration)
e["distanceText"] = metersToKilometers(e.distance, "chinese")
})
}
} else ele.publictransport = null
})
if (school == element.id) {
academyPitchIndexTarget = index
const obj = element.list[0] || {}
let toolText = "步行"
if (Object.prototype.toString.call(obj.publictransport) === "[object Object]") toolText = "公交地铁"
specialSchoolDistanceTarget = {
alias: element.alias,
distanceText: obj["distanceText"],
durationText: obj.publictransport?.durationText2 || obj["durationText2"],
toolText,
}
} else annexSchoolOmitTarget.push(element)
})
if (specialSchoolDistanceTarget) annexSchoolOmitTarget = annexSchoolOmitTarget.slice(0, 4)
else annexSchoolOmitTarget = annexSchoolOmitTarget.slice(0, 5)
annexSchoolOmit.value = annexSchoolOmitTarget
annexSchoolList.value = data
targetAcademyPitch.value = data[academyPitchIndexTarget]
specialSchoolDistance.value = specialSchoolDistanceTarget
academyPitchIndex.value = academyPitchIndexTarget
console.log("annexSchoolOmit", annexSchoolOmit)
})
}
let annexSchoolOmit = ref([]) // 7 6
let annexSchoolList = ref([]) //
let academyPitchIndex = ref(0) //
let targetAcademyPitch = ref({}) //
let specialSchoolDistance = ref(null) // school
//
const selectAcademyIndex = index => {
academyPitchIndex.value = index || 0
targetAcademyPitch.value = annexSchoolList.value[academyPitchIndex.value]
}
//
const selectIndex = id => {
if (!id) id = pitchSchool
const data = annexSchoolOmit.value || []
data.forEach((element, index) => {
if (element.id == id) {
academyPitchIndex.value = index || 0
targetAcademyPitch.value = annexSchoolList.value[academyPitchIndex.value]
}
})
// showDistance.value = true
}
//
let showDistance = ref(false)
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@ -1353,6 +1545,7 @@ const publicJump = path => router.push(path)
} }
.traffic-box { .traffic-box {
margin-top: 40px;
padding: 0 30px; padding: 0 30px;
.traffic-title { .traffic-title {
@ -1844,6 +2037,26 @@ a:-webkit-any-link {
} }
</style> </style>
<style lang="less"> <style lang="less">
.dis-f {
display: flex;
}
.jus-x {
justify-content: center;
}
.jus-sp {
justify-content: space-around;
}
.al-item {
align-items: center;
}
.pos-r {
position: relative;
}
.message-info { .message-info {
background: #000000; background: #000000;
border-color: #000000; border-color: #000000;
@ -1857,4 +2070,327 @@ a:-webkit-any-link {
display: none; display: none;
} }
} }
.annex-school-box {
margin: 20px 30px 0;
cursor: pointer;
.annex-left {
width: 100%;
height: 101px;
border: 1px solid #f2f2f2;
border-radius: 12px 0 0 12px;
position: relative;
z-index: 1;
.annex-school-item {
flex-direction: column;
align-items: center;
.distance-item-value {
height: 24px;
padding: 0 8px;
background-color: rgba(246, 246, 246, 1);
border-radius: 29px;
width: fit-content;
&.special {
background: linear-gradient(to right, rgba(255, 255, 255, 0.8) -14%, rgba(80, 227, 194, 0.8) 100%);
}
.mileage {
font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif;
font-weight: 650;
font-size: 14px;
color: #000000;
margin-right: 6px;
}
.tool-icon {
width: 14px;
height: 14px;
margin-right: 3px;
}
.tool-time {
font-size: 13px;
color: #333333;
}
}
}
.marker-icon {
margin: 9px 0 12px;
}
.line-img {
height: 2px;
width: 724px;
background-image: linear-gradient(to right, #d7d7d7 0%, #d7d7d7 50%, transparent 0%);
background-size: 4px 2px;
background-repeat: repeat-x;
position: absolute;
z-index: -1;
}
}
.annex-btn {
width: 90px;
height: 101px;
font-size: 14px;
color: #000000;
border-radius: 0 12px 12px 0;
position: relative;
z-index: 1;
.annex-btn-bj {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: -1;
}
.annex-btn-icon {
width: 16px;
height: 16px;
margin-left: 10px;
}
}
}
.distance-info-box {
.title-box {
font-weight: 650;
font-size: 20px;
color: #000000;
height: 70px;
border-bottom: 1px solid #ebebeb;
border-radius: 16px 16px 0 0;
.distance-arrow {
width: 24px;
height: 24px;
margin: 0 28px;
}
.close-icon {
width: 16px;
height: 16px;
position: absolute;
top: 20px;
right: 20px;
cursor: pointer;
}
}
.distance-info-data {
.distance-info-left {
width: 70px;
flex-direction: column;
border-right: 1px solid #ebebeb;
box-sizing: content-box;
.distance-info-left-item {
width: 100%;
height: 50px;
font-size: 14px;
color: #555555;
cursor: pointer;
&.pitch {
font-weight: 650;
color: #000000;
background: linear-gradient(to right, rgba(255, 255, 255, 0.8) -14%, rgba(80, 227, 194, 0.8) 100%);
}
&:last-of-type {
border-radius: 0 0 0 10px;
}
}
}
.distance-info-right {
padding: 30px 40px;
.distance-header-box {
color: #333333;
font-weight: 650;
font-size: 16px;
margin-bottom: 30px;
justify-content: space-between;
.distance-header-icon {
width: 30px;
height: 30px;
background-color: #fddf6d;
border-radius: 50%;
margin-right: 10px;
.distance-header-img {
width: 20px;
height: 20px;
}
}
.distance-header-hint {
color: #a09e9e;
font-size: 13px;
font-weight: 400;
}
}
.academy-school-item {
background-color: rgba(246, 246, 246, 1);
border-radius: 12px;
margin-bottom: 30px;
}
.academy-school-item-header {
font-size: 16px;
width: 670px;
height: 65px;
justify-content: space-between;
padding-left: 22px;
padding-right: 20px;
position: relative;
}
.academy-school-item-header .arrow-green {
width: 7px;
height: 12px;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}
.academy-school-item-name {
font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif;
font-weight: 650;
color: #000000;
}
.academy-school-item-number {
color: rgb(51, 51, 51);
margin-left: 4px;
font-weight: 400;
font-family: "ArialMT", "Arial", sans-serif;
}
.academy-school-item-icon {
width: 16px;
height: 16px;
margin-right: 6px;
}
.academy-school-item-time {
color: #000;
font-weight: 650;
font-size: 14px;
}
.academy-school-item-journey {
border-top: 1px solid #ebebeb;
padding-top: 22px;
padding-left: 22px;
padding-bottom: 30px;
position: relative;
}
.journey-item {
position: relative;
z-index: 1;
}
.journey-item:not(:last-of-type) {
margin-bottom: 20px;
}
.academy-school-item-journey::after {
content: "";
position: absolute;
top: 0;
left: 26.4px;
width: 1px;
height: 100%;
display: block;
background-image: linear-gradient(to bottom, #aaaaaa 50%, transparent 50%);
background-size: 1px 4px; /* 控制虚线的宽度和间距 */
}
.journey-item:first-of-type::after {
content: "";
display: block;
position: absolute;
top: -22px;
left: 0;
width: 9px;
height: calc(50% + 22px);
background-color: rgba(246, 246, 246, 1);
}
.journey-item:last-of-type::after {
content: "";
display: block;
position: absolute;
bottom: -30px;
left: 0;
width: 9px;
height: calc(50% + 30px);
background-color: rgba(246, 246, 246, 1);
}
.journey-item .circle {
width: 9px;
height: 9px;
border-radius: 50%;
background-color: #f6f6f6;
border: 1px solid #797979;
box-sizing: border-box;
margin-right: 20px;
z-index: 1;
}
.journey-item .journey-value {
color: #333;
font-size: 13px;
padding-right: 20px;
}
.journey-item .journey-value.subway {
color: #aaaaaa;
}
.journey-item .journey-value.subway .subway-name {
padding: 3.5px 11px;
background-color: rgba(51, 51, 51, 1);
border-radius: 10px;
color: #fff;
margin-right: 10px;
}
.journey-item .journey-value.bus {
color: #aaaaaa;
}
.journey-item .journey-value.bus .bus-name {
padding: 3.5px 11px;
background-color: rgba(80, 227, 194, 0);
box-sizing: border-box;
border: 1px solid rgba(51, 51, 51, 1);
border-radius: 10px;
margin-right: 10px;
color: #333333;
}
.academy-school-hint {
color: #a09e9e;
font-size: 13px;
margin-bottom: 20px;
}
}
}
}
.el-popper.is-light {
border-radius: 10px !important;
}
</style> </style>

View File

@ -295,7 +295,7 @@
<span class="title">{{ location && location[housingInfo["data"] && housingInfo["data"]["info"].location.substring(0, 1)] }} > {{ location && location[housingInfo["data"] && housingInfo["data"]["info"].location] }}</span> <span class="title">{{ location && location[housingInfo["data"] && housingInfo["data"]["info"].location.substring(0, 1)] }} > {{ location && location[housingInfo["data"] && housingInfo["data"]["info"].location] }}</span>
</div> </div>
<div class="dis-f jus-x" style="margin-top: 15px;" v-if="housingInfo['data'] && housingInfo['data'].info.latitude"> <div class="dis-f jus-x" style="margin-top: 15px;" v-if="housingInfo['data'] && housingInfo['data'].info.latitude">
<div> <div style="margin-bottom: 20px;">
<mapInfo <mapInfo
:latlng="{ :latlng="{
longitude: housingInfo['data'].info.longitude * 1, longitude: housingInfo['data'].info.longitude * 1,
@ -356,7 +356,6 @@
</div> </div>
</div> </div>
</template> </template>
<!-- <div class="distance-info-box pos-r" :class="{ 'show-distance-info-box': showDistance }" :style="{ height: showDistance ? `${50 * annexSchoolList.length + 70}px` : '0px' }"> -->
<div class="distance-info-box pos-r" :style="{ height: `${50 * annexSchoolList.length + 70}px` }"> <div class="distance-info-box pos-r" :style="{ height: `${50 * annexSchoolList.length + 70}px` }">
<div class="title-box dis-f al-item jus-x"> <div class="title-box dis-f al-item jus-x">
房源 房源
@ -368,7 +367,7 @@
<div class="distance-info-left"> <div class="distance-info-left">
<div class="distance-info-left-item flexcenter" :class="{ 'pitch': index == academyPitchIndex }" v-for="(item, index) in annexSchoolList" :key="index" @click="selectAcademyIndex(index)">{{ item.alias }}</div> <div class="distance-info-left-item flexcenter" :class="{ 'pitch': index == academyPitchIndex }" v-for="(item, index) in annexSchoolList" :key="index" @click="selectAcademyIndex(index)">{{ item.alias }}</div>
</div> </div>
<el-scrollbar v-if="distanceList.length > 0" :style="{ height: 50 * annexSchoolList.length + 'px' }"> <el-scrollbar :style="{ height: 50 * annexSchoolList.length + 'px' }">
<div class="distance-info-right flex1"> <div class="distance-info-right flex1">
<div class="distance-header-box flexacenter"> <div class="distance-header-box flexacenter">
<div class="flexacenter"> <div class="flexacenter">
@ -804,6 +803,8 @@ import report from "@/components/public/report.vue"
import store from "@/store" import store from "@/store"
import { metersToKilometers, secondsToHoursMinutes } from "@/utils/util.js"
// //
let pageType = ref("") let pageType = ref("")
@ -1250,6 +1251,7 @@ onBeforeUnmount(() => {
const distanceSchool = () => { const distanceSchool = () => {
api.detailsDistance({ api.detailsDistance({
uniqid: uniqid.value, uniqid: uniqid.value,
istype: 1
}).then(res => { }).then(res => {
const data = res.data const data = res.data
if (res.code != 200) return if (res.code != 200) return
@ -1329,37 +1331,6 @@ const selectIndex = id => {
// showDistance.value = true // showDistance.value = true
} }
//
const secondsToHoursMinutes = (seconds, type) => {
//
const hours = Math.floor(seconds / 3600)
//
const remainingSecondsAfterHours = seconds % 3600
//
const minutes = Math.floor(remainingSecondsAfterHours / 60)
//
const remainingSeconds = remainingSecondsAfterHours % 60
let text = ""
if (type == "chinese") {
if (hours != 0) text += hours + "小时"
if (minutes != 0) text += minutes + "分钟"
if (remainingSeconds != 0 && minutes == 0) text += remainingSeconds + "秒"
} else {
if (hours != 0) text += hours + "h"
if (minutes != 0) text += minutes + "min"
if (remainingSeconds != 0 && minutes == 0) text += remainingSeconds + "s"
}
return text
}
//
const metersToKilometers = (input, type) => {
let text = ""
if (input >= 1000) text = (input / 1000).toFixed(1) + (type == "chinese" ? "公里" : "km")
else text = input + (type == "chinese" ? "米" : "m")
return text
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
img { img {
@ -2787,7 +2758,7 @@ img {
border-style: solid; border-style: solid;
border-color: rgba(242, 242, 242, 1); border-color: rgba(242, 242, 242, 1);
border-radius: 12px; border-radius: 12px;
margin-top: 20px; // margin-top: 20px;
cursor: pointer; cursor: pointer;
position: relative; position: relative;
/* ::-webkit-scrollbar { /* ::-webkit-scrollbar {
@ -2996,6 +2967,10 @@ img {
color: #000000; color: #000000;
background: linear-gradient(to right, rgba(255, 255, 255, 0.8) -14%, rgba(80, 227, 194, 0.8) 100%); background: linear-gradient(to right, rgba(255, 255, 255, 0.8) -14%, rgba(80, 227, 194, 0.8) 100%);
} }
&:last-of-type {
border-radius: 0 0 0 10px;
}
} }
} }

View File

@ -50,6 +50,7 @@ import { useRoute, useRouter } from "vue-router"
import backToTop from "@/components/public/backToTop.vue" import backToTop from "@/components/public/backToTop.vue"
import store from "../../store/index" import store from "../../store/index"
import api from "../../utils/api" import api from "../../utils/api"
import { ElMessage } from "element-plus"
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
@ -214,13 +215,27 @@ const getMoreScroll = () => {
} }
// //
const handlecollect = item => { const handlecollect = uniqid => {
console.log("item", item) console.log("uniqid", uniqid)
const targetData = JSON.parse(JSON.stringify(list.value)) let targetData = {}
console.log("targetData", targetData); let targetIndex = 0
targetData.forEach(element => { let token = ""
console.log();
}); list.value.forEach((element, index) => {
if (element.uniqid == uniqid) {
targetData = element
targetIndex = index
token = element.token || ""
}
})
api.apartmentCollection({ token }).then(res => {
if (res.code != 200) return
const data = res.data
console.log("data", data)
list.value[targetIndex]["iscollect"] = data.status
ElMessage.success(res.message)
})
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>