adtec-core-package 3.2.6 → 3.2.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adtec-core-package",
3
- "version": "3.2.6",
3
+ "version": "3.2.7",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -126,30 +126,51 @@ div:focus {
126
126
  --margin-8: 8px;
127
127
  --margin-9: 9px;
128
128
  --margin-10: 10px;
129
+ /* 全系统滚动条统一为 vxe 观感 */
130
+ --adtec-scrollbar-size: 8px;
131
+ --adtec-scrollbar-thumb: #c0c4cc;
132
+ --adtec-scrollbar-thumb-hover: #909399;
133
+ /* vxe 表格滚动条粗细(仅 Chrome/Edge 的 ::-webkit-scrollbar 支持精确 px) */
134
+ --adtec-vxe-scrollbar-size: 8px;
129
135
  }
130
136
  .move-back {
131
137
  background: #f5f5f5 !important;
132
138
  }
133
139
 
140
+ /**
141
+ * 全局原生滚动条(Chrome/Edge):对齐 vxe 观感。
142
+ * 关键:-webkit-appearance: none —— macOS/Chromium 默认 overlay 细条会忽略 width/height,
143
+ * 加了才切换为经典滚动条,尊重此处的 px 与配色。勿在 * 上写 scrollbar-width(会退回 overlay)。
144
+ */
134
145
  *::-webkit-scrollbar {
135
- width: 6px;
136
- height: 6px;
146
+ -webkit-appearance: none;
147
+ appearance: none;
148
+ width: var(--adtec-scrollbar-size);
149
+ height: var(--adtec-scrollbar-size);
137
150
  background: transparent;
138
151
  }
139
152
 
140
153
  *::-webkit-scrollbar-thumb {
141
- background: transparent;
142
- border-radius: 4px;
154
+ background: var(--adtec-scrollbar-thumb);
155
+ border-radius: 6px;
143
156
  }
144
157
 
145
- *:hover::-webkit-scrollbar-thumb {
146
- background: #DDDEE0;
158
+ *::-webkit-scrollbar-thumb:hover {
159
+ background: var(--adtec-scrollbar-thumb-hover);
147
160
  }
148
161
 
149
- *:hover::-webkit-scrollbar-track {
162
+ *::-webkit-scrollbar-track {
150
163
  background: transparent;
151
164
  }
152
165
 
166
+ /* Firefox:无 webkit 伪元素时才用 scrollbar-width(无法精确到 px) */
167
+ @supports not selector(::-webkit-scrollbar) {
168
+ * {
169
+ scrollbar-width: thin;
170
+ scrollbar-color: var(--adtec-scrollbar-thumb) transparent;
171
+ }
172
+ }
173
+
153
174
  //::-webkit-scrollbar {
154
175
  // width: 6px;
155
176
  // height: 6px;
@@ -184,4 +205,59 @@ div:focus {
184
205
  // 两个滚动条的交汇处上用于通过拖动调整元素大小的小控件
185
206
  *::-webkit-resizer {
186
207
  display: none;
208
+ }
209
+
210
+ /* UMO 编辑器:工具栏横向滚动仍隐藏;正文/面板滚动条与系统对齐 */
211
+ .umo-rich-text-editor-root {
212
+ .umo-scrollable-content {
213
+ scrollbar-width: none !important;
214
+ -ms-overflow-style: none !important;
215
+
216
+ &::-webkit-scrollbar {
217
+ display: none !important;
218
+ width: 0 !important;
219
+ height: 0 !important;
220
+ }
221
+
222
+ &:hover::-webkit-scrollbar-thumb {
223
+ background: transparent !important;
224
+ }
225
+ }
226
+
227
+ .umo-scrollbar,
228
+ .umo-zoomable-container {
229
+ scrollbar-width: auto;
230
+ scrollbar-color: var(--adtec-scrollbar-thumb) transparent;
231
+
232
+ &::-webkit-scrollbar {
233
+ width: var(--adtec-scrollbar-size) !important;
234
+ height: var(--adtec-scrollbar-size) !important;
235
+ }
236
+
237
+ &::-webkit-scrollbar-thumb {
238
+ background-color: var(--adtec-scrollbar-thumb) !important;
239
+ border-radius: 6px !important;
240
+ border: 2px solid transparent !important;
241
+ background-clip: content-box !important;
242
+ }
243
+
244
+ &:hover::-webkit-scrollbar-thumb {
245
+ background-color: var(--adtec-scrollbar-thumb-hover) !important;
246
+ }
247
+ }
248
+ }
249
+
250
+ .umo-scrollable-content {
251
+ scrollbar-width: none !important;
252
+ -ms-overflow-style: none !important;
253
+
254
+ &::-webkit-scrollbar {
255
+ display: none !important;
256
+ width: 0 !important;
257
+ height: 0 !important;
258
+ }
259
+
260
+ &:hover::-webkit-scrollbar-thumb {
261
+ background: transparent !important;
262
+ }
187
263
  }
@@ -4,8 +4,9 @@
4
4
  ref="rootRef"
5
5
  class="umo-rich-text-editor-root"
6
6
  :class="{ 'umo-rich-text-editor-root--readonly': !editable }">
7
- <UmoEditor
8
- v-if="umoMountOptions"
7
+ <component
8
+ :is="UmoEditorComp"
9
+ v-if="UmoEditorComp && umoMountOptions"
9
10
  :key="umoRuntimeKey"
10
11
  ref="editorRef"
11
12
  class="umo-rich-text-editor"
@@ -14,14 +15,25 @@
14
15
  @changed="onEditorChanged"
15
16
  @blur="onEditorBlur"
16
17
  />
18
+ <!-- 受控 loading 覆盖全程:运行时 import → UmoEditor 挂载 → TipTap created,杜绝 UMO 内置 loading 闪现/泄漏 -->
19
+ <div
20
+ v-if="showControlledLoading"
21
+ class="umo-rich-text-editor-loading"
22
+ v-loading="true"
23
+ element-loading-text="编辑器加载中..."
24
+ />
17
25
  </div>
18
26
  </template>
19
27
 
20
28
  <script setup lang="ts">
21
- import { UmoEditor } from '../../../prebuilt/umo-editor/umo-editor.js'
22
- import '../../../prebuilt/umo-editor/umo-editor.css'
29
+ /**
30
+ * UMO 编辑器运行时(umo-editor ~2.9MB + TDesign ~2.29MB + exceljs 等)改为受控懒加载:
31
+ * 不再静态引入,避免这 ~7MB 打进入口/页面同步 chunk。
32
+ * 严格串行:先 import() 运行时并完成全局注册(installUmoEditorApp),再渲染 UmoEditor,
33
+ * 中间只显示一个受控 loading,杜绝「UMO 内置 loading vs 自定义 loading」竞态卡死。
34
+ */
23
35
  import { ElMessage } from 'element-plus'
24
- import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, shallowRef, watch, type App } from 'vue'
36
+ import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, shallowRef, watch, type App, type Component } from 'vue'
25
37
  import { v4 as uuidv4 } from 'uuid'
26
38
  import {
27
39
  finalizeHtml,
@@ -30,7 +42,6 @@ import {
30
42
  purgeUmoDocumentLocalStorage,
31
43
  releaseUmoDocumentStorageShim,
32
44
  } from './richTextHtmlUtils'
33
- import { installUmoEditorApp } from './installUmoEditorApp'
34
45
 
35
46
  export type RichTextEditorConfig = {
36
47
  placeholder?: string
@@ -106,15 +117,22 @@ const text = defineModel<string>('text', {
106
117
  required: false,
107
118
  })
108
119
 
109
- const editorRef = ref<InstanceType<typeof UmoEditor> | null>(null)
120
+ const editorRef = ref<any>(null)
110
121
  const rootRef = ref<HTMLElement | null>(null)
111
122
  /** setup 同步捕获;async/Observer 内 getCurrentInstance() 为 null */
112
123
  const hostApp = getCurrentInstance()?.appContext?.app as App | undefined
124
+ /** 懒加载的 UmoEditor 组件;null 时显示受控 loading,加载并注册全局后再渲染 */
125
+ const UmoEditorComp = shallowRef<Component | null>(null)
126
+ let umoRuntimePromise: Promise<boolean> | null = null
113
127
  const editorKey = `umo-${uuidv4()}`
114
128
  /** 编辑/只读扩展集不同,切换时需 remount;key 变化强制重建 UmoEditor */
115
129
  const umoRuntimeKey = ref(editorKey)
116
130
  const lastMountEditable = ref<boolean | null>(null)
117
131
  const ready = ref(false)
132
+ /** 受控 loading:运行时未就绪或编辑器尚未 created/bootstrap 完成 */
133
+ const showControlledLoading = computed(
134
+ () => !UmoEditorComp.value || !umoMountOptions.value || !ready.value,
135
+ )
118
136
  const syncingContent = ref(false)
119
137
  /** 挂载快照,避免 computed props 变更触发 Umo 内部反复 patch 导致 emitsOptions null */
120
138
  const umoMountOptions = shallowRef<Record<string, unknown> | null>(null)
@@ -139,16 +157,25 @@ function isPanelVisible() {
139
157
  }
140
158
 
141
159
  function handlePanelShown() {
142
- if (!isPanelVisible() || !umoMountOptions.value) {
160
+ if (!isPanelVisible()) {
143
161
  rootWasHidden = true
144
162
  return
145
163
  }
146
- if (!rootWasHidden) return
164
+ const wasHidden = rootWasHidden
147
165
  rootWasHidden = false
148
- if (!ready.value) {
166
+ if (!UmoEditorComp.value) {
167
+ void startUmoBootstrap()
168
+ return
169
+ }
170
+ if (!umoMountOptions.value) {
171
+ initUmoMountOptions()
172
+ return
173
+ }
174
+ if (wasHidden && !ready.value) {
149
175
  void bootstrapEditor()
150
176
  return
151
177
  }
178
+ if (!wasHidden) return
152
179
  void applyEditableStateWithRetry()
153
180
  if (editable.value) {
154
181
  void ensureBlockImageNodeView()
@@ -223,15 +250,52 @@ async function remountEditor() {
223
250
  umoMountOptions.value = null
224
251
  umoRuntimeKey.value = `${editorKey}-${Date.now()}`
225
252
  await nextTick()
226
- ensureUmoGlobals()
253
+ const ok = await ensureUmoGlobals()
254
+ if (!ok) return
227
255
  initUmoMountOptions(html)
228
256
  } finally {
229
257
  remounting = false
230
258
  }
231
259
  }
232
260
 
233
- function ensureUmoGlobals() {
234
- return installUmoEditorApp(hostApp ?? getCurrentInstance()?.appContext?.app)
261
+ /**
262
+ * 受控懒加载:并行 import UMO 运行时 + CSS + 安装器,
263
+ * 完成全局注册(TDesign + umoGlobalComponents)后再暴露 UmoEditorComp。
264
+ * 幂等:多次调用共用同一 Promise;失败可重试。
265
+ */
266
+ function ensureUmoGlobals(): Promise<boolean> {
267
+ if (UmoEditorComp.value) return Promise.resolve(true)
268
+ if (!umoRuntimePromise) {
269
+ umoRuntimePromise = Promise.all([
270
+ import('../../../prebuilt/umo-editor/umo-editor.js'),
271
+ import('../../../prebuilt/umo-editor/umo-editor.css'),
272
+ import('./installUmoEditorApp'),
273
+ ])
274
+ .then(([umoMod, _css, installMod]) => {
275
+ installMod.installUmoEditorApp(hostApp)
276
+ UmoEditorComp.value = (umoMod as { UmoEditor: Component }).UmoEditor
277
+ return true
278
+ })
279
+ .catch(() => {
280
+ umoRuntimePromise = null
281
+ ElMessage.error('编辑器加载失败,请重试')
282
+ return false
283
+ })
284
+ }
285
+ return umoRuntimePromise
286
+ }
287
+
288
+ /** 面板可见时才启动懒加载,避免隐藏 Tab/Collapse 内编辑器触发 UMO loading */
289
+ async function startUmoBootstrap() {
290
+ if (!isPanelVisible()) {
291
+ rootWasHidden = true
292
+ return
293
+ }
294
+ const ok = await ensureUmoGlobals()
295
+ if (!ok) return
296
+ if (!umoMountOptions.value) {
297
+ initUmoMountOptions()
298
+ }
235
299
  }
236
300
 
237
301
  const editable = computed(() => {
@@ -504,15 +568,11 @@ function onEditorBlur() {
504
568
  }
505
569
 
506
570
  onMounted(() => {
507
- ensureUmoGlobals()
508
571
  rootWasHidden = !isPanelVisible()
509
572
  observePanelVisibility()
573
+ void startUmoBootstrap()
510
574
  })
511
575
 
512
- // editable 就绪后同步初始化,避免 onBeforeMount 时序问题
513
- ensureUmoGlobals()
514
- initUmoMountOptions()
515
-
516
576
  onBeforeUnmount(() => {
517
577
  clearVisibilityObserver()
518
578
  ready.value = false
@@ -609,8 +669,22 @@ onUnmounted(() => {
609
669
  min-width: 0;
610
670
  min-height: 280px;
611
671
  box-sizing: border-box;
672
+ position: relative;
673
+ overflow: hidden;
612
674
  }
613
675
 
676
+ .umo-rich-text-editor-loading {
677
+ position: absolute;
678
+ inset: 0;
679
+ z-index: 20;
680
+ flex: 1;
681
+ min-height: 200px;
682
+ width: 100%;
683
+ pointer-events: none;
684
+ }
685
+
686
+ /* 受控 loading 由 installUmoEmbedStyles 全局禁用 UMO 内置 loading,此处仅保留容器样式 */
687
+
614
688
  :deep(.umo-rich-text-editor) {
615
689
  width: 100%;
616
690
  height: 100%;
@@ -687,14 +761,6 @@ onUnmounted(() => {
687
761
  }
688
762
 
689
763
  .umo-rich-text-editor-root--readonly {
690
- :deep(.umo-loading),
691
- :deep(.umo-loading--visible),
692
- :deep(.umo-loading__overlay),
693
- :deep(.umo-loading--center),
694
- :deep(.umo-icon-loading) {
695
- display: none !important;
696
- }
697
-
698
764
  :deep(.umo-editor-content .ProseMirror) {
699
765
  cursor: default;
700
766
  }
@@ -1,10 +1,25 @@
1
- import type { App, Component } from 'vue'
1
+ import { defineComponent, type App, type Component } from 'vue'
2
2
  import TDesign from 'tdesign-vue-next'
3
3
  import { umoGlobalComponents } from '../../../prebuilt/umo-editor/umo-editor.js'
4
4
 
5
5
  const registeredApps = new WeakSet<App>()
6
6
  const tdesignApps = new WeakSet<App>()
7
7
 
8
+ /** TDesign Loading 空实现:嵌入场景不使用 UMO 内置 loading(由 RichTextEditor 受控 loading 接管) */
9
+ const UmoLoadingNoop = defineComponent({
10
+ name: 'TLoading',
11
+ inheritAttrs: false,
12
+ props: { loading: { type: Boolean, default: false } },
13
+ setup() {
14
+ return () => null
15
+ },
16
+ })
17
+
18
+ const umoLoadingServiceNoop = Object.assign(
19
+ () => ({ hide: () => {} }),
20
+ { install: () => {} },
21
+ )
22
+
8
23
  /** 嵌入 Umo 的全局样式覆盖(须注入 document.head,全屏 Teleport 到 body 时组件 scoped :deep 无法命中) */
9
24
  function injectUmoEmbedStyles() {
10
25
  if (typeof document === 'undefined') return
@@ -19,6 +34,22 @@ function injectUmoEmbedStyles() {
19
34
  .umo-status-bar-button.umo-lang-button {
20
35
  display: none !important;
21
36
  }
37
+ /* 嵌入场景:彻底禁用 UMO/TDesign 内置 loading(组件 + 遮罩 + 全屏服务残留节点) */
38
+ .umo-loading,
39
+ .umo-loading--visible,
40
+ .umo-loading--full,
41
+ .umo-loading--center,
42
+ .umo-loading--lock,
43
+ .umo-loading__overlay,
44
+ .umo-loading__fullscreen,
45
+ .umo-loading__gradient,
46
+ .umo-loading__text,
47
+ .umo-icon-loading,
48
+ body > .umo-loading__fullscreen {
49
+ display: none !important;
50
+ visibility: hidden !important;
51
+ pointer-events: none !important;
52
+ }
22
53
  `
23
54
  document.head.appendChild(style)
24
55
  }
@@ -44,6 +75,9 @@ export function installUmoEditorApp(app?: App | null) {
44
75
  } catch {
45
76
  // 宿主或兄弟插件已安装 TDesign
46
77
  }
78
+ // 运行时“删除”UMO 内置 loading:空组件 + 空 $loading 服务(不碰 v-loading 指令,避免影响 Element Plus)
79
+ app.component('TLoading', UmoLoadingNoop)
80
+ app.config.globalProperties.$loading = umoLoadingServiceNoop
47
81
  tdesignApps.add(app)
48
82
  }
49
83
 
@@ -3,7 +3,8 @@
3
3
 
4
4
  @-moz-document url-prefix() {
5
5
  scrollbar-color: var(--umo-scrollbar-thumb-color) transparent;
6
- scrollbar-width: thin;
6
+ /* 勿用 thin:Chromium 会压过 ::-webkit-scrollbar 的自定义宽度 */
7
+ scrollbar-width: auto;
7
8
  }
8
9
 
9
10
  &::-webkit-scrollbar {
@@ -59,10 +59,10 @@
59
59
  --umo-content-code-family:
60
60
  Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace;
61
61
 
62
- // 滚动条
63
- --umo-scrollbar-size: 8px;
64
- --umo-scrollbar-thumb-color: rgba(0, 0, 0, 0.1);
65
- --umo-scrollbar-thumb-hover-color: rgba(0, 0, 0, 0.3);
62
+ // 滚动条(与系统 --adtec-scrollbar-* / vxe 对齐)
63
+ --umo-scrollbar-size: var(--adtec-scrollbar-size, 10px);
64
+ --umo-scrollbar-thumb-color: var(--adtec-scrollbar-thumb, rgba(144, 147, 153, 0.55));
65
+ --umo-scrollbar-thumb-hover-color: var(--adtec-scrollbar-thumb-hover, rgba(144, 147, 153, 0.8));
66
66
  }
67
67
 
68
68
  [theme-mode='dark'] {
@@ -92,6 +92,7 @@
92
92
  --umo-content-text-color: #000;
93
93
 
94
94
  // 滚动条
95
- --umo-scrollbar-thumb-color: rgba(255, 255, 255, 0.3);
96
- --umo-scrollbar-thumb-hover-color: rgba(255, 255, 255, 0.45);
95
+ --umo-scrollbar-size: 10px;
96
+ --umo-scrollbar-thumb-color: rgba(255, 255, 255, 0.55);
97
+ --umo-scrollbar-thumb-hover-color: rgba(255, 255, 255, 0.8);
97
98
  }
@@ -17,9 +17,19 @@ import elementPlus, {
17
17
  ElDrawer,
18
18
  ElSelect,
19
19
  ElTreeSelect,
20
+ ElDatePicker,
21
+ ElCascader,
20
22
  ElTable,
21
23
  ElTooltip,
22
24
  } from 'element-plus'
25
+
26
+ /**
27
+ * vxe 单元格编辑时,Element 下拉/日期面板默认 teleport 到 body。
28
+ * 点击选项会被 vxe 判定为“单元格外点击”并 clearEdit,导致间歇性选不中。
29
+ * 官方约定:弹出层加 class `vxe-table--ignore-clear` 即可跳过该清理。
30
+ * 非 vxe 场景加此 class 无副作用。
31
+ */
32
+ const VXE_IGNORE_CLEAR_POPPER = 'vxe-table--ignore-clear'
23
33
  ElPagination.props.background = {
24
34
  type: Boolean,
25
35
  default: true,
@@ -72,10 +82,26 @@ ElSelect.props.fitInputWidth = {
72
82
  type: Boolean,
73
83
  default: false,
74
84
  }
85
+ ElSelect.props.popperClass = {
86
+ type: String,
87
+ default: VXE_IGNORE_CLEAR_POPPER,
88
+ }
75
89
  ElTreeSelect.props.fitInputWidth = {
76
90
  type: Boolean,
77
91
  default: false,
78
92
  }
93
+ ElTreeSelect.props.popperClass = {
94
+ type: String,
95
+ default: VXE_IGNORE_CLEAR_POPPER,
96
+ }
97
+ ElDatePicker.props.popperClass = {
98
+ type: String,
99
+ default: VXE_IGNORE_CLEAR_POPPER,
100
+ }
101
+ ElCascader.props.popperClass = {
102
+ type: String,
103
+ default: VXE_IGNORE_CLEAR_POPPER,
104
+ }
79
105
  ElTable.props.showOverflowTooltip = {
80
106
  type: Boolean,
81
107
  default: true,
@@ -6,15 +6,35 @@ import {
6
6
 
7
7
  import VxeUIPluginRenderElement from '@vxe-ui/plugin-render-element'
8
8
  import '@vxe-ui/plugin-render-element/dist/style.css'
9
- import VxeUIPluginExportXLSX from '@vxe-ui/plugin-export-xlsx'
9
+ // 注意:经 umoCjsVirtual 转换后,导出插件的「真插件」是具名导出(带 .install),
10
+ // default 只是包装对象 { VxeUIPluginExportXLSX, default }(无 .install)。
11
+ // 用 default 导入会导致 VxeUI.use() 空转 → 导出报「不支持的文件类型 xlsx/pdf」。必须用具名导入。
12
+ import { VxeUIPluginExportXLSX } from '@vxe-ui/plugin-export-xlsx'
10
13
  import ExcelJS from 'exceljs'
11
14
  import 'vxe-pc-ui/lib/style.css'
12
15
  import '../css/vxeTableUI/all.scss'
13
- import VxeUIPluginExportPDF from '@vxe-ui/plugin-export-pdf'
16
+ import { VxeUIPluginExportPDF } from '@vxe-ui/plugin-export-pdf'
14
17
  import { jsPDF } from 'jspdf'
15
18
  // 导入默认的语言(使用 es 构建,避免 lib CJS 在 Vite 下无 default 导出)
16
19
  import zhCN from 'vxe-table/es/locale/lang/zh-CN'
17
20
 
21
+ /**
22
+ * 导出插件(Excel/PDF)全局注册一次。
23
+ * ExcelJS / jsPDF / 插件均已在本文件顶部静态引入,注册与否不影响打包体积。
24
+ * 过去按 enableExcel/enablePdf 逐页 gating,导致注册依赖页面访问顺序:
25
+ * 直连未开启导出的页面时 VxeUI 未注册 xlsx,导出报「不支持的文件类型 "xlsx"」。
26
+ * 改为无条件注册后,任意页面、任意访问顺序均可导出。
27
+ */
28
+ let vxeExportPluginsRegistered = false
29
+ function registerVxeExportPlugins() {
30
+ if (vxeExportPluginsRegistered) return
31
+ vxeExportPluginsRegistered = true
32
+ VxeUI.use(VxeUIPluginExportXLSX, { ExcelJS })
33
+ VxeUI.use(VxeUIPluginExportPDF, { jsPDF })
34
+ }
35
+ // 模块加载即注册,确保任何 grid 创建前 xlsx/pdf 类型已可用
36
+ registerVxeExportPlugins()
37
+
18
38
  /**
19
39
  * 局部初始化 vxe-table 插件与配置
20
40
  */
@@ -29,8 +49,8 @@ export function initVxeTableInPage(
29
49
  VxeUI.component(VxeTooltip)
30
50
  // 局部注册插件
31
51
  enableElementPlus && VxeUI.use(VxeUIPluginRenderElement)
32
- enableExcel && VxeUI.use(VxeUIPluginExportXLSX, { ExcelJS })
33
- enablePdf && VxeUI.use(VxeUIPluginExportPDF, { jsPDF })
52
+ // 导出插件已在模块级全局注册(enableExcel/enablePdf 仅保留签名兼容)
53
+ registerVxeExportPlugins()
34
54
 
35
55
  // 设置表格配置(可复制你在 VxeTableConfig.ts 中的配置)
36
56
  VxeUI.setConfig({
@@ -213,8 +233,7 @@ export function initVxeTableInPage(
213
233
  oSize: 2,
214
234
  },
215
235
  scrollbarConfig: {
216
- // width: 0,
217
- // height: 0
236
+ // --adtec-vxe-scrollbar-size 一致;JS 用此值预留 scroll-x/y-virtual 空间
218
237
  },
219
238
  },
220
239
  grid: {
@@ -1226,10 +1226,11 @@ $loading: map.merge(
1226
1226
  $scrollbar: () !default;
1227
1227
  $scrollbar: map.merge(
1228
1228
  (
1229
- 'opacity': 0.3,
1230
- 'bg-color': getCssVar('text-color-secondary'),
1231
- 'hover-opacity': 0.5,
1232
- 'hover-bg-color': getCssVar('text-color-secondary'),
1229
+ /* 与 vxe 实心条对齐:不透明,避免半透明看起来更细 */
1230
+ 'opacity': 1,
1231
+ 'bg-color': rgba(144, 147, 153, 0.55),
1232
+ 'hover-opacity': 1,
1233
+ 'hover-bg-color': rgba(144, 147, 153, 0.8),
1233
1234
  ),
1234
1235
  $scrollbar
1235
1236
  );
@@ -22,20 +22,20 @@
22
22
 
23
23
  // Scrollbar
24
24
  @mixin scroll-bar {
25
- $scrollbar-thumb-background: getCssVar('text-color', 'disabled');
26
- $scrollbar-track-background: getCssVar('fill-color', 'blank');
25
+ $scrollbar-thumb-background: var(--adtec-scrollbar-thumb, rgba(144, 147, 153, 0.55));
26
+ $scrollbar-track-background: transparent;
27
27
 
28
28
  &::-webkit-scrollbar {
29
29
  z-index: 11;
30
- width: 6px;
30
+ width: var(--adtec-scrollbar-size, 10px);
31
31
 
32
32
  &:horizontal {
33
- height: 6px;
33
+ height: var(--adtec-scrollbar-size, 10px);
34
34
  }
35
35
 
36
36
  &-thumb {
37
- border-radius: 5px;
38
- width: 6px;
37
+ border-radius: 6px;
38
+ width: var(--adtec-scrollbar-size, 10px);
39
39
  background: $scrollbar-thumb-background;
40
40
  }
41
41
 
@@ -48,7 +48,7 @@
48
48
 
49
49
  &-piece {
50
50
  background: $scrollbar-track-background;
51
- width: 6px;
51
+ width: var(--adtec-scrollbar-size, 10px);
52
52
  }
53
53
  }
54
54
  }
@@ -59,10 +59,10 @@
59
59
  right: 2px;
60
60
  bottom: 2px;
61
61
  z-index: 1;
62
- border-radius: 4px;
62
+ border-radius: 6px;
63
63
 
64
64
  @include when(vertical) {
65
- width: 6px;
65
+ width: var(--adtec-scrollbar-size, 10px);
66
66
  top: 2px;
67
67
 
68
68
  > div {
@@ -71,7 +71,7 @@
71
71
  }
72
72
 
73
73
  @include when(horizontal) {
74
- height: 6px;
74
+ height: var(--adtec-scrollbar-size, 10px);
75
75
  left: 2px;
76
76
 
77
77
  > div {
@@ -79,34 +79,54 @@
79
79
  overflow-x: scroll;
80
80
  }
81
81
 
82
- /* 仅显示外层滚动条:鼠标进入表格显示,移出隐藏 */
82
+ /**
83
+ * vxe 4.13 滚动条自定义粗细(可精确到 px):
84
+ * 关键是 ::-webkit-scrollbar 上的 -webkit-appearance: none。
85
+ * macOS/Chromium 默认用 overlay 细条,会忽略 width/height;
86
+ * 一旦 appearance:none,就切换为经典滚动条,尊重此处的 px 与滑块样式。
87
+ * 故不写 scrollbar-width(避免退回 auto/overlay),只走 webkit 伪元素。
88
+ *
89
+ * 自动隐藏:默认滑块/轨道透明(隐藏),鼠标悬停 vxe 表格时才显示。
90
+ * 仍保留 appearance:none 的 8px 占位(is--scroll-x/y 预留),故无布局跳动、不遮内容。
91
+ */
83
92
  .vxe-table--scroll-x-handle,
84
93
  .vxe-table--scroll-y-handle {
85
- scrollbar-width: none;
86
- -ms-overflow-style: none;
94
+ -ms-overflow-style: auto;
95
+
87
96
  &::-webkit-scrollbar {
88
- width: 8px;
89
- height: 8px;
97
+ -webkit-appearance: none;
98
+ appearance: none;
99
+ width: var(--adtec-vxe-scrollbar-size, 8px);
100
+ height: var(--adtec-vxe-scrollbar-size, 8px);
90
101
  background: transparent;
91
102
  }
92
103
  &::-webkit-scrollbar-thumb {
93
104
  background: transparent;
94
- border-radius: 4px;
105
+ border-radius: 6px;
95
106
  }
96
107
  &::-webkit-scrollbar-track {
97
108
  background: transparent;
98
109
  }
99
110
  }
100
111
 
112
+ /* 鼠标悬停在 vxe 表格上时才显示滚动条滑块(移出即隐藏) */
101
113
  .vxe-table:hover {
114
+ .vxe-table--scroll-x-handle::-webkit-scrollbar-thumb,
115
+ .vxe-table--scroll-y-handle::-webkit-scrollbar-thumb {
116
+ background: #c0c4cc;
117
+ }
118
+ .vxe-table--scroll-x-handle::-webkit-scrollbar-thumb:hover,
119
+ .vxe-table--scroll-y-handle::-webkit-scrollbar-thumb:hover {
120
+ background: #909399;
121
+ }
122
+ }
123
+
124
+ /* Firefox 无 ::-webkit-scrollbar:退而用 thin(无法精确到 px) */
125
+ @supports not selector(::-webkit-scrollbar) {
102
126
  .vxe-table--scroll-x-handle,
103
127
  .vxe-table--scroll-y-handle {
104
128
  scrollbar-width: thin;
105
- scrollbar-color: #DDDEE0 transparent;
106
- }
107
- .vxe-table--scroll-x-handle::-webkit-scrollbar-thumb,
108
- .vxe-table--scroll-y-handle::-webkit-scrollbar-thumb {
109
- background: #DDDEE0;
129
+ scrollbar-color: #c0c4cc transparent;
110
130
  }
111
131
  }
112
132
 
@@ -603,11 +623,28 @@
603
623
  }
604
624
  }
605
625
  }
626
+ /**
627
+ * 滚动条布局:
628
+ * - virtual 默认 0,由 JS(scrollbarConfig)写入真实高度/宽度(禁止 !important 压死)
629
+ * - handle 粗细由 --adtec-vxe-scrollbar-size 控制(默认 8px)
630
+ */
606
631
  .vxe-table--scroll-x-virtual {
607
- height: 0 !important;
632
+ height: 0;
608
633
  }
609
634
  .vxe-table--scroll-y-virtual {
610
- width: 0px !important;
635
+ width: 0;
636
+ }
637
+ /**
638
+ * 有滚动条时按 8px 预留占位:
639
+ * scroll-x/y-handle 是 position:absolute 浮层,appearance:none 后为 8px 实体条。
640
+ * 若虚拟条 height/width 为 0,绝对定位的滚动条会溢出盖住最后一行/最右列。
641
+ * 仅在 is--scroll-x/y(确有溢出)时预留,空表不留缝。
642
+ */
643
+ &.is--scroll-x .vxe-table--scroll-x-virtual {
644
+ height: var(--adtec-vxe-scrollbar-size, 8px);
645
+ }
646
+ &.is--scroll-y .vxe-table--scroll-y-virtual {
647
+ width: var(--adtec-vxe-scrollbar-size, 8px);
611
648
  }
612
649
  .vxe-table--scroll-x-virtual,
613
650
  .vxe-table--scroll-y-virtual {
@@ -635,10 +672,10 @@
635
672
  .vxe-table--scroll-x-handle {
636
673
  overflow-y: hidden;
637
674
  overflow-x: scroll;
638
- height: 8px;
675
+ height: var(--adtec-vxe-scrollbar-size, 8px);
639
676
  }
640
677
  .vxe-table--scroll-x-wrapper {
641
- height: 8px;
678
+ height: 100%;
642
679
  }
643
680
  .vxe-table--scroll-y-handle,
644
681
  .vxe-table--scroll-y-wrapper {
@@ -650,7 +687,7 @@
650
687
  .vxe-table--scroll-y-handle {
651
688
  overflow-y: scroll;
652
689
  overflow-x: hidden;
653
- width: 8px;
690
+ width: var(--adtec-vxe-scrollbar-size, 8px);
654
691
  height: 100%;
655
692
  }
656
693
  .vxe-table--scroll-x-space {
@@ -925,10 +962,23 @@
925
962
  border-collapse: separate;
926
963
  table-layout: fixed;
927
964
  }
928
- .vxe-table--render-wrapper{
929
- height:100%;
965
+ .vxe-table--render-wrapper {
966
+ height: 100%;
967
+ display: flex;
968
+ flex-direction: column;
969
+ min-height: 0;
970
+ overflow: hidden;
971
+ /**
972
+ * 项目 height:100% 表格必需:layout 用 flex 收缩,
973
+ * 把底部留给官方 scroll-x-virtual 预留区,避免 100%+18px 被裁掉。
974
+ */
930
975
  .vxe-table--layout-wrapper {
931
- height:100%
976
+ flex: 1 1 auto;
977
+ min-height: 0;
978
+ height: auto;
979
+ }
980
+ .vxe-table--scroll-x-virtual {
981
+ flex: 0 0 auto;
932
982
  }
933
983
  }
934
984
  &:not(.is--empty) {
@@ -1211,7 +1261,7 @@
1211
1261
  &::after {
1212
1262
  bottom: 0;
1213
1263
  height: calc(100% + var(--vxe-ui-table-border-width));
1214
- //border-top: var(--vxe-ui-table-border-width) solid var(--vxe-ui-table-border-color);
1264
+ border-top: var(--vxe-ui-table-border-width) solid var(--vxe-ui-table-border-color);
1215
1265
  }
1216
1266
  }
1217
1267
  }