raintee-maputils 1.0.34 → 1.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +870 -143
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6561,245 +6561,959 @@ class RulerControl {
|
|
|
6561
6561
|
|
|
6562
6562
|
class CustomOptionsControl {
|
|
6563
6563
|
constructor(args) {
|
|
6564
|
-
const { options, onConfirm } = args;
|
|
6564
|
+
const { title, options, onConfirm, icon } = args;
|
|
6565
6565
|
|
|
6566
|
-
this._container = null;
|
|
6567
6566
|
this._map = null;
|
|
6567
|
+
this._container = null;
|
|
6568
6568
|
|
|
6569
|
+
this._title = title || '';
|
|
6569
6570
|
this._options = options || [];
|
|
6571
|
+
this._icon = icon || null;
|
|
6570
6572
|
this._onConfirm = onConfirm || (() => { });
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
console.error('请传入有效的 options 参数(数组)');
|
|
6574
|
-
}
|
|
6573
|
+
this._originalOptions = [...this._options];
|
|
6574
|
+
this._selectedOptions = [];
|
|
6575
6575
|
}
|
|
6576
6576
|
|
|
6577
6577
|
onAdd(map) {
|
|
6578
6578
|
this._map = map;
|
|
6579
6579
|
|
|
6580
|
-
// 创建控件外层容器
|
|
6581
6580
|
this._container = document.createElement('div');
|
|
6582
6581
|
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group custom-options-control';
|
|
6583
6582
|
|
|
6584
|
-
// 创建主按钮(初始只显示“三维模型”文字,点击展开)
|
|
6585
6583
|
const mainButton = document.createElement('button');
|
|
6586
6584
|
mainButton.style.cssText = `
|
|
6587
|
-
|
|
6588
|
-
height: 100%;
|
|
6589
|
-
padding: 0.25rem 0.5rem;
|
|
6590
|
-
margin: 0;
|
|
6591
|
-
border: 1px solid #ccc;
|
|
6585
|
+
padding: 0;
|
|
6592
6586
|
background: white;
|
|
6593
|
-
border
|
|
6587
|
+
border: 0.0625rem solid #ccc;
|
|
6594
6588
|
cursor: pointer;
|
|
6595
|
-
|
|
6596
|
-
|
|
6589
|
+
display: flex;
|
|
6590
|
+
align-items: center;
|
|
6591
|
+
justify-content: center;
|
|
6592
|
+
gap: 0.375rem;
|
|
6597
6593
|
`;
|
|
6598
|
-
mainButton.textContent = '三维模型';
|
|
6599
|
-
mainButton.addEventListener('click', () => this._toggleExpanded());
|
|
6600
6594
|
|
|
6601
|
-
this.
|
|
6595
|
+
if (this._icon) {
|
|
6596
|
+
const iconWrapper = document.createElement('span');
|
|
6597
|
+
iconWrapper.style.cssText = `
|
|
6598
|
+
width: 1rem;
|
|
6599
|
+
height: 1rem;
|
|
6600
|
+
display: inline-flex;
|
|
6601
|
+
align-items: center;
|
|
6602
|
+
justify-content: center;
|
|
6603
|
+
`;
|
|
6604
|
+
|
|
6605
|
+
if (this._icon.trim().startsWith('<svg')) {
|
|
6606
|
+
iconWrapper.innerHTML = this._icon;
|
|
6607
|
+
} else {
|
|
6608
|
+
const img = document.createElement('img');
|
|
6609
|
+
img.src = this._icon;
|
|
6610
|
+
img.style.cssText = `width: 1rem; height: 1rem; object-fit: contain;`;
|
|
6611
|
+
iconWrapper.appendChild(img);
|
|
6612
|
+
}
|
|
6613
|
+
|
|
6614
|
+
mainButton.appendChild(iconWrapper);
|
|
6615
|
+
}
|
|
6602
6616
|
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
this._container.appendChild(
|
|
6617
|
+
mainButton.addEventListener('click', () => {
|
|
6618
|
+
this._showModal();
|
|
6619
|
+
});
|
|
6620
|
+
|
|
6621
|
+
this._container.appendChild(mainButton);
|
|
6608
6622
|
|
|
6609
|
-
//
|
|
6610
|
-
this.
|
|
6623
|
+
// 添加全局样式
|
|
6624
|
+
this._addGlobalStyles();
|
|
6611
6625
|
|
|
6612
6626
|
return this._container;
|
|
6613
6627
|
}
|
|
6614
6628
|
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6629
|
+
_addGlobalStyles() {
|
|
6630
|
+
if (document.querySelector('#custom-options-styles')) return;
|
|
6631
|
+
|
|
6632
|
+
const styles = document.createElement('style');
|
|
6633
|
+
styles.id = 'custom-options-styles';
|
|
6634
|
+
styles.textContent = `
|
|
6635
|
+
@keyframes modalSlideIn {
|
|
6636
|
+
from {
|
|
6637
|
+
opacity: 0;
|
|
6638
|
+
transform: scale(0.95) translateY(-20px);
|
|
6639
|
+
}
|
|
6640
|
+
to {
|
|
6641
|
+
opacity: 1;
|
|
6642
|
+
transform: scale(1) translateY(0);
|
|
6643
|
+
}
|
|
6644
|
+
}
|
|
6645
|
+
|
|
6646
|
+
@keyframes modalBackdropFadeIn {
|
|
6647
|
+
from { opacity: 0; }
|
|
6648
|
+
to { opacity: 1; }
|
|
6649
|
+
}
|
|
6650
|
+
|
|
6651
|
+
@keyframes fadeInUp {
|
|
6652
|
+
from {
|
|
6653
|
+
opacity: 0;
|
|
6654
|
+
transform: translateY(20px);
|
|
6655
|
+
}
|
|
6656
|
+
to {
|
|
6657
|
+
opacity: 1;
|
|
6658
|
+
transform: translateY(0);
|
|
6659
|
+
}
|
|
6660
|
+
}
|
|
6661
|
+
|
|
6662
|
+
.custom-modal-overlay {
|
|
6663
|
+
animation: modalBackdropFadeIn 0.2s ease-out;
|
|
6664
|
+
}
|
|
6665
|
+
|
|
6666
|
+
.custom-modal {
|
|
6667
|
+
animation: modalSlideIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
6668
|
+
}
|
|
6669
|
+
|
|
6670
|
+
.custom-search-input:focus {
|
|
6671
|
+
border-color: #667eea !important;
|
|
6672
|
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important;
|
|
6673
|
+
}
|
|
6674
|
+
|
|
6675
|
+
.custom-checkbox {
|
|
6676
|
+
position: relative;
|
|
6677
|
+
appearance: none;
|
|
6678
|
+
width: 1rem;
|
|
6679
|
+
height: 1rem;
|
|
6680
|
+
border: 2px solid #d1d5db;
|
|
6681
|
+
border-radius: 0.25rem;
|
|
6682
|
+
background: white;
|
|
6683
|
+
cursor: pointer;
|
|
6684
|
+
transition: all 0.2s ease;
|
|
6685
|
+
margin-right: 0.75rem;
|
|
6686
|
+
}
|
|
6687
|
+
|
|
6688
|
+
.custom-checkbox:checked {
|
|
6689
|
+
background: linear-gradient(135deg, #667eea, #764ba2);
|
|
6690
|
+
border-color: #667eea;
|
|
6691
|
+
}
|
|
6692
|
+
|
|
6693
|
+
.custom-checkbox:checked::after {
|
|
6694
|
+
content: '✓';
|
|
6695
|
+
position: absolute;
|
|
6696
|
+
top: 50%;
|
|
6697
|
+
left: 50%;
|
|
6698
|
+
transform: translate(-50%, -50%);
|
|
6699
|
+
color: white;
|
|
6700
|
+
font-size: 0.75rem;
|
|
6701
|
+
font-weight: bold;
|
|
6702
|
+
}
|
|
6703
|
+
|
|
6704
|
+
.custom-checkbox:hover {
|
|
6705
|
+
border-color: #667eea;
|
|
6706
|
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
|
6707
|
+
}
|
|
6708
|
+
|
|
6709
|
+
.custom-list-item {
|
|
6710
|
+
transition: all 0.2s ease;
|
|
6711
|
+
}
|
|
6712
|
+
|
|
6713
|
+
.custom-list-item:hover {
|
|
6714
|
+
background-color: #f8fafc !important;
|
|
6715
|
+
border-color: #e2e8f0 !important;
|
|
6716
|
+
transform: translateX(4px) !important;
|
|
6717
|
+
}
|
|
6718
|
+
|
|
6719
|
+
.custom-modal::-webkit-scrollbar {
|
|
6720
|
+
width: 6px;
|
|
6721
|
+
}
|
|
6722
|
+
|
|
6723
|
+
.custom-modal::-webkit-scrollbar-track {
|
|
6724
|
+
background: #f1f5f9;
|
|
6725
|
+
border-radius: 3px;
|
|
6726
|
+
}
|
|
6727
|
+
|
|
6728
|
+
.custom-modal::-webkit-scrollbar-thumb {
|
|
6729
|
+
background: linear-gradient(135deg, #667eea, #764ba2);
|
|
6730
|
+
border-radius: 3px;
|
|
6731
|
+
}
|
|
6732
|
+
|
|
6733
|
+
.custom-modal::-webkit-scrollbar-thumb:hover {
|
|
6734
|
+
background: linear-gradient(135deg, #5a67d8, #6b46c1);
|
|
6735
|
+
}
|
|
6736
|
+
`;
|
|
6737
|
+
document.head.appendChild(styles);
|
|
6618
6738
|
}
|
|
6619
6739
|
|
|
6620
|
-
|
|
6621
|
-
this.
|
|
6740
|
+
_showModal() {
|
|
6741
|
+
this._overlay = document.createElement('div');
|
|
6742
|
+
this._overlay.className = 'custom-modal-overlay';
|
|
6743
|
+
this._overlay.style.cssText = `
|
|
6744
|
+
position: fixed;
|
|
6745
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
6746
|
+
background: rgba(0, 0, 0, 0.5);
|
|
6747
|
+
backdrop-filter: blur(4px);
|
|
6748
|
+
-webkit-backdrop-filter: blur(4px);
|
|
6749
|
+
z-index: 10000;
|
|
6750
|
+
display: flex;
|
|
6751
|
+
justify-content: center;
|
|
6752
|
+
align-items: center;
|
|
6753
|
+
padding: 1rem;
|
|
6754
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
6755
|
+
`;
|
|
6756
|
+
|
|
6757
|
+
this._modal = document.createElement('div');
|
|
6758
|
+
this._modal.className = 'custom-modal';
|
|
6759
|
+
this._modal.style.cssText = `
|
|
6760
|
+
width: 100%;
|
|
6761
|
+
max-width: 26rem;
|
|
6762
|
+
max-height: 80vh;
|
|
6763
|
+
background: linear-gradient(145deg, #ffffff 0%, #f8fafc 100%);
|
|
6764
|
+
border-radius: 0.75rem;
|
|
6765
|
+
box-shadow:
|
|
6766
|
+
0 20px 25px -5px rgba(0, 0, 0, 0.1),
|
|
6767
|
+
0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
|
6768
|
+
border: 1px solid rgba(255, 255, 255, 0.8);
|
|
6769
|
+
overflow: hidden;
|
|
6770
|
+
display: flex;
|
|
6771
|
+
flex-direction: column;
|
|
6772
|
+
`;
|
|
6773
|
+
|
|
6774
|
+
// 创建头部
|
|
6775
|
+
const header = this._createHeader();
|
|
6776
|
+
this._modal.appendChild(header);
|
|
6777
|
+
|
|
6778
|
+
// 创建搜索区域
|
|
6779
|
+
const searchSection = this._createSearchSection();
|
|
6780
|
+
this._modal.appendChild(searchSection);
|
|
6781
|
+
|
|
6782
|
+
// 创建选项列表
|
|
6783
|
+
this._listBox = document.createElement('div');
|
|
6784
|
+
this._listBox.style.cssText = `
|
|
6785
|
+
flex: 1;
|
|
6786
|
+
overflow-y: auto;
|
|
6787
|
+
padding: 0 1.25rem 1.25rem 1.25rem;
|
|
6788
|
+
min-height: 10rem;
|
|
6789
|
+
`;
|
|
6790
|
+
this._modal.appendChild(this._listBox);
|
|
6791
|
+
|
|
6792
|
+
// 创建底部按钮
|
|
6793
|
+
const footer = this._createFooter();
|
|
6794
|
+
this._modal.appendChild(footer);
|
|
6795
|
+
|
|
6796
|
+
this._overlay.appendChild(this._modal);
|
|
6797
|
+
document.body.appendChild(this._overlay);
|
|
6798
|
+
|
|
6799
|
+
// 聚焦搜索框
|
|
6800
|
+
// setTimeout(() => {
|
|
6801
|
+
// const searchInput = this._modal.querySelector('.custom-search-input');
|
|
6802
|
+
// if (searchInput) {
|
|
6803
|
+
// searchInput.focus();
|
|
6804
|
+
// }
|
|
6805
|
+
// }, 100);
|
|
6806
|
+
|
|
6807
|
+
// 点击遮罩关闭
|
|
6808
|
+
this._overlay.addEventListener('click', (e) => {
|
|
6809
|
+
if (e.target === this._overlay) {
|
|
6810
|
+
this._closeModal();
|
|
6811
|
+
}
|
|
6812
|
+
});
|
|
6813
|
+
|
|
6814
|
+
// ESC 键关闭
|
|
6815
|
+
this._handleKeydown = (e) => {
|
|
6816
|
+
if (e.key === 'Escape') {
|
|
6817
|
+
this._closeModal();
|
|
6818
|
+
}
|
|
6819
|
+
};
|
|
6820
|
+
document.addEventListener('keydown', this._handleKeydown);
|
|
6821
|
+
|
|
6822
|
+
this._renderList('');
|
|
6622
6823
|
}
|
|
6623
6824
|
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6825
|
+
_createHeader() {
|
|
6826
|
+
const header = document.createElement('div');
|
|
6827
|
+
header.style.cssText = `
|
|
6828
|
+
padding: 1.25rem 1.25rem 1rem 1.25rem;
|
|
6829
|
+
border-bottom: 1px solid #e2e8f0;
|
|
6830
|
+
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
|
6831
|
+
`;
|
|
6832
|
+
|
|
6833
|
+
const title = document.createElement('h2');
|
|
6834
|
+
title.textContent = this._title;
|
|
6835
|
+
title.style.cssText = `
|
|
6836
|
+
margin: 0 0 0.5rem 0;
|
|
6837
|
+
font-size: 1.125rem;
|
|
6838
|
+
font-weight: 600;
|
|
6839
|
+
color: #1e293b;
|
|
6840
|
+
display: flex;
|
|
6841
|
+
align-items: center;
|
|
6842
|
+
gap: 0.5rem;
|
|
6843
|
+
`;
|
|
6627
6844
|
|
|
6628
|
-
//
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6845
|
+
// 添加图标
|
|
6846
|
+
const icon = document.createElement('span');
|
|
6847
|
+
icon.innerHTML = '📋';
|
|
6848
|
+
icon.style.fontSize = '1.25rem';
|
|
6849
|
+
title.insertBefore(icon, title.firstChild);
|
|
6632
6850
|
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6851
|
+
const subtitle = document.createElement('p');
|
|
6852
|
+
subtitle.textContent = `共 ${this._originalOptions.length} 个选项,已选择 ${this._selectedOptions.length} 个`;
|
|
6853
|
+
subtitle.style.cssText = `
|
|
6854
|
+
margin: 0;
|
|
6855
|
+
font-size: 0.8125rem;
|
|
6856
|
+
color: #64748b;
|
|
6857
|
+
`;
|
|
6637
6858
|
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6859
|
+
const closeBtn = document.createElement('button');
|
|
6860
|
+
closeBtn.innerHTML = '✕';
|
|
6861
|
+
closeBtn.style.cssText = `
|
|
6862
|
+
position: absolute;
|
|
6863
|
+
top: 1rem;
|
|
6864
|
+
right: 1rem;
|
|
6865
|
+
width: 1.75rem;
|
|
6866
|
+
height: 1.75rem;
|
|
6867
|
+
border: none;
|
|
6868
|
+
background: #f1f5f9;
|
|
6869
|
+
color: #64748b;
|
|
6870
|
+
border-radius: 50%;
|
|
6871
|
+
cursor: pointer;
|
|
6872
|
+
display: flex;
|
|
6873
|
+
align-items: center;
|
|
6874
|
+
justify-content: center;
|
|
6875
|
+
font-size: 0.875rem;
|
|
6876
|
+
transition: all 0.2s ease;
|
|
6877
|
+
font-weight: 500;
|
|
6878
|
+
`;
|
|
6879
|
+
closeBtn.addEventListener('mouseenter', () => {
|
|
6880
|
+
closeBtn.style.background = '#ef4444';
|
|
6881
|
+
closeBtn.style.color = 'white';
|
|
6882
|
+
closeBtn.style.transform = 'rotate(90deg)';
|
|
6883
|
+
});
|
|
6884
|
+
closeBtn.addEventListener('mouseleave', () => {
|
|
6885
|
+
closeBtn.style.background = '#f1f5f9';
|
|
6886
|
+
closeBtn.style.color = '#64748b';
|
|
6887
|
+
closeBtn.style.transform = 'rotate(0deg)';
|
|
6888
|
+
});
|
|
6889
|
+
closeBtn.addEventListener('click', () => this._closeModal());
|
|
6642
6890
|
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6891
|
+
header.style.position = 'relative';
|
|
6892
|
+
header.appendChild(title);
|
|
6893
|
+
header.appendChild(subtitle);
|
|
6894
|
+
header.appendChild(closeBtn);
|
|
6646
6895
|
|
|
6647
|
-
|
|
6648
|
-
|
|
6896
|
+
return header;
|
|
6897
|
+
}
|
|
6898
|
+
|
|
6899
|
+
_createSearchSection() {
|
|
6900
|
+
const section = document.createElement('div');
|
|
6901
|
+
section.style.cssText = `
|
|
6902
|
+
padding: 1.25rem 1.25rem 1rem 1.25rem;
|
|
6903
|
+
`;
|
|
6904
|
+
|
|
6905
|
+
const searchContainer = document.createElement('div');
|
|
6906
|
+
searchContainer.style.cssText = `
|
|
6907
|
+
position: relative;
|
|
6908
|
+
`;
|
|
6649
6909
|
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6910
|
+
const searchIcon = document.createElement('div');
|
|
6911
|
+
searchIcon.innerHTML = '🔍';
|
|
6912
|
+
searchIcon.style.cssText = `
|
|
6913
|
+
position: absolute;
|
|
6914
|
+
left: 0.875rem;
|
|
6915
|
+
top: 50%;
|
|
6916
|
+
transform: translateY(-50%);
|
|
6917
|
+
font-size: 0.875rem;
|
|
6918
|
+
color: #94a3b8;
|
|
6919
|
+
pointer-events: none;
|
|
6920
|
+
`;
|
|
6921
|
+
|
|
6922
|
+
const searchInput = document.createElement('input');
|
|
6923
|
+
searchInput.placeholder = '搜索选项...';
|
|
6924
|
+
searchInput.className = 'custom-search-input';
|
|
6925
|
+
searchInput.style.cssText = `
|
|
6926
|
+
width: 100%;
|
|
6927
|
+
padding: 0.75rem 1rem 0.75rem 2.5rem;
|
|
6928
|
+
border: 2px solid #e2e8f0;
|
|
6929
|
+
border-radius: 0.5rem;
|
|
6930
|
+
font-size: 0.875rem;
|
|
6931
|
+
background: white;
|
|
6932
|
+
transition: all 0.3s ease;
|
|
6933
|
+
box-sizing: border-box;
|
|
6934
|
+
font-family: inherit;
|
|
6935
|
+
outline: none;
|
|
6936
|
+
`;
|
|
6937
|
+
|
|
6938
|
+
searchInput.addEventListener('focus', () => {
|
|
6939
|
+
searchInput.style.borderColor = '#667eea';
|
|
6940
|
+
searchInput.style.boxShadow = '0 0 0 3px rgba(102, 126, 234, 0.1)';
|
|
6654
6941
|
});
|
|
6655
6942
|
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6943
|
+
searchInput.addEventListener('blur', () => {
|
|
6944
|
+
searchInput.style.borderColor = '#e2e8f0';
|
|
6945
|
+
searchInput.style.boxShadow = 'none';
|
|
6946
|
+
});
|
|
6947
|
+
|
|
6948
|
+
searchInput.addEventListener('input', (e) => {
|
|
6949
|
+
this._renderList(e.target.value);
|
|
6950
|
+
});
|
|
6951
|
+
|
|
6952
|
+
searchContainer.appendChild(searchIcon);
|
|
6953
|
+
searchContainer.appendChild(searchInput);
|
|
6954
|
+
section.appendChild(searchContainer);
|
|
6955
|
+
|
|
6956
|
+
return section;
|
|
6957
|
+
}
|
|
6958
|
+
|
|
6959
|
+
_createFooter() {
|
|
6960
|
+
const footer = document.createElement('div');
|
|
6961
|
+
footer.style.cssText = `
|
|
6962
|
+
padding: 1rem 1.25rem;
|
|
6963
|
+
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
|
6964
|
+
border-top: 1px solid #e2e8f0;
|
|
6965
|
+
display: flex;
|
|
6966
|
+
justify-content: flex-end;
|
|
6967
|
+
gap: 0.75rem;
|
|
6968
|
+
`;
|
|
6969
|
+
|
|
6970
|
+
const cancelBtn = document.createElement('button');
|
|
6971
|
+
cancelBtn.textContent = '取消';
|
|
6972
|
+
cancelBtn.style.cssText = `
|
|
6973
|
+
padding: 0.5rem 1rem;
|
|
6974
|
+
background: white;
|
|
6975
|
+
border: 1px solid #d1d5db;
|
|
6976
|
+
border-radius: 0.375rem;
|
|
6670
6977
|
cursor: pointer;
|
|
6671
|
-
|
|
6978
|
+
font-size: 0.875rem;
|
|
6979
|
+
font-weight: 500;
|
|
6980
|
+
color: #374151;
|
|
6981
|
+
transition: all 0.2s ease;
|
|
6982
|
+
font-family: inherit;
|
|
6672
6983
|
`;
|
|
6673
|
-
|
|
6984
|
+
cancelBtn.addEventListener('mouseenter', () => {
|
|
6985
|
+
cancelBtn.style.borderColor = '#ef4444';
|
|
6986
|
+
cancelBtn.style.color = '#ef4444';
|
|
6987
|
+
cancelBtn.style.transform = 'translateY(-1px)';
|
|
6988
|
+
});
|
|
6989
|
+
cancelBtn.addEventListener('mouseleave', () => {
|
|
6990
|
+
cancelBtn.style.borderColor = '#d1d5db';
|
|
6991
|
+
cancelBtn.style.color = '#374151';
|
|
6992
|
+
cancelBtn.style.transform = 'translateY(0)';
|
|
6993
|
+
});
|
|
6994
|
+
cancelBtn.addEventListener('click', () => this._closeModal());
|
|
6674
6995
|
|
|
6675
|
-
const
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
padding:
|
|
6996
|
+
const okBtn = document.createElement('button');
|
|
6997
|
+
okBtn.textContent = '确定';
|
|
6998
|
+
okBtn.style.cssText = `
|
|
6999
|
+
padding: 0.5rem 1rem;
|
|
6679
7000
|
background: #007cba;
|
|
6680
7001
|
color: white;
|
|
6681
7002
|
border: none;
|
|
6682
|
-
border-radius:
|
|
7003
|
+
border-radius: 0.375rem;
|
|
6683
7004
|
cursor: pointer;
|
|
6684
|
-
|
|
7005
|
+
font-size: 0.875rem;
|
|
7006
|
+
font-weight: 500;
|
|
7007
|
+
transition: all 0.2s ease;
|
|
7008
|
+
font-family: inherit;
|
|
7009
|
+
box-shadow: 0 2px 4px rgba(0, 124, 186, 0.2);
|
|
7010
|
+
`;
|
|
7011
|
+
okBtn.addEventListener('mouseenter', () => {
|
|
7012
|
+
okBtn.style.background = '#005a87';
|
|
7013
|
+
okBtn.style.transform = 'translateY(-1px)';
|
|
7014
|
+
okBtn.style.boxShadow = '0 4px 8px rgba(0, 124, 186, 0.3)';
|
|
7015
|
+
});
|
|
7016
|
+
okBtn.addEventListener('mouseleave', () => {
|
|
7017
|
+
okBtn.style.background = '#007cba';
|
|
7018
|
+
okBtn.style.transform = 'translateY(0)';
|
|
7019
|
+
okBtn.style.boxShadow = '0 2px 4px rgba(0, 124, 186, 0.2)';
|
|
7020
|
+
});
|
|
7021
|
+
okBtn.addEventListener('click', () => this._confirm());
|
|
7022
|
+
|
|
7023
|
+
footer.appendChild(cancelBtn);
|
|
7024
|
+
footer.appendChild(okBtn);
|
|
7025
|
+
return footer;
|
|
7026
|
+
}
|
|
7027
|
+
|
|
7028
|
+
_renderList(keyword) {
|
|
7029
|
+
this._listBox.innerHTML = '';
|
|
7030
|
+
|
|
7031
|
+
const list = keyword
|
|
7032
|
+
? this._originalOptions.filter(
|
|
7033
|
+
(o) =>
|
|
7034
|
+
o.label.toLowerCase().includes(keyword.toLowerCase()) ||
|
|
7035
|
+
String(o.value).toLowerCase().includes(keyword.toLowerCase())
|
|
7036
|
+
)
|
|
7037
|
+
: this._originalOptions;
|
|
7038
|
+
|
|
7039
|
+
if (list.length === 0) {
|
|
7040
|
+
const empty = document.createElement('div');
|
|
7041
|
+
empty.style.cssText = `
|
|
7042
|
+
text-align: center;
|
|
7043
|
+
padding: 2.5rem 1rem;
|
|
7044
|
+
color: #94a3b8;
|
|
7045
|
+
`;
|
|
7046
|
+
empty.innerHTML = `
|
|
7047
|
+
<div style="font-size: 2.5rem; margin-bottom: 0.75rem; opacity: 0.6;">🔍</div>
|
|
7048
|
+
<div style="font-size: 1rem; font-weight: 500; margin-bottom: 0.25rem; color: #64748b;">未找到相关结果</div>
|
|
7049
|
+
<div style="font-size: 0.8125rem;">尝试使用其他关键词搜索</div>
|
|
7050
|
+
`;
|
|
7051
|
+
this._listBox.appendChild(empty);
|
|
7052
|
+
return;
|
|
7053
|
+
}
|
|
7054
|
+
|
|
7055
|
+
// 添加选项统计
|
|
7056
|
+
const stats = document.createElement('div');
|
|
7057
|
+
stats.style.cssText = `
|
|
7058
|
+
padding: 0.5rem 0;
|
|
7059
|
+
font-size: 0.8125rem;
|
|
7060
|
+
color: #64748b;
|
|
7061
|
+
border-bottom: 1px solid #f1f5f9;
|
|
7062
|
+
margin-bottom: 0.5rem;
|
|
6685
7063
|
`;
|
|
6686
|
-
|
|
7064
|
+
stats.textContent = `找到 ${list.length} 个相关选项`;
|
|
7065
|
+
this._listBox.appendChild(stats);
|
|
7066
|
+
|
|
7067
|
+
list.forEach((opt, index) => {
|
|
7068
|
+
const item = document.createElement('label');
|
|
7069
|
+
item.className = 'custom-list-item';
|
|
7070
|
+
item.style.cssText = `
|
|
7071
|
+
display: flex;
|
|
7072
|
+
align-items: center;
|
|
7073
|
+
padding: 0.75rem;
|
|
7074
|
+
cursor: pointer;
|
|
7075
|
+
border-radius: 0.5rem;
|
|
7076
|
+
margin-bottom: 0.375rem;
|
|
7077
|
+
transition: all 0.2s ease;
|
|
7078
|
+
border: 2px solid transparent;
|
|
7079
|
+
background: white;
|
|
7080
|
+
position: relative;
|
|
7081
|
+
overflow: hidden;
|
|
7082
|
+
`;
|
|
7083
|
+
|
|
7084
|
+
const checkbox = document.createElement('input');
|
|
7085
|
+
checkbox.type = 'checkbox';
|
|
7086
|
+
checkbox.className = 'custom-checkbox';
|
|
7087
|
+
checkbox.value = opt.value;
|
|
7088
|
+
checkbox.checked = this._selectedOptions.includes(opt.value);
|
|
7089
|
+
checkbox.style.marginRight = '0.75rem';
|
|
7090
|
+
|
|
7091
|
+
const labelSpan = document.createElement('span');
|
|
7092
|
+
labelSpan.innerHTML = this._highlight(opt.label, keyword);
|
|
7093
|
+
labelSpan.style.cssText = `
|
|
7094
|
+
flex: 1;
|
|
7095
|
+
font-size: 0.875rem;
|
|
7096
|
+
color: #374151;
|
|
7097
|
+
line-height: 1.4;
|
|
7098
|
+
font-weight: 500;
|
|
7099
|
+
`;
|
|
7100
|
+
|
|
7101
|
+
// 添加选中状态的视觉反馈
|
|
7102
|
+
if (checkbox.checked) {
|
|
7103
|
+
item.style.backgroundColor = '#f0f4ff';
|
|
7104
|
+
item.style.borderColor = '#667eea';
|
|
7105
|
+
}
|
|
7106
|
+
|
|
7107
|
+
checkbox.addEventListener('change', () => {
|
|
7108
|
+
this._toggle(opt.value);
|
|
7109
|
+
|
|
7110
|
+
// 更新项目样式
|
|
7111
|
+
if (checkbox.checked) {
|
|
7112
|
+
item.style.backgroundColor = '#f0f4ff';
|
|
7113
|
+
item.style.borderColor = '#667eea';
|
|
7114
|
+
} else {
|
|
7115
|
+
item.style.backgroundColor = 'white';
|
|
7116
|
+
item.style.borderColor = 'transparent';
|
|
7117
|
+
}
|
|
6687
7118
|
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
7119
|
+
// 更新标题中的统计信息
|
|
7120
|
+
const subtitle = this._modal.querySelector('p');
|
|
7121
|
+
if (subtitle) {
|
|
7122
|
+
subtitle.textContent = `共 ${this._originalOptions.length} 个选项,已选择 ${this._selectedOptions.length} 个`;
|
|
7123
|
+
}
|
|
7124
|
+
});
|
|
7125
|
+
|
|
7126
|
+
item.appendChild(checkbox);
|
|
7127
|
+
item.appendChild(labelSpan);
|
|
7128
|
+
|
|
7129
|
+
// 添加进入动画
|
|
7130
|
+
item.style.opacity = '0';
|
|
7131
|
+
item.style.transform = 'translateY(10px)';
|
|
7132
|
+
this._listBox.appendChild(item);
|
|
7133
|
+
|
|
7134
|
+
setTimeout(() => {
|
|
7135
|
+
item.style.transition = 'all 0.3s ease';
|
|
7136
|
+
item.style.opacity = '1';
|
|
7137
|
+
item.style.transform = 'translateY(0)';
|
|
7138
|
+
}, index * 30);
|
|
7139
|
+
});
|
|
6691
7140
|
}
|
|
6692
7141
|
|
|
6693
|
-
|
|
6694
|
-
|
|
7142
|
+
_highlight(text, key) {
|
|
7143
|
+
if (!key) return text;
|
|
7144
|
+
const regex = new RegExp(`(${this._escapeRegExp(key)})`, 'gi');
|
|
7145
|
+
return text.replace(regex, '<mark style="background: linear-gradient(120deg, #fef3c7 0%, #fde68a 100%); padding: 0.125rem 0.25rem; border-radius: 0.25rem; font-weight: 600;">$1</mark>');
|
|
6695
7146
|
}
|
|
6696
7147
|
|
|
6697
|
-
|
|
6698
|
-
|
|
7148
|
+
_escapeRegExp(string) {
|
|
7149
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
7150
|
+
}
|
|
6699
7151
|
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
7152
|
+
_toggle(value) {
|
|
7153
|
+
const index = this._selectedOptions.indexOf(value);
|
|
7154
|
+
if (index >= 0) {
|
|
7155
|
+
this._selectedOptions.splice(index, 1);
|
|
6703
7156
|
} else {
|
|
6704
7157
|
this._selectedOptions.push(value);
|
|
6705
7158
|
}
|
|
6706
|
-
|
|
6707
|
-
// 可选:重新渲染复选框状态(如果需要动态更新 UI,但目前 onchange 已处理)
|
|
6708
7159
|
}
|
|
6709
7160
|
|
|
6710
|
-
|
|
6711
|
-
this._setExpanded(false);
|
|
6712
|
-
|
|
7161
|
+
_confirm() {
|
|
6713
7162
|
this._onConfirm({
|
|
6714
|
-
selectedOptions: this._selectedOptions
|
|
6715
|
-
unselectedOptions: this.
|
|
6716
|
-
|
|
7163
|
+
selectedOptions: this._selectedOptions,
|
|
7164
|
+
unselectedOptions: this._originalOptions.filter(
|
|
7165
|
+
(o) => !this._selectedOptions.includes(o.value)
|
|
7166
|
+
),
|
|
7167
|
+
allOptions: this._originalOptions
|
|
6717
7168
|
});
|
|
7169
|
+
this._closeModal();
|
|
6718
7170
|
}
|
|
6719
7171
|
|
|
6720
|
-
|
|
6721
|
-
this.
|
|
7172
|
+
_closeModal() {
|
|
7173
|
+
if (this._overlay) {
|
|
7174
|
+
// 添加退出动画
|
|
7175
|
+
this._modal.style.animation = 'modalSlideIn 0.2s ease-out reverse';
|
|
7176
|
+
this._overlay.style.animation = 'modalBackdropFadeIn 0.2s ease-out reverse';
|
|
7177
|
+
|
|
7178
|
+
setTimeout(() => {
|
|
7179
|
+
if (this._overlay && this._overlay.parentNode) {
|
|
7180
|
+
document.body.removeChild(this._overlay);
|
|
7181
|
+
}
|
|
7182
|
+
this._overlay = null;
|
|
7183
|
+
this._modal = null;
|
|
7184
|
+
}, 200);
|
|
7185
|
+
|
|
7186
|
+
document.removeEventListener('keydown', this._handleKeydown);
|
|
7187
|
+
}
|
|
6722
7188
|
}
|
|
6723
7189
|
|
|
6724
7190
|
onRemove() {
|
|
6725
|
-
if (this._container
|
|
6726
|
-
this._container.
|
|
7191
|
+
if (this._container) {
|
|
7192
|
+
this._container.remove();
|
|
6727
7193
|
}
|
|
7194
|
+
this._closeModal();
|
|
6728
7195
|
}
|
|
6729
7196
|
}
|
|
6730
7197
|
|
|
6731
|
-
// 自定义控件类:ToggleControl
|
|
7198
|
+
// 自定义控件类:ToggleControl(带搜索过滤功能)
|
|
6732
7199
|
class CustomToggleControl {
|
|
6733
7200
|
/**
|
|
6734
7201
|
* 构造函数
|
|
6735
7202
|
* @param {Object} options
|
|
6736
|
-
* @param {string} options.name -
|
|
6737
|
-
* @param {string} options.field -
|
|
6738
|
-
* @param {boolean} options.defaultValue -
|
|
6739
|
-
* @param {string} options.svgIcon - SVG
|
|
6740
|
-
* @param {Function} [options.onToggle] -
|
|
7203
|
+
* @param {string} options.name - 控件名称
|
|
7204
|
+
* @param {string} options.field - 控制的字段名
|
|
7205
|
+
* @param {boolean} options.defaultValue - 默认值
|
|
7206
|
+
* @param {string} options.svgIcon - SVG 图标字符串
|
|
7207
|
+
* @param {Function} [options.onToggle] - 状态切换回调
|
|
7208
|
+
* @param {Array} [options.options] - 可选项目数组 [{id, name, icon?}]
|
|
7209
|
+
* @param {Function} [options.onOptionSelect] - 选项选择回调
|
|
7210
|
+
* @param {boolean} [options.showSearch] - 是否显示搜索框,默认 true
|
|
6741
7211
|
*/
|
|
6742
|
-
constructor({
|
|
7212
|
+
constructor({
|
|
7213
|
+
name,
|
|
7214
|
+
field,
|
|
7215
|
+
defaultValue = false,
|
|
7216
|
+
svgIcon,
|
|
7217
|
+
onToggle,
|
|
7218
|
+
options = [],
|
|
7219
|
+
onOptionSelect,
|
|
7220
|
+
showSearch = true
|
|
7221
|
+
}) {
|
|
6743
7222
|
this.name = name;
|
|
6744
7223
|
this.field = field;
|
|
6745
7224
|
this.defaultValue = defaultValue;
|
|
6746
7225
|
this.svgIcon = svgIcon;
|
|
6747
|
-
this.onToggle = onToggle;
|
|
7226
|
+
this.onToggle = onToggle;
|
|
7227
|
+
this.options = options; // 可选项目
|
|
7228
|
+
this.onOptionSelect = onOptionSelect; // 选项选择回调
|
|
7229
|
+
this.showSearch = showSearch; // 是否显示搜索框
|
|
6748
7230
|
|
|
6749
|
-
//
|
|
7231
|
+
// 控件状态
|
|
6750
7232
|
this._container = null;
|
|
6751
7233
|
this._button = null;
|
|
6752
|
-
this.
|
|
7234
|
+
this._dropdown = null;
|
|
7235
|
+
this._searchInput = null;
|
|
7236
|
+
this._optionsList = null;
|
|
7237
|
+
this.isActive = false;
|
|
7238
|
+
this.isDropdownOpen = false;
|
|
7239
|
+
this.filteredOptions = [...options]; // 过滤后的选项
|
|
7240
|
+
|
|
7241
|
+
// 绑定事件处理函数
|
|
7242
|
+
this._boundHandleClickOutside = this._handleClickOutside.bind(this);
|
|
6753
7243
|
}
|
|
6754
7244
|
|
|
6755
7245
|
// Mapbox 要求的 onAdd 方法
|
|
6756
7246
|
onAdd(map) {
|
|
6757
7247
|
this.map = map;
|
|
6758
7248
|
|
|
6759
|
-
// 创建外层容器
|
|
7249
|
+
// 创建外层容器
|
|
6760
7250
|
this._container = document.createElement('div');
|
|
6761
|
-
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group';
|
|
7251
|
+
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group custom-toggle-control';
|
|
6762
7252
|
|
|
6763
|
-
//
|
|
7253
|
+
// 创建主按钮
|
|
6764
7254
|
this._button = document.createElement('button');
|
|
6765
7255
|
this._button.type = 'button';
|
|
6766
7256
|
this._button.innerHTML = this.svgIcon;
|
|
7257
|
+
this._button.title = this.name;
|
|
6767
7258
|
|
|
6768
7259
|
// 设置按钮样式
|
|
6769
|
-
this.
|
|
6770
|
-
this._button.style.border = 'none';
|
|
6771
|
-
this._button.style.background = 'none';
|
|
6772
|
-
this._button.style.padding = '0';
|
|
6773
|
-
this._button.style.display = 'flex';
|
|
6774
|
-
this._button.style.alignItems = 'center';
|
|
6775
|
-
this._button.style.justifyContent = 'center';
|
|
7260
|
+
this._setupButtonStyles();
|
|
6776
7261
|
|
|
6777
7262
|
// 初始化状态
|
|
6778
7263
|
this.updateStatus();
|
|
6779
7264
|
|
|
6780
|
-
//
|
|
6781
|
-
this._button.addEventListener('click', () => {
|
|
7265
|
+
// 绑定事件
|
|
7266
|
+
this._button.addEventListener('click', (e) => {
|
|
7267
|
+
e.stopPropagation();
|
|
6782
7268
|
this.toggle();
|
|
6783
7269
|
});
|
|
6784
7270
|
|
|
6785
7271
|
this._container.appendChild(this._button);
|
|
6786
7272
|
|
|
7273
|
+
// 创建下拉菜单(如果有选项)
|
|
7274
|
+
if (this.options.length > 0) {
|
|
7275
|
+
this._createDropdown();
|
|
7276
|
+
}
|
|
7277
|
+
|
|
6787
7278
|
return this._container;
|
|
6788
7279
|
}
|
|
6789
7280
|
|
|
6790
|
-
//
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
7281
|
+
// 设置按钮样式
|
|
7282
|
+
_setupButtonStyles() {
|
|
7283
|
+
Object.assign(this._button.style, {
|
|
7284
|
+
cursor: 'pointer',
|
|
7285
|
+
border: 'none',
|
|
7286
|
+
background: 'none',
|
|
7287
|
+
padding: '8px',
|
|
7288
|
+
display: 'flex',
|
|
7289
|
+
alignItems: 'center',
|
|
7290
|
+
justifyContent: 'center',
|
|
7291
|
+
borderRadius: '4px',
|
|
7292
|
+
transition: 'all 0.2s ease'
|
|
7293
|
+
});
|
|
7294
|
+
}
|
|
7295
|
+
|
|
7296
|
+
// 创建下拉菜单
|
|
7297
|
+
_createDropdown() {
|
|
7298
|
+
// 创建下拉容器
|
|
7299
|
+
this._dropdown = document.createElement('div');
|
|
7300
|
+
this._dropdown.className = 'custom-toggle-dropdown';
|
|
7301
|
+
Object.assign(this._dropdown.style, {
|
|
7302
|
+
position: 'absolute',
|
|
7303
|
+
top: '100%',
|
|
7304
|
+
right: '0',
|
|
7305
|
+
backgroundColor: 'white',
|
|
7306
|
+
border: '1px solid #ccc',
|
|
7307
|
+
borderRadius: '4px',
|
|
7308
|
+
boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
|
|
7309
|
+
zIndex: '1000',
|
|
7310
|
+
minWidth: '200px',
|
|
7311
|
+
maxWidth: '300px',
|
|
7312
|
+
display: 'none',
|
|
7313
|
+
marginTop: '4px'
|
|
7314
|
+
});
|
|
7315
|
+
|
|
7316
|
+
// 创建搜索框(如果需要)
|
|
7317
|
+
if (this.showSearch && this.options.length > 5) {
|
|
7318
|
+
this._createSearchBox();
|
|
6794
7319
|
}
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
this.
|
|
7320
|
+
|
|
7321
|
+
// 创建选项列表
|
|
7322
|
+
this._createOptionsList();
|
|
7323
|
+
|
|
7324
|
+
this._container.appendChild(this._dropdown);
|
|
7325
|
+
}
|
|
7326
|
+
|
|
7327
|
+
// 创建搜索框
|
|
7328
|
+
_createSearchBox() {
|
|
7329
|
+
const searchContainer = document.createElement('div');
|
|
7330
|
+
Object.assign(searchContainer.style, {
|
|
7331
|
+
padding: '8px',
|
|
7332
|
+
borderBottom: '1px solid #eee'
|
|
7333
|
+
});
|
|
7334
|
+
|
|
7335
|
+
this._searchInput = document.createElement('input');
|
|
7336
|
+
this._searchInput.type = 'text';
|
|
7337
|
+
this._searchInput.placeholder = '搜索...';
|
|
7338
|
+
this._searchInput.style.cssText = `
|
|
7339
|
+
width: 100%;
|
|
7340
|
+
padding: 6px 8px;
|
|
7341
|
+
border: 1px solid #ddd;
|
|
7342
|
+
border-radius: 4px;
|
|
7343
|
+
fontSize: 12px;
|
|
7344
|
+
outline: none;
|
|
7345
|
+
box-sizing: border-box;
|
|
7346
|
+
`;
|
|
7347
|
+
|
|
7348
|
+
// 绑定搜索事件
|
|
7349
|
+
this._searchInput.addEventListener('input', (e) => {
|
|
7350
|
+
this._filterOptions(e.target.value);
|
|
7351
|
+
});
|
|
7352
|
+
|
|
7353
|
+
// 阻止下拉菜单关闭
|
|
7354
|
+
this._searchInput.addEventListener('click', (e) => {
|
|
7355
|
+
e.stopPropagation();
|
|
7356
|
+
});
|
|
7357
|
+
|
|
7358
|
+
searchContainer.appendChild(this._searchInput);
|
|
7359
|
+
this._dropdown.appendChild(searchContainer);
|
|
6798
7360
|
}
|
|
6799
7361
|
|
|
6800
|
-
//
|
|
7362
|
+
// 创建选项列表
|
|
7363
|
+
_createOptionsList() {
|
|
7364
|
+
this._optionsList = document.createElement('div');
|
|
7365
|
+
Object.assign(this._optionsList.style, {
|
|
7366
|
+
maxHeight: '200px',
|
|
7367
|
+
overflowY: 'auto',
|
|
7368
|
+
padding: '4px 0'
|
|
7369
|
+
});
|
|
7370
|
+
|
|
7371
|
+
this._renderOptionsList();
|
|
7372
|
+
this._dropdown.appendChild(this._optionsList);
|
|
7373
|
+
}
|
|
7374
|
+
|
|
7375
|
+
// 渲染选项列表
|
|
7376
|
+
_renderOptionsList() {
|
|
7377
|
+
if (!this._optionsList) return;
|
|
7378
|
+
|
|
7379
|
+
this._optionsList.innerHTML = '';
|
|
7380
|
+
|
|
7381
|
+
this.filteredOptions.forEach(option => {
|
|
7382
|
+
const optionItem = document.createElement('div');
|
|
7383
|
+
optionItem.className = 'custom-toggle-option';
|
|
7384
|
+
optionItem.dataset.id = option.id;
|
|
7385
|
+
|
|
7386
|
+
Object.assign(optionItem.style, {
|
|
7387
|
+
padding: '8px 12px',
|
|
7388
|
+
cursor: 'pointer',
|
|
7389
|
+
display: 'flex',
|
|
7390
|
+
alignItems: 'center',
|
|
7391
|
+
gap: '8px',
|
|
7392
|
+
fontSize: '13px',
|
|
7393
|
+
transition: 'background-color 0.2s'
|
|
7394
|
+
});
|
|
7395
|
+
|
|
7396
|
+
// 添加图标(如果有)
|
|
7397
|
+
if (option.icon) {
|
|
7398
|
+
const icon = document.createElement('span');
|
|
7399
|
+
icon.innerHTML = option.icon;
|
|
7400
|
+
icon.style.fontSize = '14px';
|
|
7401
|
+
optionItem.appendChild(icon);
|
|
7402
|
+
}
|
|
7403
|
+
|
|
7404
|
+
// 添加文本
|
|
7405
|
+
const text = document.createElement('span');
|
|
7406
|
+
text.textContent = option.name;
|
|
7407
|
+
optionItem.appendChild(text);
|
|
7408
|
+
|
|
7409
|
+
// 绑定点击事件
|
|
7410
|
+
optionItem.addEventListener('click', (e) => {
|
|
7411
|
+
e.stopPropagation();
|
|
7412
|
+
this._selectOption(option);
|
|
7413
|
+
});
|
|
7414
|
+
|
|
7415
|
+
// 鼠标悬停效果
|
|
7416
|
+
optionItem.addEventListener('mouseenter', () => {
|
|
7417
|
+
optionItem.style.backgroundColor = '#f5f5f5';
|
|
7418
|
+
});
|
|
7419
|
+
|
|
7420
|
+
optionItem.addEventListener('mouseleave', () => {
|
|
7421
|
+
optionItem.style.backgroundColor = 'transparent';
|
|
7422
|
+
});
|
|
7423
|
+
|
|
7424
|
+
this._optionsList.appendChild(optionItem);
|
|
7425
|
+
});
|
|
7426
|
+
|
|
7427
|
+
// 如果没有匹配的选项
|
|
7428
|
+
if (this.filteredOptions.length === 0) {
|
|
7429
|
+
const noResults = document.createElement('div');
|
|
7430
|
+
noResults.textContent = '无匹配项';
|
|
7431
|
+
Object.assign(noResults.style, {
|
|
7432
|
+
padding: '12px',
|
|
7433
|
+
textAlign: 'center',
|
|
7434
|
+
color: '#999',
|
|
7435
|
+
fontSize: '12px'
|
|
7436
|
+
});
|
|
7437
|
+
this._optionsList.appendChild(noResults);
|
|
7438
|
+
}
|
|
7439
|
+
}
|
|
7440
|
+
|
|
7441
|
+
// 过滤选项
|
|
7442
|
+
_filterOptions(searchTerm) {
|
|
7443
|
+
const term = searchTerm.toLowerCase().trim();
|
|
7444
|
+
|
|
7445
|
+
if (!term) {
|
|
7446
|
+
this.filteredOptions = [...this.options];
|
|
7447
|
+
} else {
|
|
7448
|
+
this.filteredOptions = this.options.filter(option =>
|
|
7449
|
+
option.name.toLowerCase().includes(term) ||
|
|
7450
|
+
(option.id && option.id.toString().toLowerCase().includes(term))
|
|
7451
|
+
);
|
|
7452
|
+
}
|
|
7453
|
+
|
|
7454
|
+
this._renderOptionsList();
|
|
7455
|
+
}
|
|
7456
|
+
|
|
7457
|
+
// 选择选项
|
|
7458
|
+
_selectOption(option) {
|
|
7459
|
+
// 调用选项选择回调
|
|
7460
|
+
if (this.onOptionSelect) {
|
|
7461
|
+
this.onOptionSelect(option);
|
|
7462
|
+
}
|
|
7463
|
+
|
|
7464
|
+
// 关闭下拉菜单
|
|
7465
|
+
this.closeDropdown();
|
|
7466
|
+
}
|
|
7467
|
+
|
|
7468
|
+
// 切换下拉菜单显示状态
|
|
7469
|
+
toggle() {
|
|
7470
|
+
if (this.isDropdownOpen) {
|
|
7471
|
+
this.closeDropdown();
|
|
7472
|
+
} else {
|
|
7473
|
+
this.openDropdown();
|
|
7474
|
+
}
|
|
7475
|
+
}
|
|
7476
|
+
|
|
7477
|
+
// 打开下拉菜单
|
|
7478
|
+
openDropdown() {
|
|
7479
|
+
if (!this._dropdown || this.options.length === 0) return;
|
|
7480
|
+
|
|
7481
|
+
this.isDropdownOpen = true;
|
|
7482
|
+
this._dropdown.style.display = 'block';
|
|
7483
|
+
|
|
7484
|
+
// 添加全局点击监听
|
|
7485
|
+
document.addEventListener('click', this._boundHandleClickOutside);
|
|
7486
|
+
|
|
7487
|
+
// 聚焦搜索框
|
|
7488
|
+
if (this._searchInput) {
|
|
7489
|
+
setTimeout(() => {
|
|
7490
|
+
this._searchInput.focus();
|
|
7491
|
+
this._searchInput.value = '';
|
|
7492
|
+
this._filterOptions('');
|
|
7493
|
+
}, 100);
|
|
7494
|
+
}
|
|
7495
|
+
}
|
|
7496
|
+
|
|
7497
|
+
// 关闭下拉菜单
|
|
7498
|
+
closeDropdown() {
|
|
7499
|
+
if (!this._dropdown) return;
|
|
7500
|
+
|
|
7501
|
+
this.isDropdownOpen = false;
|
|
7502
|
+
this._dropdown.style.display = 'none';
|
|
7503
|
+
|
|
7504
|
+
// 移除全局点击监听
|
|
7505
|
+
document.removeEventListener('click', this._boundHandleClickOutside);
|
|
7506
|
+
}
|
|
7507
|
+
|
|
7508
|
+
// 处理外部点击
|
|
7509
|
+
_handleClickOutside(event) {
|
|
7510
|
+
if (!this._container.contains(event.target)) {
|
|
7511
|
+
this.closeDropdown();
|
|
7512
|
+
}
|
|
7513
|
+
}
|
|
7514
|
+
|
|
7515
|
+
// 更新控件状态
|
|
6801
7516
|
updateStatus() {
|
|
6802
|
-
// 从 map.SourceMap 中获取当前 field 的值,如果不存在则使用 defaultValue
|
|
6803
7517
|
let currentValue = this.defaultValue;
|
|
6804
7518
|
|
|
6805
7519
|
if (
|
|
@@ -6810,21 +7524,22 @@ class CustomToggleControl {
|
|
|
6810
7524
|
currentValue = this.map.SourceMap[this.field];
|
|
6811
7525
|
}
|
|
6812
7526
|
|
|
6813
|
-
this.isActive = currentValue;
|
|
7527
|
+
this.isActive = currentValue;
|
|
6814
7528
|
|
|
6815
7529
|
// 更新按钮样式
|
|
6816
7530
|
if (this.isActive) {
|
|
6817
7531
|
this._button.style.opacity = '1';
|
|
6818
7532
|
this._button.style.filter = 'none';
|
|
7533
|
+
this._button.style.backgroundColor = '#e6f3ff';
|
|
6819
7534
|
} else {
|
|
6820
|
-
this._button.style.opacity = '0.
|
|
7535
|
+
this._button.style.opacity = '0.7';
|
|
6821
7536
|
this._button.style.filter = 'grayscale(100%)';
|
|
7537
|
+
this._button.style.backgroundColor = 'transparent';
|
|
6822
7538
|
}
|
|
6823
7539
|
}
|
|
6824
7540
|
|
|
6825
|
-
//
|
|
6826
|
-
|
|
6827
|
-
// 获取当前值
|
|
7541
|
+
// 切换状态(保持原有功能)
|
|
7542
|
+
toggleState() {
|
|
6828
7543
|
let currentValue = this.defaultValue;
|
|
6829
7544
|
|
|
6830
7545
|
if (
|
|
@@ -6835,22 +7550,34 @@ class CustomToggleControl {
|
|
|
6835
7550
|
currentValue = this.map.SourceMap[this.field];
|
|
6836
7551
|
}
|
|
6837
7552
|
|
|
6838
|
-
// 切换值
|
|
6839
7553
|
const newValue = !currentValue;
|
|
6840
7554
|
|
|
6841
|
-
// 更新到 map.SourceMap 中
|
|
6842
7555
|
if (this.map && this.map.SourceMap) {
|
|
6843
7556
|
this.map.SourceMap[this.field] = newValue;
|
|
6844
7557
|
}
|
|
6845
7558
|
|
|
6846
|
-
// 更新内部状态
|
|
6847
7559
|
this.isActive = newValue;
|
|
6848
|
-
|
|
6849
|
-
// 更新 UI 样式
|
|
6850
7560
|
this.updateStatus();
|
|
6851
7561
|
|
|
6852
|
-
|
|
6853
|
-
|
|
7562
|
+
if (this.onToggle) {
|
|
7563
|
+
this.onToggle(newValue);
|
|
7564
|
+
}
|
|
7565
|
+
}
|
|
7566
|
+
|
|
7567
|
+
// Mapbox 要求的 onRemove 方法
|
|
7568
|
+
onRemove() {
|
|
7569
|
+
this.closeDropdown();
|
|
7570
|
+
|
|
7571
|
+
if (this._container && this._container.parentNode) {
|
|
7572
|
+
this._container.parentNode.removeChild(this._container);
|
|
7573
|
+
}
|
|
7574
|
+
|
|
7575
|
+
this.map = null;
|
|
7576
|
+
this._container = null;
|
|
7577
|
+
this._button = null;
|
|
7578
|
+
this._dropdown = null;
|
|
7579
|
+
this._searchInput = null;
|
|
7580
|
+
this._optionsList = null;
|
|
6854
7581
|
}
|
|
6855
7582
|
}
|
|
6856
7583
|
|