centaline-data-driven-v3 0.1.41 → 0.1.43
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/centaline-data-driven-v3.umd.js +96 -96
- package/package.json +1 -1
- package/src/components/web/Form.vue +202 -49
- package/src/components/web/Tree/Tree.vue +838 -179
- package/src/loader/src/SearchScreen.js +1 -1
- package/src/main.js +3 -3
- package/src/utils/request.js +5 -6
- package/src/views/Form.vue +2 -2
- package/src/views/SearchList.vue +2 -2
- package/src/views/Tree.vue +2 -2
package/package.json
CHANGED
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
<template #title>
|
|
103
103
|
<i class="sign"></i>
|
|
104
104
|
<span :class="[item.required ? 'requiredLabel' : '']">{{ item.controlLabel
|
|
105
|
-
|
|
105
|
+
}}</span>
|
|
106
106
|
<span v-html="item.sufLabel1"></span>
|
|
107
107
|
</template>
|
|
108
108
|
|
|
@@ -293,6 +293,7 @@ const refTip = ref()
|
|
|
293
293
|
const tipTopHight = ref(0)
|
|
294
294
|
const tabTopHight = ref(0)
|
|
295
295
|
const refTabs = ref()
|
|
296
|
+
const translateX = ref(0)
|
|
296
297
|
|
|
297
298
|
const qrtimer1 = ref(null)
|
|
298
299
|
const qrtimer2 = ref(null)
|
|
@@ -324,6 +325,7 @@ onUpdated(() => {
|
|
|
324
325
|
onDeactivated(() => {
|
|
325
326
|
downloadUrl.value = ''
|
|
326
327
|
})
|
|
328
|
+
|
|
327
329
|
onMounted(() => {
|
|
328
330
|
setCss();
|
|
329
331
|
if (refForm.value) {
|
|
@@ -337,6 +339,13 @@ onMounted(() => {
|
|
|
337
339
|
tabTopHight.value = tipTopHight.value;
|
|
338
340
|
}
|
|
339
341
|
}
|
|
342
|
+
nextTick(() => {
|
|
343
|
+
|
|
344
|
+
setTimeout(() => {
|
|
345
|
+
attachScrollButtonListeners()
|
|
346
|
+
}, 1000);
|
|
347
|
+
|
|
348
|
+
});
|
|
340
349
|
})
|
|
341
350
|
init()
|
|
342
351
|
//初始化数据
|
|
@@ -767,59 +776,73 @@ async function tabClick(pane: TabsPaneContext) {
|
|
|
767
776
|
if (props.openType == 'detail') {
|
|
768
777
|
window.localStorage.setItem(tabActiveNameKey.value, model.value.collapse[event.index].fieldName1);//存储
|
|
769
778
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
779
|
+
await nextTick() // 等 DOM 更新完再取节点
|
|
780
|
+
const navWrapScroll = document.querySelector('.el-tabs__nav-scroll') as HTMLElement
|
|
781
|
+
const navWrap = document.querySelector('.el-tabs__nav') as HTMLElement
|
|
782
|
+
const activeBtn = document.querySelector(`.el-tabs__item#tab-${pane.paneName}`) as HTMLElement
|
|
783
|
+
if (!navWrapScroll || !navWrap || !activeBtn) return
|
|
784
|
+
const visibleCount = getVisibleTabCount()
|
|
785
|
+
if (pane.index <= visibleCount / 2) {
|
|
786
|
+
setTimeout(() => {
|
|
787
|
+
navWrap.style.transition = 'transform .3s ease-out'
|
|
788
|
+
navWrap.style.transform = 'translateX(0px)'
|
|
789
|
+
}, 50);
|
|
790
|
+
translateX.value = 0
|
|
791
|
+
return
|
|
792
|
+
}
|
|
793
|
+
const allTabs = Array.from(navWrap.querySelectorAll('.el-tabs__item')) as HTMLElement[]
|
|
794
|
+
const total = allTabs.length
|
|
795
|
+
if (pane.index >= total - 5) {
|
|
796
|
+
const lastTab = allTabs[total - 1]
|
|
797
|
+
const wrapWidth = navWrapScroll.clientWidth
|
|
798
|
+
const lastWidth = lastTab.offsetWidth
|
|
799
|
+
const lastRight = lastTab.offsetLeft + lastWidth // 最后一个右边到 nav 左边的距离
|
|
800
|
+
const needShift = wrapWidth - lastRight // 负值,让右边对齐容器右边
|
|
801
|
+
setTimeout(() => {
|
|
802
|
+
navWrap.style.transition = 'transform .3s ease-out'
|
|
803
|
+
navWrap.style.transform = `translateX(${needShift}px)`
|
|
804
|
+
}, 50);
|
|
805
|
+
translateX.value = needShift
|
|
806
|
+
return
|
|
807
|
+
}
|
|
808
|
+
/* ---------- 1. 初始状态:还没滑过 ---------- */
|
|
809
|
+
const neverSlid = navWrap.style.transform == 'translateX(0px)'
|
|
800
810
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
811
|
+
if (neverSlid && pane.index >= visibleCount / 2) {
|
|
812
|
+
/* 第一次往后走,直接允许滑动 → 走居中逻辑 */
|
|
813
|
+
const wrapWidth = navWrapScroll.clientWidth
|
|
814
|
+
const btnLeft = activeBtn.offsetLeft
|
|
815
|
+
const btnWidth = activeBtn.offsetWidth
|
|
816
|
+
const dx = (wrapWidth - btnWidth) / 2 - btnLeft
|
|
817
|
+
setTimeout(() => {
|
|
818
|
+
navWrap.style.transition = 'transform .3s ease-out'
|
|
819
|
+
navWrap.style.transform = `translateX(${dx}px)`
|
|
820
|
+
}, 50);
|
|
821
|
+
translateX.value = dx
|
|
822
|
+
return
|
|
823
|
+
}
|
|
805
824
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
// ) as HTMLElement
|
|
811
|
-
// if (!navWrapScroll || !activeBtn) return
|
|
825
|
+
/* ---------- 2. 已经滑过 → 恢复两端贴边即锁死 ---------- */
|
|
826
|
+
const firstTab = navWrap.querySelector('.el-tabs__item') as HTMLElement
|
|
827
|
+
const lastTab = navWrap.querySelector('.el-tabs__item:last-child') as HTMLElement
|
|
828
|
+
if (!firstTab || !lastTab) return
|
|
812
829
|
|
|
813
|
-
|
|
814
|
-
// const btnLeft = activeBtn.offsetLeft
|
|
815
|
-
// const btnWidth = activeBtn.offsetWidth
|
|
830
|
+
const lastAtRight = lastTab.getBoundingClientRect().right <= navWrapScroll.getBoundingClientRect().right
|
|
816
831
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
//
|
|
820
|
-
// behavior: 'smooth'
|
|
821
|
-
// })
|
|
832
|
+
if ((lastAtRight && pane.index >= total - 5)) {
|
|
833
|
+
return
|
|
834
|
+
} // 已贴边,不滑
|
|
822
835
|
|
|
836
|
+
/* 需要居中 */
|
|
837
|
+
const wrapWidth = navWrapScroll.clientWidth
|
|
838
|
+
const btnLeft = activeBtn.offsetLeft
|
|
839
|
+
const btnWidth = activeBtn.offsetWidth
|
|
840
|
+
const dx = (wrapWidth - btnWidth) / 2 - btnLeft
|
|
841
|
+
translateX.value = dx
|
|
842
|
+
setTimeout(() => {
|
|
843
|
+
navWrap.style.transition = 'transform .3s ease-out'
|
|
844
|
+
navWrap.style.transform = `translateX(${dx}px)`
|
|
845
|
+
}, 50);
|
|
823
846
|
}
|
|
824
847
|
/** 返回当前屏幕完全可见的 tab 个数 */
|
|
825
848
|
function getVisibleTabCount(): number {
|
|
@@ -839,7 +862,137 @@ function getVisibleTabCount(): number {
|
|
|
839
862
|
const avgWidth = totalWidth / allTabs.length
|
|
840
863
|
return Math.floor(wrapWidth / avgWidth)
|
|
841
864
|
}
|
|
865
|
+
function attachScrollButtonListeners() {
|
|
866
|
+
if (refTabs.value) {
|
|
867
|
+
const tabsEl = refTabs.value.$el
|
|
868
|
+
|
|
869
|
+
// 监听原生左右箭头点击事件(事件委托)
|
|
870
|
+
const arrowLeft = tabsEl.querySelector('.el-tabs__nav-prev')
|
|
871
|
+
const arrowRight = tabsEl.querySelector('.el-tabs__nav-next')
|
|
872
|
+
|
|
873
|
+
if (arrowLeft) {
|
|
874
|
+
// 1. 移除所有已有事件监听(保险)
|
|
875
|
+
const newArrowLeft = arrowLeft.cloneNode(true)
|
|
876
|
+
arrowLeft.parentNode.replaceChild(newArrowLeft, arrowLeft)
|
|
877
|
+
// 2. 添加自定义事件,彻底阻断原生行为
|
|
878
|
+
newArrowLeft.addEventListener('click', handleArrowLeft, { capture: true })
|
|
879
|
+
newArrowLeft.addEventListener('mousedown', (e) => e.preventDefault(), { capture: true })
|
|
880
|
+
arrowLeft.addEventListener('click', handleArrowLeft)
|
|
881
|
+
}
|
|
882
|
+
if (arrowRight) {
|
|
883
|
+
// 1. 移除所有已有事件监听(保险)
|
|
884
|
+
const newArrowRight = arrowRight.cloneNode(true)
|
|
885
|
+
arrowRight.parentNode.replaceChild(newArrowRight, arrowRight)
|
|
886
|
+
// 2. 添加自定义事件,彻底阻断原生行为
|
|
887
|
+
newArrowRight.addEventListener('click', handleArrowRight, { capture: true })
|
|
888
|
+
newArrowRight.addEventListener('mousedown', (e) => e.preventDefault(), { capture: true })
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
function handleArrowLeft(e) {
|
|
893
|
+
// 彻底阻断原生事件传播和默认行为
|
|
894
|
+
e.stopImmediatePropagation()
|
|
895
|
+
e.stopPropagation()
|
|
896
|
+
e.preventDefault()
|
|
897
|
+
scrollTabs('left')
|
|
898
|
+
}
|
|
899
|
+
function handleArrowRight(e) {
|
|
900
|
+
// 彻底阻断原生事件传播和默认行为
|
|
901
|
+
e.stopImmediatePropagation()
|
|
902
|
+
e.stopPropagation()
|
|
903
|
+
e.preventDefault()
|
|
904
|
+
scrollTabs('right')
|
|
905
|
+
}
|
|
906
|
+
function scrollTabs(direction) {
|
|
907
|
+
const navWrapScroll = document.querySelector('.el-tabs__nav-scroll') as HTMLElement
|
|
908
|
+
const navWrap = document.querySelector('.el-tabs__nav') as HTMLElement
|
|
909
|
+
if (!navWrapScroll || !navWrap) return
|
|
910
|
+
const allTabs = Array.from(navWrap.querySelectorAll('.el-tabs__item')) as HTMLElement[]
|
|
911
|
+
if (!allTabs.length) return
|
|
912
|
+
// 找到当前第一个可见的标签索引
|
|
913
|
+
const firstVisibleIndex = getFirstVisibleTabIndex(allTabs)
|
|
914
|
+
if (direction == 'left') {
|
|
915
|
+
if (translateX.value >= 0) {
|
|
916
|
+
translateX.value = 0
|
|
917
|
+
setTimeout(() => {
|
|
918
|
+
navWrap.style.transition = 'transform .3s ease-out'
|
|
919
|
+
navWrap.style.transform = `translateX(${translateX.value}px)`
|
|
920
|
+
}, 50);
|
|
921
|
+
return
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
// 找到当前第一个可见的标签索引
|
|
925
|
+
const firstVisibleIndex = getFirstVisibleTabIndex(allTabs)
|
|
926
|
+
// 计算上一个标签的宽度
|
|
927
|
+
const prevTabWidth = getFirstVisibleTabIndex(allTabs) > 0 ? getTabWidth(allTabs, firstVisibleIndex - 1) : 0
|
|
928
|
+
if (prevTabWidth == 0) {
|
|
929
|
+
translateX.value = 0
|
|
930
|
+
}
|
|
931
|
+
else {
|
|
932
|
+
// 更新偏移量(向右平移)
|
|
933
|
+
translateX.value += prevTabWidth
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
setTimeout(() => {
|
|
937
|
+
navWrap.style.transition = 'transform .3s ease-out'
|
|
938
|
+
navWrap.style.transform = `translateX(${translateX.value}px)`
|
|
939
|
+
}, 50);
|
|
940
|
+
}
|
|
941
|
+
else if (direction == 'right') {
|
|
842
942
|
|
|
943
|
+
// 判断最后一个标签是否已靠右,若是则禁止滚动
|
|
944
|
+
if (isLastTabAlignedRight(navWrapScroll, navWrap)) {
|
|
945
|
+
return
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// 计算下一个标签的宽度
|
|
949
|
+
const nextTabWidth = getTabWidth(allTabs, firstVisibleIndex)
|
|
950
|
+
// 更新偏移量(向左平移)
|
|
951
|
+
translateX.value -= nextTabWidth
|
|
952
|
+
setTimeout(() => {
|
|
953
|
+
navWrap.style.transition = 'transform .3s ease-out'
|
|
954
|
+
navWrap.style.transform = `translateX(${translateX.value}px)`
|
|
955
|
+
}, 50);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
// 获取当前第一个可见的标签索引
|
|
959
|
+
const getFirstVisibleTabIndex = (allTabs) => {
|
|
960
|
+
const scrollLeft = Math.abs(translateX.value)
|
|
961
|
+
let sumWidth = 0
|
|
962
|
+
for (let i = 0; i < allTabs.length; i++) {
|
|
963
|
+
sumWidth += getTabWidth(allTabs, i)
|
|
964
|
+
if (sumWidth > scrollLeft) {
|
|
965
|
+
return i
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
return 0
|
|
969
|
+
}
|
|
970
|
+
// 计算单个标签宽度(包含间距)
|
|
971
|
+
const getTabWidth = (allTabs, index) => {
|
|
972
|
+
if (!allTabs[index]) return 0
|
|
973
|
+
const tab = allTabs[index]
|
|
974
|
+
// 获取标签的实际宽度(包含内边距、边框)
|
|
975
|
+
const width = tab.offsetWidth
|
|
976
|
+
// 获取标签的左右外边距(ElementPlus 默认有间距)
|
|
977
|
+
const style = window.getComputedStyle(tab)
|
|
978
|
+
const marginLeft = parseFloat(style.marginLeft) || 0
|
|
979
|
+
const marginRight = parseFloat(style.marginRight) || 0
|
|
980
|
+
return width + marginLeft + marginRight
|
|
981
|
+
}
|
|
982
|
+
// 检查最后一个标签是否已靠最右侧
|
|
983
|
+
const isLastTabAlignedRight = (navWrapScroll, navWrap) => {
|
|
984
|
+
|
|
985
|
+
// 滚动容器的可视宽度
|
|
986
|
+
const containerWidth = navWrapScroll.clientWidth
|
|
987
|
+
// 所有标签的总宽度
|
|
988
|
+
const totalTabsWidth = navWrap.scrollWidth
|
|
989
|
+
// 当前向左偏移的总距离(绝对值)
|
|
990
|
+
const currentOffset = Math.abs(translateX.value)
|
|
991
|
+
|
|
992
|
+
// 最后一个标签靠右的判定条件:偏移量 + 容器宽度 ≥ 总标签宽度
|
|
993
|
+
// 预留2px误差,避免因像素精度问题导致判断失误
|
|
994
|
+
return (currentOffset + containerWidth) >= (totalTabsWidth - 2)
|
|
995
|
+
}
|
|
843
996
|
|
|
844
997
|
</script>
|
|
845
998
|
|