20 changed files with 3876 additions and 1863 deletions
File diff suppressed because it is too large
@ -0,0 +1,47 @@ |
|||||
|
import request from '@/utils/http.ts' |
||||
|
/** |
||||
|
* 获取组织树 |
||||
|
* @param params deptName |
||||
|
* |
||||
|
* @returns |
||||
|
*/ |
||||
|
export const getAgencyList = (params: object) => { |
||||
|
return request.get('/system/dept/listForH5', params) |
||||
|
} |
||||
|
/** |
||||
|
* 获取房型 |
||||
|
* @param params apartmentId |
||||
|
* |
||||
|
* @returns |
||||
|
*/ |
||||
|
export const getHouseTypeList = (params: object) => { |
||||
|
return request.get('/asdh5/chooseRoom/getHouseTypeListForH5', params) |
||||
|
} |
||||
|
/** |
||||
|
* 地图右侧列表 |
||||
|
* @param params apartmentId |
||||
|
* |
||||
|
* @returns |
||||
|
*/ |
||||
|
export const getHouseTypeMap = (params: object) => { |
||||
|
return request.get('/mz/choose/list-house-type-with-count', params) |
||||
|
} |
||||
|
/** |
||||
|
* 地图点位 |
||||
|
* @param params apartmentId |
||||
|
* |
||||
|
* @returns |
||||
|
*/ |
||||
|
export const getMapPoint = (params: object) => { |
||||
|
return request.get('/mz/choose/list-house-with-count', params) |
||||
|
} |
||||
|
/** |
||||
|
* 地图点位 |
||||
|
* @param params apartmentId |
||||
|
* |
||||
|
* @returns |
||||
|
*/ |
||||
|
export const getDict = (params: object) => { |
||||
|
return request.get('/system/dict/data/getDict', params) |
||||
|
} |
||||
|
|
@ -0,0 +1,138 @@ |
|||||
|
<template> |
||||
|
<div class="map-container" ref="mapContainer"></div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, onMounted, watch } from "vue"; // 添加watch |
||||
|
import AMapLoader from "@amap/amap-jsapi-loader"; |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
center: { |
||||
|
type: Array, |
||||
|
default: () => [120.287882, 36.178786], |
||||
|
}, |
||||
|
zoom: { |
||||
|
type: Number, |
||||
|
default: 10.5, |
||||
|
}, |
||||
|
//地图点位 |
||||
|
markers: { |
||||
|
type: Array, |
||||
|
default: () => [], |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
const mapContainer = ref(null); |
||||
|
let map = null; |
||||
|
|
||||
|
let markers = []; // 存储当前地图上的marker实例 |
||||
|
|
||||
|
// 清除所有点位 |
||||
|
const clearMarkers = () => { |
||||
|
if (map) { |
||||
|
map.remove(markers); |
||||
|
markers = []; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// 添加点位 |
||||
|
const emit = defineEmits(['marker-click']) // 添加事件发射器 |
||||
|
|
||||
|
const addMarkers = () => { |
||||
|
clearMarkers(); |
||||
|
props.markers.forEach((marker, index) => { |
||||
|
const content = ` |
||||
|
<div style=" |
||||
|
background: ${marker.color || "#3388FF"}; |
||||
|
color: white; |
||||
|
display: inline-flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
font-size: 12px; |
||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.3); |
||||
|
padding: 8px; |
||||
|
border-radius: 15px; |
||||
|
white-space: nowrap; |
||||
|
"> |
||||
|
${marker.name || ""} |
||||
|
<span style=" |
||||
|
background: #ffffff; |
||||
|
color: ${marker.color || "#3388FF"}; |
||||
|
border-radius: 10px; |
||||
|
min-width: 20px; |
||||
|
height: 20px; |
||||
|
display: inline-flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
font-size: 10px; |
||||
|
padding: 0 4px; |
||||
|
margin-left: 4px; |
||||
|
box-sizing: border-box; |
||||
|
font-weight: bold; |
||||
|
">${marker.total || ''}间</span> |
||||
|
</div> |
||||
|
`; |
||||
|
|
||||
|
const amarker = new AMap.Marker({ |
||||
|
position: [marker.longitude, marker.latitude], |
||||
|
content: content, |
||||
|
offset: new AMap.Pixel(-15, -15), |
||||
|
}); |
||||
|
|
||||
|
// 添加点击事件 |
||||
|
amarker.on('click', () => { |
||||
|
emit('marker-click', { |
||||
|
marker, |
||||
|
index, |
||||
|
position: [marker.longitude, marker.latitude] |
||||
|
}) |
||||
|
map.setCenter([marker.longitude, marker.latitude]); |
||||
|
map.setZoom(12); |
||||
|
}); |
||||
|
markers.push(amarker); |
||||
|
map.add(amarker); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
onMounted(async () => { |
||||
|
try { |
||||
|
const AMap = await AMapLoader.load({ |
||||
|
key: import.meta.env.VITE_AMAP_KEY, |
||||
|
version: "2.0", |
||||
|
plugins: ["AMap.ToolBar", "AMap.Scale", "AMap.Marker"], // 添加Marker插件 |
||||
|
}); |
||||
|
|
||||
|
map = new AMap.Map(mapContainer.value, { |
||||
|
viewMode: "2D", |
||||
|
zoom: props.zoom, |
||||
|
center: props.center, |
||||
|
}); |
||||
|
|
||||
|
// 添加控件 |
||||
|
map.addControl(new AMap.ToolBar()); |
||||
|
map.addControl(new AMap.Scale()); |
||||
|
|
||||
|
// 初始添加点位 |
||||
|
addMarkers(); |
||||
|
|
||||
|
// 监听markers变化 |
||||
|
watch( |
||||
|
() => props.markers, |
||||
|
() => { |
||||
|
addMarkers(); |
||||
|
}, |
||||
|
{ deep: true } |
||||
|
); |
||||
|
} catch (error) { |
||||
|
console.error("地图加载失败:", error); |
||||
|
} |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.map-container { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
min-height: 400px; |
||||
|
} |
||||
|
</style> |
@ -1,36 +0,0 @@ |
|||||
<template> |
|
||||
<div class="bg-syGreyBg overflow-hidden"> |
|
||||
<div class="md:w-[1200px] m-auto md:mt-[66px] w-[390px] mt-2"> |
|
||||
<div class="w-[350px] m-auto md:w-[1200px]"> |
|
||||
<div |
|
||||
class="md:w-[86px] mt-8 md:h-[50px] w-[75px] h-[38px] rounded-3xl border border-gray-200 flex justify-center items-center"> |
|
||||
<span class="text-secondary md:text-[18px] text-[14px] font-normal">FAQs</span> |
|
||||
</div> |
|
||||
<div |
|
||||
class="mt-4 md:w-[629px] md:h-[54px] md:text-5xl font-medium md:whitespace-nowrap w-[350px] h-[80px] text-3xl"> |
|
||||
Frequently Asked Questions |
|
||||
</div> |
|
||||
<div class="mt-4 w-full md:text-lg font-normal text-base"> |
|
||||
We understand that you may have some questions about insurance. We have compiled a list of frequently asked |
|
||||
questions to help you get the information you need. If you have any other questions, please do not hesitate to |
|
||||
contact us. |
|
||||
</div> |
|
||||
</div> |
|
||||
<Faqs :type="2" /> |
|
||||
</div> |
|
||||
<!-- footer背景 --> |
|
||||
<FooterBg /> |
|
||||
</div> |
|
||||
</template> |
|
||||
<script setup lang="ts"> |
|
||||
import { useUserStore } from '@/stores/user' |
|
||||
import { getCardList } from '@/api/test' |
|
||||
const store = useUserStore() |
|
||||
const getInfo = async () => { |
|
||||
const res = await getCardList() |
|
||||
console.log(res, store) |
|
||||
} |
|
||||
getInfo() |
|
||||
</script> |
|
||||
|
|
||||
<style scoped></style> |
|
@ -0,0 +1,141 @@ |
|||||
|
<template> |
||||
|
<div class="flex items-center gap-5"> |
||||
|
<el-dropdown trigger="click"> |
||||
|
<span class="el-dropdown-link"> |
||||
|
{{ cityName }}<el-icon class="el-icon--right"><arrow-down /></el-icon> |
||||
|
</span> |
||||
|
<template #dropdown> |
||||
|
<el-dropdown-menu> |
||||
|
<el-dropdown-item |
||||
|
@click="handleCity(item.deptId, item.deptName)" |
||||
|
v-for="(item, index) in cityList" |
||||
|
:label="item.deptName" |
||||
|
:value="item.deptId" |
||||
|
:key="index" |
||||
|
>{{ item.deptName }}</el-dropdown-item |
||||
|
> |
||||
|
</el-dropdown-menu> |
||||
|
</template> |
||||
|
</el-dropdown> |
||||
|
<el-dropdown trigger="click"> |
||||
|
<span class="el-dropdown-link"> |
||||
|
{{ apartmentName |
||||
|
}}<el-icon class="el-icon--right"><arrow-down /></el-icon> |
||||
|
</span> |
||||
|
<template #dropdown> |
||||
|
<el-dropdown-menu> |
||||
|
<el-dropdown-item |
||||
|
v-for="(item, index) in apartmentList" |
||||
|
:label="item.deptName" |
||||
|
:value="item.deptId" |
||||
|
:key="index" |
||||
|
@click="handleApartment(item.deptId, item.deptName)" |
||||
|
>{{ item.deptName }}</el-dropdown-item |
||||
|
> |
||||
|
</el-dropdown-menu> |
||||
|
</template> |
||||
|
</el-dropdown> |
||||
|
<el-dropdown trigger="click"> |
||||
|
<span class="el-dropdown-link"> |
||||
|
{{ houseTypeName |
||||
|
}}<el-icon class="el-icon--right"><arrow-down /></el-icon> |
||||
|
</span> |
||||
|
<template #dropdown> |
||||
|
<el-dropdown-menu> |
||||
|
<el-dropdown-item |
||||
|
v-for="(item, index) in roomTypeList" |
||||
|
:label="item.typeName" |
||||
|
:value="item.id" |
||||
|
:key="index" |
||||
|
@click="handleHouseType(item.id, item.typeName)" |
||||
|
>{{ item.typeName }}</el-dropdown-item |
||||
|
> |
||||
|
</el-dropdown-menu> |
||||
|
</template> |
||||
|
</el-dropdown> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script setup> |
||||
|
import { ref, reactive, onMounted, onUnmounted } from "vue"; |
||||
|
import { getAgencyList, getHouseTypeList } from "@/api/index"; |
||||
|
const emit = defineEmits(["changeAngecy"]); |
||||
|
const props = defineProps({ |
||||
|
deptName: { |
||||
|
// 部门名称 |
||||
|
type: String, // 类型为字符串 |
||||
|
default: "", |
||||
|
}, |
||||
|
}); |
||||
|
const list = ref([]); // 定义列表数据 |
||||
|
const joinIn = reactive({ |
||||
|
// 定义查询参数 |
||||
|
deptName: props.deptName || "青岛市", |
||||
|
}); |
||||
|
const deptId = ref(""); |
||||
|
const cityList = ref([]); // 定义列表数据 |
||||
|
const apartmentList = ref([]); // 定义列表数据 |
||||
|
const roomTypeList = ref([]); // 定义列表数据 |
||||
|
const cityName = ref("请选择"); // 定义列表数据 |
||||
|
const apartmentName = ref("请选择"); // 定义列表数据 |
||||
|
const houseTypeName = ref("请选择"); // 定义列表数据 |
||||
|
const getQIngDaoId = async () => { |
||||
|
// 获取列表数据 |
||||
|
try { |
||||
|
const res = await getAgencyList(joinIn); // 调用接口获取数据 |
||||
|
list.value = res.data; // 赋值给列表数据 |
||||
|
deptId.value = list.value[0].deptId; |
||||
|
getDropdownList("city"); |
||||
|
} catch (err) { |
||||
|
console.error("获取数据失败:", err); // 处理错误 |
||||
|
} |
||||
|
}; |
||||
|
const getDropdownList = async (type) => { |
||||
|
// 获取列表数据 |
||||
|
try { |
||||
|
const res = await getAgencyList({ parentId: deptId.value }); // 调用接口获取数据 |
||||
|
if (type === "city") { |
||||
|
cityList.value = res.data; // 赋值给列表数据 |
||||
|
console.log(cityList.value); |
||||
|
} else if (type === "apartment") { |
||||
|
apartmentList.value = res.data; // 赋值给列表数据 |
||||
|
} |
||||
|
} catch (err) { |
||||
|
console.error("获取数据失败:", err); // 处理错误 |
||||
|
} |
||||
|
}; |
||||
|
const handleCity = (id, name) => { |
||||
|
deptId.value = id; |
||||
|
cityName.value = name; |
||||
|
apartmentList.value = []; // 清空 apartmentList |
||||
|
roomTypeList.value = []; // 清空 roomTypeList |
||||
|
apartmentName.value = "请选择"; // 清空 apartmentName |
||||
|
houseTypeName.value = "请选择"; // 清空 apartmentName |
||||
|
emit("changeAngecy", { id, type: "city" }); |
||||
|
getDropdownList("apartment"); |
||||
|
}; |
||||
|
const handleApartment = (id, name) => { |
||||
|
roomTypeList.value = []; // 清空 roomTypeList |
||||
|
apartmentName.value = name; |
||||
|
deptId.value = id; |
||||
|
houseTypeName.value = "请选择"; // 清空 apartmentName |
||||
|
emit("changeAngecy", { id, type: "apartment" }); |
||||
|
getHouseType(id); |
||||
|
}; |
||||
|
const handleHouseType = (id, name) => { |
||||
|
houseTypeName.value = name; |
||||
|
deptId.value = id; |
||||
|
emit("changeAngecy", { id, type: "houseType" }); |
||||
|
}; |
||||
|
const getHouseType = async (id) => { |
||||
|
try { |
||||
|
const res = await getHouseTypeList({ apartmentId: id }); // 调用接口获取数据 |
||||
|
roomTypeList.value = res.data; // 赋值给列表数据 |
||||
|
} catch (err) { |
||||
|
console.error("获取数据失败:", err); // 处理错误 |
||||
|
} |
||||
|
}; |
||||
|
onMounted(() => { |
||||
|
// 组件挂载时获取数据 |
||||
|
getQIngDaoId(); // 调用获取数据函数 |
||||
|
}); |
||||
|
</script> |
@ -0,0 +1,100 @@ |
|||||
|
<template> |
||||
|
<div class="w-[420px] h-[344px] overflow-y-auto"> |
||||
|
<div>选择房型</div> |
||||
|
<el-divider /> |
||||
|
<div class="flex flex-col"> |
||||
|
<div class="flex gap-5" v-for="(item, index) in list" :key="index"> |
||||
|
<img :src="item.coverImg" alt="" class="w-[140px] h-[100px]" /> |
||||
|
<div class="flex-1 flex flex-col"> |
||||
|
<div class="font-bold">{{ item.name }}</div> |
||||
|
<div>共{{ item.total }}间</div> |
||||
|
<div class="text-gray-400">{{ item.address }}</div> |
||||
|
<div> |
||||
|
<div |
||||
|
v-for="tag in item.labels" |
||||
|
:key="tag" |
||||
|
class="mr-1 mb-1 inline-flex items-center px-2 py-1 rounded text-xs font-medium" |
||||
|
:class="tag === '1' ? 'bule' : tag === '2' ? 'green' : 'yellow'" |
||||
|
> |
||||
|
{{ getLabel(tag) }} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script setup> |
||||
|
import { ref, reactive, onMounted, onUnmounted, watch } from "vue"; |
||||
|
import { getHouseTypeMap, getDict } from "@/api/index"; |
||||
|
const props = defineProps({ |
||||
|
selfObj: { |
||||
|
type: Object, |
||||
|
default: () => { |
||||
|
return {}; |
||||
|
}, |
||||
|
}, |
||||
|
}); // 定义props对象,用于接收外部传入的参数 |
||||
|
const list = ref([]); |
||||
|
const dict = ref({}); |
||||
|
const joinIn = reactive({ |
||||
|
pageNum: 1, |
||||
|
pageSize: 200, |
||||
|
regionCode: "", // 区域 |
||||
|
apartmentId: "", // 公寓 |
||||
|
houseTypeId: "", // 户型 |
||||
|
}); |
||||
|
const getDictList = async () => { |
||||
|
const res = await getDict({ dictType: "apartment_label" }); |
||||
|
try { |
||||
|
dict.value = res.rows[0]; |
||||
|
} catch (error) {} |
||||
|
}; |
||||
|
const getList = async () => { |
||||
|
const res = await getHouseTypeMap(joinIn); |
||||
|
list.value = res.rows; |
||||
|
}; |
||||
|
|
||||
|
getDictList(); |
||||
|
watch( |
||||
|
() => props.selfObj, |
||||
|
(newVal, oldVal) => { |
||||
|
if (newVal.type === "city") { |
||||
|
joinIn.regionCode = newVal.id; |
||||
|
} else if (newVal.type === "apartment") { |
||||
|
joinIn.apartmentId = newVal.id; |
||||
|
} else if (newVal.type === "houseType") { |
||||
|
joinIn.houseTypeId = newVal.id; |
||||
|
} |
||||
|
|
||||
|
getList(); |
||||
|
}, |
||||
|
{ deep: true } |
||||
|
); |
||||
|
getList(); |
||||
|
const getLabel = (tag) => { |
||||
|
// 如果dict.value是对象,需要先转换为数组 |
||||
|
const dictArray = Array.isArray(dict.value) |
||||
|
? dict.value |
||||
|
: Object.values(dict.value); |
||||
|
return dictArray.find((item) => item.dictValue === tag)?.dictLabel || tag; |
||||
|
}; |
||||
|
</script> |
||||
|
<style scoped> |
||||
|
.bule{ |
||||
|
color: #99bbfe; |
||||
|
border:1px solid #99bbfe; |
||||
|
padding: 0 5px; |
||||
|
|
||||
|
} |
||||
|
.green{ |
||||
|
color: #3bcccd; |
||||
|
border:1px solid #3bcccd; |
||||
|
padding: 0 5px; |
||||
|
} |
||||
|
.yellow{ |
||||
|
color: #efca3f; |
||||
|
border:1px solid #efca3f; |
||||
|
padding: 0 5px; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,69 @@ |
|||||
|
<template> |
||||
|
<div class="bg-syGreyBg overflow-hidden"> |
||||
|
<div class="bg-white absolute top-20 left-24 z-20 py-4 px-6 rounded-md"> |
||||
|
<Agency :deptName="deptName" @changeAngecy="changeAngecy" /> |
||||
|
</div> |
||||
|
<Amap :markers="markers" @marker-click="handleMarkerClick" /> |
||||
|
<div class="bg-white absolute bottom-32 right-24 z-20 py-4 px-6 rounded-md"> |
||||
|
<HouseList :selfObj="selfObj" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script setup lang="ts"> |
||||
|
import { ref, reactive, onMounted, onUnmounted } from "vue"; |
||||
|
import Amap from "@/components/AMap.vue"; |
||||
|
import Agency from "./components/Agency.vue"; |
||||
|
import HouseList from "./components/HouseList.vue"; |
||||
|
import { getMapPoint } from "@/api/index"; |
||||
|
const deptName = ref(""); |
||||
|
let selfObj = ref({}); |
||||
|
// 定义标记点数据 |
||||
|
const markers = ref([]); |
||||
|
const deptId = ref(""); |
||||
|
const handleMarkerClick = (event) => { |
||||
|
console.log("点击了标记点:", event); |
||||
|
selfObj.value = { type: "apartment", id: event.marker.id }; |
||||
|
// 先将所有点位恢复默认颜色 |
||||
|
markers.value = markers.value.map((marker) => ({ |
||||
|
...marker, |
||||
|
color: "#3388FF", // 默认颜色 |
||||
|
})); |
||||
|
|
||||
|
// 然后设置当前点击的点位为高亮颜色 |
||||
|
markers.value[event.index].color = "#ff9f00"; |
||||
|
}; |
||||
|
|
||||
|
const getMarkers = async (event) => { |
||||
|
try { |
||||
|
let pamrs = { |
||||
|
pageSize: 200, |
||||
|
pageNum: 1, |
||||
|
regionCode: '', // 区域 |
||||
|
apartmentId: "", // 公寓 |
||||
|
houseTypeId: "", // 户型 |
||||
|
}; |
||||
|
|
||||
|
if (event) { |
||||
|
if (event.type === "city") { |
||||
|
pamrs.regionCode = event.id; |
||||
|
} else if (event.type === "apartment") { |
||||
|
pamrs.apartmentId = event.id; |
||||
|
} else if (event.type === "houseType") { |
||||
|
pamrs.houseTypeId = event.id; |
||||
|
} |
||||
|
} |
||||
|
const res = await getMapPoint(pamrs); |
||||
|
markers.value = res.rows; |
||||
|
console.log(markers, "seeeee"); |
||||
|
} catch (error) { |
||||
|
console.log(error); |
||||
|
} |
||||
|
}; |
||||
|
const changeAngecy = (event) => { |
||||
|
selfObj.value = { type: event.type, id: event.id }; |
||||
|
getMarkers(event); |
||||
|
}; |
||||
|
getMarkers(); |
||||
|
</script> |
||||
|
|
||||
|
<style scoped></style> |
File diff suppressed because it is too large
Loading…
Reference in new issue