百度地图修改
This commit is contained in:
parent
af33236f56
commit
b332137dc3
|
|
@ -65,6 +65,79 @@
|
|||
.tree-children { margin-top: 2px; display: none; }
|
||||
.tree-children.expanded { display: block; }
|
||||
|
||||
/* 全选/全不选按钮 */
|
||||
.tree-select-all {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
padding: 10px 0;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.tree-select-btn {
|
||||
flex: 1;
|
||||
padding: 6px 12px;
|
||||
font-size: 13px;
|
||||
background: rgba(0, 45, 182, 0.8);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
.tree-select-btn:hover {
|
||||
background: rgba(0, 45, 182, 1);
|
||||
}
|
||||
|
||||
/* 工程列表面板 */
|
||||
.project-list-panel {
|
||||
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
|
||||
z-index: 999; display: flex; pointer-events: none; align-items: flex-start;
|
||||
}
|
||||
|
||||
.project-list-container {
|
||||
width: 300px; height: auto; max-height: 80vh;
|
||||
margin: 5% 0 0 2%;
|
||||
background: rgba(30, 30, 30, 0.85);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 8px;
|
||||
overflow-y: auto; overflow-x: hidden;
|
||||
padding: 20px;
|
||||
pointer-events: auto;
|
||||
backdrop-filter: blur(5px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.project-list-container::-webkit-scrollbar { width: 6px; }
|
||||
.project-list-container::-webkit-scrollbar-track { background: rgba(255, 255, 255, 0.05); border-radius: 3px; }
|
||||
.project-list-container::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.3); border-radius: 3px; }
|
||||
.project-list-container::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.5); }
|
||||
|
||||
.project-list-item {
|
||||
display: flex; align-items: center; padding: 6px 8px;
|
||||
cursor: pointer; border-radius: 4px; transition: background-color 0.2s;
|
||||
min-height: 28px; margin-bottom: 2px;
|
||||
}
|
||||
.project-list-item:hover { background-color: rgba(255, 255, 255, 0.1); }
|
||||
|
||||
.project-list-radio {
|
||||
width: 16px; height: 16px; margin-right: 8px; cursor: pointer;
|
||||
accent-color: #002db6;
|
||||
}
|
||||
|
||||
.project-list-label {
|
||||
flex: 1; font-size: 14px; user-select: none;
|
||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.project-list-enter-btn {
|
||||
padding: 4px 12px; font-size: 12px; background: rgba(0, 45, 182, 0.8);
|
||||
color: #fff; border: none; border-radius: 4px; cursor: pointer;
|
||||
transition: background-color 0.2s; margin-left: 8px;
|
||||
}
|
||||
.project-list-enter-btn:hover { background: rgba(0, 45, 182, 1); }
|
||||
|
||||
.model-preview-close {
|
||||
position: absolute; top: 50px; right: 20px;
|
||||
width: 40px; height: 40px;
|
||||
|
|
@ -79,6 +152,22 @@
|
|||
}
|
||||
.model-preview-close::after { transform: rotate(-45deg); }
|
||||
|
||||
/* AR 按钮 */
|
||||
.model-preview-ar {
|
||||
position: absolute; top: 100px; right: 20px;
|
||||
width: 40px; height: 40px;
|
||||
background: rgba(0, 45, 182, 0.95);
|
||||
border-radius: 50%; display: flex; align-items: center; justify-content: center;
|
||||
cursor: pointer; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1001; pointer-events: auto;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
.model-preview-ar:hover {
|
||||
background: rgba(0, 45, 182, 1);
|
||||
}
|
||||
|
||||
/* 地图 Label 样式 - 提取至 CSS */
|
||||
.map-project-label {
|
||||
color: #002db6 !important;
|
||||
|
|
@ -123,11 +212,23 @@
|
|||
<body>
|
||||
<div id="map-container"></div>
|
||||
|
||||
<!-- 工程列表面板 -->
|
||||
<div id="project-list-panel" class="project-list-panel">
|
||||
<div class="project-list-container">
|
||||
<div id="project-list-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="model-preview-panel" class="model-preview-panel" style="display: none;">
|
||||
<div class="model-preview-tree">
|
||||
<div class="tree-select-all">
|
||||
<button class="tree-select-btn" id="select-all-btn">全选</button>
|
||||
<button class="tree-select-btn" id="deselect-all-btn">全不选</button>
|
||||
</div>
|
||||
<div id="tree-container"></div>
|
||||
</div>
|
||||
<div class="model-preview-close" id="close-preview-btn"></div>
|
||||
<div class="model-preview-ar" id="ar-btn">AR</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
|
@ -263,12 +364,14 @@
|
|||
projectInfo: [],
|
||||
currentClickedProject: null,
|
||||
modelList: [],
|
||||
checkedNodeIds: []
|
||||
checkedNodeIds: [],
|
||||
selectedProjectId: null
|
||||
},
|
||||
elements: {
|
||||
panel: null,
|
||||
tree: null,
|
||||
closeBtn: null
|
||||
closeBtn: null,
|
||||
projectListContainer: null
|
||||
},
|
||||
|
||||
init() {
|
||||
|
|
@ -287,6 +390,9 @@
|
|||
// 初始化地图
|
||||
this.initMap(this.state.projectInfo);
|
||||
|
||||
// 渲染工程列表
|
||||
this.renderProjectList();
|
||||
|
||||
// 处理 URL Action
|
||||
this.handleUrlActions(params);
|
||||
},
|
||||
|
|
@ -295,6 +401,10 @@
|
|||
this.elements.panel = document.getElementById('model-preview-panel');
|
||||
this.elements.tree = document.getElementById('tree-container');
|
||||
this.elements.closeBtn = document.getElementById('close-preview-btn');
|
||||
this.elements.projectListContainer = document.getElementById('project-list-container');
|
||||
this.elements.selectAllBtn = document.getElementById('select-all-btn');
|
||||
this.elements.deselectAllBtn = document.getElementById('deselect-all-btn');
|
||||
this.elements.arBtn = document.getElementById('ar-btn');
|
||||
},
|
||||
|
||||
bindEvents() {
|
||||
|
|
@ -302,6 +412,21 @@
|
|||
this.elements.closeBtn.addEventListener('click', () => this.closePreview());
|
||||
}
|
||||
|
||||
// AR 按钮
|
||||
if (this.elements.arBtn) {
|
||||
this.elements.arBtn.addEventListener('click', () => this.navigateToAR());
|
||||
}
|
||||
|
||||
// 全选按钮
|
||||
if (this.elements.selectAllBtn) {
|
||||
this.elements.selectAllBtn.addEventListener('click', () => this.selectAllNodes());
|
||||
}
|
||||
|
||||
// 全不选按钮
|
||||
if (this.elements.deselectAllBtn) {
|
||||
this.elements.deselectAllBtn.addEventListener('click', () => this.deselectAllNodes());
|
||||
}
|
||||
|
||||
// 监听 postMessage
|
||||
window.addEventListener('message', (e) => {
|
||||
const data = e.data;
|
||||
|
|
@ -360,6 +485,111 @@
|
|||
});
|
||||
},
|
||||
|
||||
renderProjectList() {
|
||||
if (!this.elements.projectListContainer) return;
|
||||
|
||||
const projectInfo = this.state.projectInfo || [];
|
||||
if (projectInfo.length === 0) {
|
||||
this.elements.projectListContainer.innerHTML = '<div style="color:#aaa;text-align:center;padding:20px;">暂无工程数据</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
projectInfo.forEach((project, index) => {
|
||||
const projectId = project.id || `project-${index}`;
|
||||
const itemDiv = document.createElement('div');
|
||||
itemDiv.className = 'project-list-item';
|
||||
itemDiv.dataset.projectId = projectId;
|
||||
|
||||
// 单选框
|
||||
const radio = document.createElement('input');
|
||||
radio.type = 'radio';
|
||||
radio.name = 'project-radio';
|
||||
radio.className = 'project-list-radio';
|
||||
radio.checked = this.state.selectedProjectId === projectId;
|
||||
|
||||
// 工程名称标签
|
||||
const label = document.createElement('span');
|
||||
label.className = 'project-list-label';
|
||||
label.textContent = `${project.proName || '未命名工程'} (${project.declination || ''})`;
|
||||
|
||||
// 进入按钮
|
||||
const enterBtn = document.createElement('button');
|
||||
enterBtn.className = 'project-list-enter-btn';
|
||||
enterBtn.textContent = '预览';
|
||||
// 只有选中时才显示进入按钮
|
||||
enterBtn.style.display = radio.checked ? 'block' : 'none';
|
||||
|
||||
itemDiv.appendChild(radio);
|
||||
itemDiv.appendChild(label);
|
||||
itemDiv.appendChild(enterBtn);
|
||||
|
||||
// 点击工程项:选中单选框并定位
|
||||
itemDiv.addEventListener('click', (e) => {
|
||||
// 如果点击的是按钮,不触发定位
|
||||
if (e.target === enterBtn) return;
|
||||
|
||||
// 选中单选框
|
||||
const projectId = project.id || `project-${index}`;
|
||||
radio.checked = true;
|
||||
this.state.selectedProjectId = projectId;
|
||||
|
||||
// 更新所有单选框状态和进入按钮显示状态
|
||||
this.updateProjectRadioStates();
|
||||
this.updateEnterButtonsVisibility();
|
||||
|
||||
// 定位到该工程坐标
|
||||
if (project.lng && project.lat) {
|
||||
const point = new BMapGL.Point(project.lng, project.lat);
|
||||
this.map.centerAndZoom(point, 15);
|
||||
}
|
||||
});
|
||||
|
||||
// 单选框变化事件
|
||||
radio.addEventListener('change', () => {
|
||||
if (radio.checked) {
|
||||
this.state.selectedProjectId = projectId;
|
||||
this.updateProjectRadioStates();
|
||||
this.updateEnterButtonsVisibility();
|
||||
}
|
||||
});
|
||||
|
||||
// 点击跳转按钮 - 直接进入模型预览
|
||||
enterBtn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
// 设置当前点击的工程
|
||||
this.state.currentClickedProject = project;
|
||||
// 直接触发模型预览
|
||||
this.triggerPreview(project);
|
||||
});
|
||||
|
||||
fragment.appendChild(itemDiv);
|
||||
});
|
||||
|
||||
this.elements.projectListContainer.innerHTML = '';
|
||||
this.elements.projectListContainer.appendChild(fragment);
|
||||
},
|
||||
|
||||
updateProjectRadioStates() {
|
||||
const radios = this.elements.projectListContainer.querySelectorAll('.project-list-radio');
|
||||
radios.forEach(radio => {
|
||||
const item = radio.closest('.project-list-item');
|
||||
const projectId = item ? item.dataset.projectId : null;
|
||||
radio.checked = this.state.selectedProjectId === projectId;
|
||||
});
|
||||
},
|
||||
|
||||
updateEnterButtonsVisibility() {
|
||||
const items = this.elements.projectListContainer.querySelectorAll('.project-list-item');
|
||||
items.forEach(item => {
|
||||
const radio = item.querySelector('.project-list-radio');
|
||||
const enterBtn = item.querySelector('.project-list-enter-btn');
|
||||
if (radio && enterBtn) {
|
||||
enterBtn.style.display = radio.checked ? 'block' : 'none';
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
openActionMenu(point, info) {
|
||||
const content = `
|
||||
<div class="action-menu">
|
||||
|
|
@ -455,11 +685,24 @@
|
|||
const fragment = document.createDocumentFragment();
|
||||
treeData.forEach(node => this.renderTreeNode(node, fragment, 0));
|
||||
this.elements.tree.appendChild(fragment);
|
||||
|
||||
// 默认全选
|
||||
this.selectAllNodes();
|
||||
}
|
||||
|
||||
this.elements.panel.style.display = 'flex';
|
||||
},
|
||||
|
||||
navigateToAR() {
|
||||
// 跳转到勘察逻辑
|
||||
const projectInfo = this.state.currentClickedProject;
|
||||
if (projectInfo) {
|
||||
Bridge.sendMessage('navigateToProject', { projectInfo: projectInfo });
|
||||
} else {
|
||||
console.warn('没有选中的工程信息,无法跳转到勘察页面');
|
||||
}
|
||||
},
|
||||
|
||||
closePreview() {
|
||||
this.elements.panel.style.display = 'none';
|
||||
this.clearModels();
|
||||
|
|
@ -569,6 +812,7 @@
|
|||
const checkbox = document.createElement('input');
|
||||
checkbox.type = 'checkbox';
|
||||
checkbox.className = 'tree-node-checkbox';
|
||||
checkbox.dataset.id = node.id; // 添加data-id用于全选/全不选时更新UI
|
||||
checkbox.checked = this.state.checkedNodeIds.includes(node.id);
|
||||
checkbox.addEventListener('change', (e) => this.handleCheck(node, e.target.checked));
|
||||
itemDiv.appendChild(checkbox);
|
||||
|
|
@ -621,6 +865,57 @@
|
|||
this.loadBatchData();
|
||||
},
|
||||
|
||||
// 获取所有节点ID(递归)
|
||||
getAllNodeIds(nodes) {
|
||||
let ids = [];
|
||||
nodes.forEach(node => {
|
||||
ids.push(node.id);
|
||||
if (node.children && node.children.length > 0) {
|
||||
ids = ids.concat(this.getAllNodeIds(node.children));
|
||||
}
|
||||
});
|
||||
return ids;
|
||||
},
|
||||
|
||||
// 全选
|
||||
selectAllNodes() {
|
||||
const treeData = this.buildTreeData(this.state.modelList);
|
||||
const allIds = this.getAllNodeIds(treeData);
|
||||
this.state.checkedNodeIds = [...new Set(allIds)]; // 去重
|
||||
|
||||
// 更新所有复选框UI
|
||||
this.updateAllCheckboxes();
|
||||
|
||||
// 触发数据加载
|
||||
this.loadBatchData();
|
||||
},
|
||||
|
||||
// 全不选
|
||||
deselectAllNodes() {
|
||||
this.state.checkedNodeIds = [];
|
||||
|
||||
// 更新所有复选框UI
|
||||
this.updateAllCheckboxes();
|
||||
|
||||
// 清除模型
|
||||
this.clearModels();
|
||||
},
|
||||
|
||||
// 更新所有复选框状态
|
||||
updateAllCheckboxes() {
|
||||
const checkboxes = this.elements.tree.querySelectorAll('input[type="checkbox"]');
|
||||
checkboxes.forEach(checkbox => {
|
||||
// 从checkbox的data-id获取节点ID
|
||||
const nodeId = checkbox.dataset.id;
|
||||
if (nodeId !== undefined) {
|
||||
// 确保ID类型一致(都转为字符串或数字进行比较)
|
||||
const idStr = String(nodeId);
|
||||
const checkedIdsStr = this.state.checkedNodeIds.map(id => String(id));
|
||||
checkbox.checked = checkedIdsStr.includes(idStr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
syncCheckboxUI(rootNode, checked) {
|
||||
// 简易实现:重新渲染虽然 heavy,但在没有 VDOM 的情况下保证一致性。
|
||||
// 更好的方式是在 render 时给 checkbox 加 data-id
|
||||
|
|
|
|||
Loading…
Reference in New Issue