|
@@ -80,28 +80,54 @@
|
|
|
</span>
|
|
</span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <div class="tabs-container" role="tablist" aria-label="EHR模块">
|
|
|
|
|
|
|
+ <div class="tabs-wrapper">
|
|
|
|
|
+ <!-- 左侧箭头 -->
|
|
|
<button
|
|
<button
|
|
|
- class="el-tab-item"
|
|
|
|
|
- type="button"
|
|
|
|
|
- role="tab"
|
|
|
|
|
- :class="{ 'is-active': activeKey === 'all' }"
|
|
|
|
|
- :aria-selected="activeKey === 'all'"
|
|
|
|
|
- @click="setAll"
|
|
|
|
|
|
|
+ class="scroll-arrow left"
|
|
|
|
|
+ @click="scrollTabs('left')"
|
|
|
|
|
+ :disabled="isLeftDisabled"
|
|
|
>
|
|
>
|
|
|
- <span class="tab-label">全部</span>
|
|
|
|
|
|
|
+ <Icon icon="mdi:chevron-left" />
|
|
|
</button>
|
|
</button>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Tab 列表容器 -->
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="tabs-container"
|
|
|
|
|
+ ref="tabsContainerRef"
|
|
|
|
|
+ role="tablist"
|
|
|
|
|
+ aria-label="EHR模块"
|
|
|
|
|
+ >
|
|
|
|
|
+ <button
|
|
|
|
|
+ class="el-tab-item"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ role="tab"
|
|
|
|
|
+ :class="{ 'is-active': activeKey === 'all' }"
|
|
|
|
|
+ :aria-selected="activeKey === 'all'"
|
|
|
|
|
+ @click="setAll"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span class="tab-label">全部</span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button
|
|
|
|
|
+ v-for="tab in tabs"
|
|
|
|
|
+ :key="tab.groupName"
|
|
|
|
|
+ class="el-tab-item"
|
|
|
|
|
+ :class="{ 'is-active': tab.groupName === activeKey }"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ role="tab"
|
|
|
|
|
+ :aria-selected="tab.groupName === activeKey"
|
|
|
|
|
+ @click="getById(tab)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span class="tab-label">{{ tab.groupName }}</span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 右侧箭头 -->
|
|
|
<button
|
|
<button
|
|
|
- v-for="tab in tabs"
|
|
|
|
|
- :key="tab.groupName"
|
|
|
|
|
- class="el-tab-item"
|
|
|
|
|
- :class="{ 'is-active': tab.groupName === activeKey }"
|
|
|
|
|
- type="button"
|
|
|
|
|
- role="tab"
|
|
|
|
|
- :aria-selected="tab.groupName === activeKey"
|
|
|
|
|
- @click="getById(tab)"
|
|
|
|
|
|
|
+ class="scroll-arrow right"
|
|
|
|
|
+ @click="scrollTabs('right')"
|
|
|
|
|
+ :disabled="!isLeftDisabled"
|
|
|
>
|
|
>
|
|
|
- <span class="tab-label">{{ tab.groupName }}</span>
|
|
|
|
|
|
|
+ <Icon icon="mdi:chevron-right" />
|
|
|
</button>
|
|
</button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
@@ -142,34 +168,6 @@
|
|
|
</h3>
|
|
</h3>
|
|
|
<p class="item-desc">{{ item.remark || "暂无描述" }}</p>
|
|
<p class="item-desc">{{ item.remark || "暂无描述" }}</p>
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
- <!-- <div class="flex justify-between">
|
|
|
|
|
- <div class="item-time flex items-center gap-2">
|
|
|
|
|
- <svg
|
|
|
|
|
- xmlns="http://www.w3.org/2000/svg"
|
|
|
|
|
- width="1em"
|
|
|
|
|
- height="1em"
|
|
|
|
|
- viewBox="0 0 24 24"
|
|
|
|
|
- >
|
|
|
|
|
- <g
|
|
|
|
|
- fill="none"
|
|
|
|
|
- stroke="#f97316"
|
|
|
|
|
- stroke-linecap="round"
|
|
|
|
|
- stroke-linejoin="round"
|
|
|
|
|
- stroke-width="1.5"
|
|
|
|
|
- >
|
|
|
|
|
- <path
|
|
|
|
|
- d="M15.362 5.214A8.252 8.252 0 0 1 12 21A8.25 8.25 0 0 1 6.038 7.047A8.3 8.3 0 0 0 9 9.601a8.98 8.98 0 0 1 3.361-6.867a8.2 8.2 0 0 0 3 2.48"
|
|
|
|
|
- ></path>
|
|
|
|
|
- <path
|
|
|
|
|
- d="M12 18a3.75 3.75 0 0 0 .495-7.468a6 6 0 0 0-1.925 3.547a6 6 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18"
|
|
|
|
|
- ></path>
|
|
|
|
|
- </g>
|
|
|
|
|
- </svg>
|
|
|
|
|
- <span class="text-[12px] text-[#babdd1]">提交流程</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <Icon icon="mdi-light:chevron-right" class="item-arrow w-6 h-6" />
|
|
|
|
|
- </div> -->
|
|
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div v-else class="empty-state">
|
|
<div v-else class="empty-state">
|
|
@@ -206,6 +204,47 @@ const pieChartInstance = ref(null);
|
|
|
let chartResizeObserver = null;
|
|
let chartResizeObserver = null;
|
|
|
let chartInitTimer = null;
|
|
let chartInitTimer = null;
|
|
|
|
|
|
|
|
|
|
+// 1. 定义 Ref
|
|
|
|
|
+const tabsContainerRef = ref(null);
|
|
|
|
|
+const isLeftDisabled = ref(true);
|
|
|
|
|
+const isRightDisabled = ref(true);
|
|
|
|
|
+
|
|
|
|
|
+// 2. 滚动逻辑
|
|
|
|
|
+const scrollTabs = (direction) => {
|
|
|
|
|
+ const container = tabsContainerRef.value;
|
|
|
|
|
+ if (!container) return;
|
|
|
|
|
+
|
|
|
|
|
+ // 每次滚动的距离,可以根据需求调整,例如 200px 或 container.clientWidth / 2
|
|
|
|
|
+ const scrollAmount = 200;
|
|
|
|
|
+
|
|
|
|
|
+ if (direction === "left") {
|
|
|
|
|
+ container.scrollBy({ left: -scrollAmount, behavior: "smooth" });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ container.scrollBy({ left: scrollAmount, behavior: "smooth" });
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 3. 更新箭头禁用状态
|
|
|
|
|
+const updateArrowState = () => {
|
|
|
|
|
+ const container = tabsContainerRef.value;
|
|
|
|
|
+ if (!container) return;
|
|
|
|
|
+
|
|
|
|
|
+ const { scrollLeft, scrollWidth, clientWidth } = container;
|
|
|
|
|
+
|
|
|
|
|
+ // 如果滚动条在最左边(容差1px),禁用左箭头
|
|
|
|
|
+ isLeftDisabled.value = scrollLeft <= 1;
|
|
|
|
|
+
|
|
|
|
|
+ // 如果滚动条在最右边(容差1px),禁用右箭头
|
|
|
|
|
+ // Math.ceil 处理小数像素问题
|
|
|
|
|
+ isRightDisabled.value =
|
|
|
|
|
+ Math.ceil(scrollLeft + clientWidth) >= scrollWidth - 1;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 4. 监听滚动事件
|
|
|
|
|
+const handleTabScroll = () => {
|
|
|
|
|
+ updateArrowState();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const initChartsSafe = (attempt = 0) => {
|
|
const initChartsSafe = (attempt = 0) => {
|
|
|
const lineDom = lineChartRef.value;
|
|
const lineDom = lineChartRef.value;
|
|
|
const pieDom = pieChartRef.value;
|
|
const pieDom = pieChartRef.value;
|
|
@@ -650,6 +689,11 @@ onMounted(async () => {
|
|
|
getAll();
|
|
getAll();
|
|
|
// 等待 DOM 与样式生效,避免移动端首屏尺寸为 0
|
|
// 等待 DOM 与样式生效,避免移动端首屏尺寸为 0
|
|
|
await nextTick();
|
|
await nextTick();
|
|
|
|
|
+ updateArrowState();
|
|
|
|
|
+ // 添加滚动监听
|
|
|
|
|
+ if (tabsContainerRef.value) {
|
|
|
|
|
+ tabsContainerRef.value.addEventListener("scroll", handleTabScroll);
|
|
|
|
|
+ }
|
|
|
requestAnimationFrame(() => {
|
|
requestAnimationFrame(() => {
|
|
|
initChartsSafe();
|
|
initChartsSafe();
|
|
|
// 添加监听
|
|
// 添加监听
|
|
@@ -764,6 +808,10 @@ onBeforeUnmount(() => {
|
|
|
// 可选:销毁 echarts 实例
|
|
// 可选:销毁 echarts 实例
|
|
|
lineChartInstance.value?.dispose();
|
|
lineChartInstance.value?.dispose();
|
|
|
pieChartInstance.value?.dispose();
|
|
pieChartInstance.value?.dispose();
|
|
|
|
|
+
|
|
|
|
|
+ if (tabsContainerRef.value) {
|
|
|
|
|
+ tabsContainerRef.value.removeEventListener("scroll", handleTabScroll);
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
@@ -878,15 +926,6 @@ onBeforeUnmount(() => {
|
|
|
color: #64748b;
|
|
color: #64748b;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.tabs-container {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- border-bottom: 1px solid #e4e7ed; /* Element Plus 标准的分割线颜色 */
|
|
|
|
|
- margin-bottom: 20px;
|
|
|
|
|
- padding-left: 0;
|
|
|
|
|
- overflow-x: auto; /* 防止Tab过多时溢出 */
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
.el-tab-item {
|
|
.el-tab-item {
|
|
|
position: relative;
|
|
position: relative;
|
|
|
display: inline-flex;
|
|
display: inline-flex;
|
|
@@ -1333,4 +1372,101 @@ onBeforeUnmount(() => {
|
|
|
color: #02409b; /* 变蓝 (使用你主题中的蓝色) */
|
|
color: #02409b; /* 变蓝 (使用你主题中的蓝色) */
|
|
|
transform: translateX(4px); /* 向右平移 4px */
|
|
transform: translateX(4px); /* 向右平移 4px */
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+.tabs-wrapper {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 修改:原有的 .tabs-container 去掉 margin-bottom,因为现在由 wrapper 控制间距 */
|
|
|
|
|
+.tabs-container {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ border-bottom: 1px solid #e4e7ed;
|
|
|
|
|
+ padding-left: 0;
|
|
|
|
|
+ overflow-x: auto;
|
|
|
|
|
+ scroll-behavior: smooth;
|
|
|
|
|
+ scrollbar-width: none; /* Firefox */
|
|
|
|
|
+ -ms-overflow-style: none; /* IE 10+ */
|
|
|
|
|
+ flex: 1; /* 占据中间剩余空间 */
|
|
|
|
|
+ mask-image: linear-gradient(
|
|
|
|
|
+ to right,
|
|
|
|
|
+ transparent,
|
|
|
|
|
+ black 20px,
|
|
|
|
|
+ black 98%,
|
|
|
|
|
+ transparent
|
|
|
|
|
+ ); /* 可选:添加两侧渐变遮罩效果 */
|
|
|
|
|
+ -webkit-mask-image: linear-gradient(
|
|
|
|
|
+ to right,
|
|
|
|
|
+ transparent,
|
|
|
|
|
+ black 20px,
|
|
|
|
|
+ black 98%,
|
|
|
|
|
+ transparent
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tabs-container::-webkit-scrollbar {
|
|
|
|
|
+ display: none;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 新增:箭头按钮样式 */
|
|
|
|
|
+.scroll-arrow {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 50%;
|
|
|
|
|
+ transform: translateY(-50%);
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ width: 32px;
|
|
|
|
|
+ height: 32px;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ background-color: #ffffff;
|
|
|
|
|
+ border: 1px solid #e2e8f0;
|
|
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ color: #64748b;
|
|
|
|
|
+ transition: all 0.2s ease;
|
|
|
|
|
+ opacity: 0; /* 默认隐藏,鼠标悬停容器或需要时显示,或者始终显示但禁用时变灰 */
|
|
|
|
|
+ visibility: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 当容器被悬停时显示箭头,或者你可以去掉这个限制让它始终显示 */
|
|
|
|
|
+.tabs-wrapper:hover .scroll-arrow {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ visibility: visible;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.scroll-arrow.left {
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.scroll-arrow.right {
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.scroll-arrow:hover:not(:disabled) {
|
|
|
|
|
+ background-color: #f1f5f9;
|
|
|
|
|
+ color: #02409b;
|
|
|
|
|
+ border-color: #cbd5e1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.scroll-arrow:disabled {
|
|
|
|
|
+ background-color: #f8fafc;
|
|
|
|
|
+ color: #cbd5e1;
|
|
|
|
|
+ cursor: not-allowed;
|
|
|
|
|
+ box-shadow: none;
|
|
|
|
|
+ border-color: #f1f5f9;
|
|
|
|
|
+ opacity: 0.6;
|
|
|
|
|
+ visibility: visible; /* 禁用时也要可见以展示状态 */
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 确保 Tab 项不会被箭头遮挡太多,可以在容器两侧加一点 padding */
|
|
|
|
|
+.tabs-container {
|
|
|
|
|
+ /* 在原有样式基础上增加左右 padding,防止第一个和最后一个 Tab 被箭头完全遮住 */
|
|
|
|
|
+ padding: 0 40px;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|