vite-uni-dev-tool 0.0.11 → 0.0.12

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.
Files changed (38) hide show
  1. package/README.md +55 -1
  2. package/dev/components/ConsoleList/ConsoleItem.vue +24 -3
  3. package/dev/components/ConsoleList/RunJSInput.vue +3 -1
  4. package/dev/components/ConsoleList/index.vue +11 -2
  5. package/dev/components/DevTool/index.vue +37 -31
  6. package/dev/components/DevToolButton/index.vue +9 -12
  7. package/dev/components/DevToolTitle/index.vue +2 -2
  8. package/dev/components/DevToolWindow/index.vue +32 -16
  9. package/dev/components/JsonPretty/index.vue +2 -0
  10. package/dev/components/NetworkList/NetworkDetail.vue +3 -6
  11. package/dev/components/NetworkList/NetworkItem.vue +21 -8
  12. package/dev/components/NetworkList/index.vue +15 -2
  13. package/dev/components/RouteList/index.vue +12 -1
  14. package/dev/components/SettingList/index.vue +2 -5
  15. package/dev/components/SourceCode/index.vue +231 -0
  16. package/dev/components/UniEvent/UniEventItem.vue +4 -2
  17. package/dev/components/UniEvent/index.vue +7 -3
  18. package/dev/components/UploadList/UploadDetail.vue +3 -7
  19. package/dev/components/UploadList/UploadItem.vue +7 -1
  20. package/dev/components/UploadList/index.vue +15 -2
  21. package/dev/components/VirtualListPro/index.vue +67 -4
  22. package/dev/components/VuexList/index.vue +2 -2
  23. package/dev/components/WebSocket/WebSocketItem.vue +7 -2
  24. package/dev/components/WebSocket/WebSocketList.vue +3 -6
  25. package/dev/components/WebSocket/index.vue +15 -2
  26. package/dev/const.ts +11 -13
  27. package/dev/devEvent/index.ts +20 -16
  28. package/dev/devStore/index.ts +27 -13
  29. package/dev/devToolInfo/index.ts +26 -0
  30. package/dev/plugins/uniDevTool/uniDevTool.d.ts +9 -1
  31. package/dev/plugins/uniDevTool/uniDevTool.d.ts.map +1 -1
  32. package/dev/plugins/uniDevTool/uniDevTool.js +36 -36
  33. package/dev/plugins/uniGlobalComponents/uniGlobalComponents.js +7 -7
  34. package/dev/type.ts +27 -0
  35. package/dev/utils/index.ts +5 -0
  36. package/dev/utils/language.ts +8 -3
  37. package/dev/utils/object.ts +10 -2
  38. package/package.json +1 -1
@@ -18,14 +18,19 @@
18
18
  </Tag>
19
19
  </view>
20
20
 
21
- <VirtualListPro :data="networkList" :pageSize="10" className="network-list">
21
+ <VirtualListPro
22
+ :data="networkList"
23
+ :pageSize="15"
24
+ :height="height"
25
+ className="network-list"
26
+ >
22
27
  <template v-slot="{ list, start }">
23
28
  <AutoSize
24
29
  v-for="(item, index) in list"
25
30
  :index="start + index"
26
31
  :key="start + index"
27
32
  >
28
- <NetworkItem :network="item" />
33
+ <NetworkItem :network="item" :zIndex="zIndex" />
29
34
  </AutoSize>
30
35
  <Empty v-if="!networkList || networkList.length === 0" />
31
36
  </template>
@@ -40,11 +45,13 @@ import FilterInput from '../FilterInput/index.vue';
40
45
  import type { DevTool } from '../../type';
41
46
  import VirtualListPro from '../VirtualListPro/index.vue';
42
47
  import AutoSize from '../VirtualListPro/AutoSize.vue';
48
+ import { onMounted, ref } from 'vue';
43
49
 
44
50
  defineProps<{
45
51
  currentNetworkType: string;
46
52
  networkList: DevTool.NetworkItem[];
47
53
  modelValue: string;
54
+ zIndex?: number;
48
55
  }>();
49
56
 
50
57
  const emit = defineEmits<{
@@ -93,6 +100,12 @@ const networkFilterItems = [
93
100
  function onChoose(type: string) {
94
101
  emit('choose', type);
95
102
  }
103
+
104
+ const height = ref(0);
105
+ onMounted(() => {
106
+ const { windowHeight } = uni.getWindowInfo();
107
+ height.value = windowHeight - 32 - 32;
108
+ });
96
109
  </script>
97
110
  <style scoped>
98
111
  .network-content {
@@ -11,7 +11,12 @@
11
11
  <Tag mode="clear" @click="onRefresh">刷新</Tag>
12
12
  </view>
13
13
 
14
- <VirtualListPro :data="routeList" :pageSize="10" className="route-list">
14
+ <VirtualListPro
15
+ :data="routeList"
16
+ :pageSize="15"
17
+ :height="height"
18
+ className="route-list"
19
+ >
15
20
  <template v-slot="{ list, start }">
16
21
  <AutoSize
17
22
  v-for="(item, index) in list"
@@ -47,6 +52,7 @@ import FilterInput from '../FilterInput/index.vue';
47
52
  import type { DevTool } from '../../type';
48
53
  import VirtualListPro from '../VirtualListPro/index.vue';
49
54
  import AutoSize from '../VirtualListPro/AutoSize.vue';
55
+ import { onMounted, ref } from 'vue';
50
56
 
51
57
  defineProps<{ routeList: DevTool.Page[]; modelValue?: string }>();
52
58
  const emit = defineEmits<{
@@ -62,6 +68,11 @@ function onGoTo(page: DevTool.Page) {
62
68
  function onRefresh() {
63
69
  emit('routeRefresh');
64
70
  }
71
+ const height = ref(0);
72
+ onMounted(() => {
73
+ const { windowHeight } = uni.getWindowInfo();
74
+ height.value = windowHeight - 32 - 32;
75
+ });
65
76
  </script>
66
77
  <style scoped>
67
78
  .route-content {
@@ -6,7 +6,7 @@
6
6
  <view class="setting-row">
7
7
  <view>显示调试按钮:</view>
8
8
  <Checkbox
9
- v-model="setting.showDevButton"
9
+ :modelValue="devToolVisible"
10
10
  @change="onChangeShowDevButton"
11
11
  />
12
12
  </view>
@@ -122,13 +122,11 @@ import { reactive } from 'vue';
122
122
  import Checkbox from '../Checkbox/index.vue';
123
123
  import DButton from '../Button/index.vue';
124
124
  import DevToolTitle from '../DevToolTitle/index.vue';
125
- const props = defineProps<{
125
+ defineProps<{
126
126
  devToolVisible?: boolean;
127
127
  sizeFormat?: string;
128
128
  }>();
129
129
  const setting = reactive({
130
- showDevButton: props.devToolVisible,
131
-
132
130
  restartDevTool: false,
133
131
  restartApp: false,
134
132
  exportLog: false,
@@ -166,7 +164,6 @@ function onChangeShowDevButton(show: boolean) {
166
164
  emit('showDevButton', show);
167
165
  }
168
166
  function onRestartDevTool(restart: boolean) {
169
- console.log('restart: ', restart);
170
167
  restart && emit('restartDevTool');
171
168
  }
172
169
 
@@ -0,0 +1,231 @@
1
+ <template>
2
+ <view class="dev-tool-code" :style="{ zIndex: zIndex }">
3
+ <view class="dev-tool-code-control">
4
+ <FilterInput
5
+ v-model="modelValue"
6
+ style="width: 100%"
7
+ @search="onSearch"
8
+ />
9
+ <CloseButton style="margin-left: auto" @click="onClose" />
10
+ </view>
11
+ <view class="dev-tool-code-title">{{ fileName }}</view>
12
+ <scroll-view
13
+ scroll-y="true"
14
+ scroll-x="true"
15
+ class="dev-tool-code-list"
16
+ scroll-with-animation="true"
17
+ :scroll-top="scrollTop"
18
+ :scroll-into-view="scrollIntoView"
19
+ >
20
+ <view
21
+ v-for="(code, index) in codes"
22
+ :id="`dev-tool-code-item-${index}`"
23
+ :key="index"
24
+ :class="`dev-tool-code-item ${index === activeRowCol.activeRow ? 'dev-tool-code-item-active' : ''}`"
25
+ >
26
+ <view class="dev-tool-code-item-index">
27
+ {{ start + index + 1 }}
28
+ </view>
29
+
30
+ <view class="dev-tool-code-item-content" v-html="code"></view>
31
+ </view>
32
+ <Empty v-if="!codes || codes.length === 0" />
33
+ </scroll-view>
34
+ </view>
35
+ </template>
36
+ <script lang="ts" setup>
37
+ import { computed, ref, nextTick, onMounted } from 'vue';
38
+ import FilterInput from '../FilterInput/index.vue';
39
+ import CloseButton from '../CloseButton/index.vue';
40
+ import Empty from '../Empty/index.vue';
41
+ import { escapeHTML, hightLight, isAndroid, parseStock } from '../../utils';
42
+
43
+ const props = defineProps<{
44
+ url: string;
45
+ sourceFileServers?: string[];
46
+ mode?: string;
47
+ zIndex?: number;
48
+ }>();
49
+
50
+ const emit = defineEmits<{ (e: 'close'): void }>();
51
+
52
+ const modelValue = ref('');
53
+ const scrollTop = ref(0);
54
+ const fileName = computed(() => {
55
+ const name =
56
+ props?.url?.split('/')?.pop()?.replace(/\)|\(/, '') ?? '文件名称未知';
57
+ return name;
58
+ });
59
+
60
+ const activeRowCol = ref({ row: -1, col: -1, activeRow: -1 });
61
+
62
+ let backupCodes: string[] = [];
63
+
64
+ const codes = ref<string[]>([]);
65
+
66
+ const scrollIntoView = ref('');
67
+
68
+ const start = computed(() => {
69
+ return activeRowCol.value.row - 20 > 0 ? activeRowCol.value.row - 20 : 0;
70
+ });
71
+
72
+ function onClose() {
73
+ emit('close');
74
+ }
75
+
76
+ function onSearch(value: string) {
77
+ codes.value = backupCodes.map((code) => {
78
+ return hightLight(code, value);
79
+ });
80
+ }
81
+
82
+ let index = 0;
83
+ function getCode(url: string, i: number = 0) {
84
+ let allUrl = url;
85
+ // 平台判断
86
+ if (isAndroid()) {
87
+ if (!props.sourceFileServers?.[i]) {
88
+ index = 0;
89
+ return;
90
+ }
91
+
92
+ allUrl = props.sourceFileServers?.[i] + '/src/' + url;
93
+ }
94
+
95
+ uni.showLoading({ mask: true });
96
+ uni.request({
97
+ url: allUrl,
98
+ success: (res) => {
99
+ if (typeof res.data === 'string') {
100
+ // 为什么要注释掉?
101
+ // 在 Android 识别到标签后会进行重启,导致代码无法显示
102
+ // TODO: 还有其它原因导致重启
103
+ const str = res.data
104
+ ?.replace(/<jscript/, '// [DevTool] 注释 <javascript')
105
+ ?.replace(/<\/script>/, '// [DevTool] 注释 </javascript>')
106
+ ?.replace(/<style/, '// [DevTool] 注释 <style')
107
+ ?.replace(/<\/style>/, '// [DevTool] 注释 </style>');
108
+ backupCodes = escapeHTML(str ?? '')
109
+ .toString()
110
+ .split('\n');
111
+
112
+ const start =
113
+ activeRowCol.value.row - 20 > 0 ? activeRowCol.value.row - 20 : 0;
114
+
115
+ const end =
116
+ activeRowCol.value.row + 20 > backupCodes.length
117
+ ? backupCodes.length
118
+ : activeRowCol.value.row + 20;
119
+
120
+ // backupCodes.slice(start, end);
121
+
122
+ codes.value = backupCodes.slice(start, end);
123
+
124
+ activeRowCol.value.activeRow = activeRowCol.value.row - start;
125
+
126
+ nextTick(() => {
127
+ scrollIntoView.value = `dev-tool-code-item-${activeRowCol.value.activeRow}`;
128
+ });
129
+ }
130
+ },
131
+ fail: (err) => {
132
+ index++;
133
+ getCode(url, index);
134
+ uni.showToast({ icon: 'none', title: '正在重新尝试中...' });
135
+ },
136
+ complete: () => {
137
+ uni.hideLoading();
138
+ },
139
+ });
140
+ }
141
+
142
+ /** 开发环境获取源代码 */
143
+ function getSourceCodeDev(url: string) {
144
+ if (!url) {
145
+ uni.showToast({ icon: 'none', title: '[DevTool] url 处理异常' });
146
+ uni?.__dev__console?.log('[DevTool] url 处理异常');
147
+ return;
148
+ }
149
+
150
+ getCode(url, index);
151
+ }
152
+
153
+ onMounted(() => {
154
+ let url = props?.url;
155
+
156
+ const { path, col, row } = parseStock(props?.url ?? '');
157
+
158
+ if (path) {
159
+ url = path;
160
+ }
161
+
162
+ activeRowCol.value.col = col;
163
+ activeRowCol.value.row = row;
164
+
165
+ if (props.mode === 'development') {
166
+ // 开发环境查看源码
167
+ getSourceCodeDev(url);
168
+ } else if (props.mode === 'production') {
169
+ // TODO 生产环境查看源码
170
+ }
171
+ });
172
+ </script>
173
+ <style scoped>
174
+ .dev-tool-code {
175
+ position: fixed;
176
+ width: 100vw;
177
+ height: 100vh;
178
+ z-index: 1001;
179
+ top: 0;
180
+ left: 0;
181
+ padding: 0 16px;
182
+
183
+ background-color: rgba(255, 255, 255, 0.95);
184
+ box-sizing: border-box;
185
+ color: #000;
186
+ }
187
+
188
+ .dev-tool-code-control {
189
+ display: flex;
190
+ align-items: center;
191
+ gap: 12px;
192
+ height: 32px;
193
+ border-bottom: 1px solid var(--dev-tool-border-color);
194
+ box-sizing: border-box;
195
+ }
196
+
197
+ .dev-tool-code-title {
198
+ height: 32px;
199
+ line-height: 32px;
200
+ margin-bottom: 4px;
201
+ border-bottom: 1px solid var(--dev-tool-border-color);
202
+ box-sizing: border-box;
203
+ white-space: nowrap;
204
+ overflow: auto;
205
+ }
206
+
207
+ .dev-tool-code-list {
208
+ height: calc(100% - 68px);
209
+ }
210
+
211
+ .dev-tool-code-item {
212
+ display: flex;
213
+ align-items: center;
214
+ height: 28px;
215
+ }
216
+ .dev-tool-code-item-active {
217
+ color: #fff;
218
+ background-color: var(--dev-tool-main-color);
219
+ }
220
+
221
+ .dev-tool-code-item-index {
222
+ flex-shrink: 0;
223
+ width: 20px;
224
+ margin-right: 8px;
225
+ text-align: right;
226
+ }
227
+
228
+ .dev-tool-code-item-content {
229
+ white-space: pre;
230
+ }
231
+ </style>
@@ -24,18 +24,19 @@
24
24
  {{ eventItem.stack }}
25
25
  </view>
26
26
 
27
- <Code
27
+ <SourceCode
28
28
  v-if="openCode && eventItem.stack"
29
29
  :url="eventItem.stack"
30
30
  :sourceFileServers="sourceFileServers"
31
31
  :mode="mode"
32
+ :zIndex="zIndex"
32
33
  @close="onCloseCode"
33
34
  />
34
35
  </view>
35
36
  </template>
36
37
  <script lang="ts" setup>
37
38
  import Tag from '../Tag/index.vue';
38
- import Code from '../Code/index.vue';
39
+ import SourceCode from '../SourceCode/index.vue';
39
40
  import type { DevTool } from '../../type';
40
41
  import { computed, ref } from 'vue';
41
42
  import { isAndroid, isMockWX } from '../../utils';
@@ -45,6 +46,7 @@ const props = defineProps<{
45
46
  mode?: string;
46
47
  useDevSource?: boolean;
47
48
  sourceFileServers?: string[];
49
+ zIndex?: number;
48
50
  }>();
49
51
 
50
52
  const openCode = ref(false);
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <view class="uni-event-content">
3
- <DevToolTitle style="padding: 0 16px">事件触发统计</DevToolTitle>
3
+ <DevToolTitle innerStyle="padding: 0 16px">事件触发统计</DevToolTitle>
4
4
  <view class="uni-event-statistics">
5
5
  <view class="uni-event-statistics-item">
6
6
  <view>on: </view>
@@ -27,8 +27,8 @@
27
27
  </Tag>
28
28
  </view>
29
29
  </view>
30
- <DevToolTitle style="padding: 0 16px"
31
- >事件触发列表
30
+ <DevToolTitle innerStyle="padding: 0 16px">
31
+ 事件触发列表
32
32
 
33
33
  <Tag mode="clear" style="margin-left: auto" @click="emit('clear')">
34
34
  清空
@@ -41,7 +41,9 @@
41
41
  :mode="mode"
42
42
  :useDevSource="useDevSource"
43
43
  :sourceFileServers="sourceFileServers"
44
+ :zIndex="zIndex"
44
45
  />
46
+ <Empty v-if="!eventList || eventList.length === 0"> </Empty>
45
47
  </view>
46
48
  </view>
47
49
  </template>
@@ -49,6 +51,7 @@
49
51
  import DevToolTitle from '../DevToolTitle/index.vue';
50
52
  import UniEventItem from './UniEventItem.vue';
51
53
  import Tag from '../Tag/index.vue';
54
+ import Empty from '../Empty/index.vue';
52
55
  import type { DevTool } from '@/dev/type';
53
56
 
54
57
  defineProps<{
@@ -57,6 +60,7 @@ defineProps<{
57
60
  useDevSource?: boolean;
58
61
  mode?: string;
59
62
  sourceFileServers?: string[];
63
+ zIndex?: number;
60
64
  }>();
61
65
 
62
66
  const emit = defineEmits<{
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <view class="upload-detail">
2
+ <view class="upload-detail" :style="{ zIndex: zIndex }">
3
3
  <view class="upload-detail-control">
4
4
  <Tag
5
5
  v-for="item in selectItems"
@@ -82,7 +82,7 @@ import Tag from '../Tag/index.vue';
82
82
  import Empty from '../Empty/index.vue';
83
83
  import CloseButton from '../CloseButton/index.vue';
84
84
  import type { DevTool } from '../../type';
85
- const props = defineProps<{ upload: DevTool.UploadItem }>();
85
+ const props = defineProps<{ upload: DevTool.UploadItem; zIndex?: number }>();
86
86
  const emit = defineEmits<{ (e: 'close'): void }>();
87
87
  const selectItems = [
88
88
  {
@@ -156,14 +156,10 @@ function onClose() {
156
156
  position: fixed;
157
157
  width: 100vw;
158
158
  height: 100vh;
159
- z-index: 1000;
159
+ z-index: 1001;
160
160
  top: 0;
161
161
  left: 0;
162
162
  padding: 0 16px;
163
- /* #ifdef H5 */
164
- padding: 50px 16px;
165
- /* #endif */
166
-
167
163
  background-color: rgba(255, 255, 255, 0.95);
168
164
  box-sizing: border-box;
169
165
  }
@@ -37,7 +37,12 @@
37
37
  </view>
38
38
  </view>
39
39
  <!-- <Transition name="slide-fade"> -->
40
- <UploadDetail v-if="showDetail" :upload="upload" @close="onClose" />
40
+ <UploadDetail
41
+ v-if="showDetail"
42
+ :upload="upload"
43
+ :zIndex="zIndex"
44
+ @close="onClose"
45
+ />
41
46
  <!-- </Transition> -->
42
47
  </template>
43
48
 
@@ -49,6 +54,7 @@ import { formatDate } from '../../utils';
49
54
  import type { DevTool } from '../../type';
50
55
  defineProps<{
51
56
  upload: DevTool.UploadItem;
57
+ zIndex?: number;
52
58
  }>();
53
59
  const showDetail = ref(false);
54
60
 
@@ -17,14 +17,19 @@
17
17
  {{ item.label }}
18
18
  </Tag>
19
19
  </view>
20
- <VirtualListPro :data="uploadList" :pageSize="10" className="upload-list">
20
+ <VirtualListPro
21
+ :data="uploadList"
22
+ :pageSize="15"
23
+ :height="height"
24
+ className="upload-list"
25
+ >
21
26
  <template v-slot="{ list, start }">
22
27
  <AutoSize
23
28
  v-for="(item, index) in list"
24
29
  :index="start + index"
25
30
  :key="start + index"
26
31
  >
27
- <UploadItem :upload="item" />
32
+ <UploadItem :upload="item" :zIndex="zIndex" />
28
33
  </AutoSize>
29
34
  <Empty v-if="!uploadList || uploadList.length === 0" />
30
35
  </template>
@@ -39,11 +44,13 @@ import FilterInput from '../FilterInput/index.vue';
39
44
  import type { DevTool } from '../../type';
40
45
  import VirtualListPro from '../VirtualListPro/index.vue';
41
46
  import AutoSize from '../VirtualListPro/AutoSize.vue';
47
+ import { onMounted, ref } from 'vue';
42
48
 
43
49
  defineProps<{
44
50
  currentUploadType: string;
45
51
  uploadList: DevTool.UploadItem[];
46
52
  modelValue: string;
53
+ zIndex: number;
47
54
  }>();
48
55
 
49
56
  const emit = defineEmits<{
@@ -82,6 +89,12 @@ const uploadFilterItems = [
82
89
  function onChoose(type: string) {
83
90
  emit('choose', type);
84
91
  }
92
+
93
+ const height = ref(0);
94
+ onMounted(() => {
95
+ const { windowHeight } = uni.getWindowInfo();
96
+ height.value = windowHeight - 32 - 32;
97
+ });
85
98
  </script>
86
99
  <style scoped>
87
100
  .upload-content {
@@ -1,15 +1,19 @@
1
1
  <template>
2
2
  <scroll-view
3
3
  :lower-threshold="preLodeHeight"
4
- :scroll-into-view="scrollIntoView"
5
4
  :scroll-with-animation="scrollWithAnimation"
6
5
  :class="['virtual-list', className]"
6
+ :style="style"
7
+ :scroll-into-view="innerScrollIntoView"
7
8
  scroll-y
8
9
  @scroll="onScroll"
9
10
  @scrolltolower="onScrollToLower"
10
11
  >
11
12
  <!-- 阈值判断 -->
12
- <view :style="{ height: `${state.currentHeight}px` }"></view>
13
+ <view
14
+ :id="placeholderId"
15
+ :style="{ height: `${state.currentHeight}px` }"
16
+ ></view>
13
17
  <view>
14
18
  <!-- 将可视数据传入到slot -->
15
19
  <slot
@@ -18,10 +22,20 @@
18
22
  :start="(state.current - 1) * props.pageSize"
19
23
  ></slot>
20
24
  </view>
25
+
26
+ <view
27
+ v-if="state.currentHeight > props.height && showBackTop"
28
+ class="virtual-back-top"
29
+ @click="onBackTop"
30
+ >
31
+
32
+ </view>
21
33
  </scroll-view>
22
34
  </template>
23
35
  <script lang="ts" setup>
24
- import { reactive, watch, onBeforeMount, provide } from 'vue';
36
+ import { nextTick } from 'vue';
37
+ import { uniqueId } from '../../utils';
38
+ import { reactive, watch, onBeforeMount, provide, computed, ref } from 'vue';
25
39
 
26
40
  const props = withDefaults(
27
41
  defineProps<{
@@ -43,6 +57,8 @@ const props = withDefaults(
43
57
  scrollIntoView?: string;
44
58
  /** 滚动动画 */
45
59
  scrollWithAnimation?: boolean;
60
+ /** 返回顶部 */
61
+ showBackTop?: boolean;
46
62
  }>(),
47
63
  {
48
64
  height: 400,
@@ -57,12 +73,17 @@ const state = reactive<{
57
73
  visitableData: any[];
58
74
  currentHeight: number;
59
75
  height: number;
76
+ scrollTop: number;
60
77
  }>({
61
78
  height: 0,
62
79
  current: 1,
63
80
  visitableData: [],
64
81
  currentHeight: 0,
82
+ scrollTop: 0,
65
83
  });
84
+
85
+ const placeholderId = uniqueId('virtual-placeholder-');
86
+
66
87
  /**
67
88
  * 每一项的高度
68
89
  */
@@ -70,6 +91,19 @@ const itemsHeight: number[] = [];
70
91
 
71
92
  provide('itemsHeight', itemsHeight);
72
93
 
94
+ const style = computed(() => {
95
+ return {
96
+ height:
97
+ typeof props.height === 'string' ? props.height : props.height + 'px',
98
+ };
99
+ });
100
+
101
+ const toView = ref('');
102
+
103
+ const innerScrollIntoView = computed(() => {
104
+ return toView.value || props.scrollIntoView;
105
+ });
106
+
73
107
  onBeforeMount(() => {
74
108
  // 初始渲染数据
75
109
  state.visitableData = props.data.slice(0, props.pageSize * 2);
@@ -171,5 +205,34 @@ function onSizeChange(index: number, height: number) {
171
205
  itemsHeight[index] = height;
172
206
  }
173
207
  provide('onSizeChange', onSizeChange);
208
+
209
+ /** 返回顶部 */
210
+ function onBackTop() {
211
+ toView.value = placeholderId;
212
+
213
+ nextTick(() => {
214
+ state.current = 1;
215
+ state.currentHeight = 0;
216
+ updateVisitableData('up');
217
+
218
+ toView.value = '';
219
+ });
220
+ }
174
221
  </script>
175
- <style scoped></style>
222
+ <style scoped>
223
+ .virtual-list {
224
+ position: relative;
225
+ }
226
+
227
+ .virtual-back-top {
228
+ position: sticky;
229
+ bottom: 20px;
230
+ left: 80%;
231
+ display: flex;
232
+ align-items: center;
233
+ justify-content: center;
234
+ width: 40px;
235
+ height: 40px;
236
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
237
+ }
238
+ </style>
@@ -12,7 +12,7 @@
12
12
  </view>
13
13
  </template>
14
14
  <script lang="ts" setup>
15
- import { computed, ref } from 'vue';
15
+ import { computed } from 'vue';
16
16
  import JsonPretty from '../JsonPretty/index.vue';
17
17
  import Empty from '../Empty/index.vue';
18
18
  const props = defineProps<{
@@ -39,7 +39,7 @@ function onUpdateData(data: Record<string, any>) {
39
39
  const firstKey = currentSelect?.path.split('.')?.slice(1)?.[0];
40
40
  emit('update:vuexList', data);
41
41
  emit('diffValue', {
42
- [firstKey]: data[firstKey]
42
+ [firstKey]: data[firstKey],
43
43
  });
44
44
  }
45
45
  function onNodeClick(node: any) {
@@ -34,7 +34,12 @@
34
34
  }}</view>
35
35
  </view>
36
36
 
37
- <WebSocketList v-if="showDetail" :ws="ws" @close="onClose" />
37
+ <WebSocketList
38
+ v-if="showDetail"
39
+ :ws="ws"
40
+ :zIndex="zIndex"
41
+ @close="onClose"
42
+ />
38
43
  </view>
39
44
  </template>
40
45
  <script lang="ts" setup>
@@ -45,7 +50,7 @@ import WebSocketList from './WebSocketList.vue';
45
50
  import { formatDate } from '../../utils';
46
51
  import type { DevTool } from '../../type';
47
52
 
48
- defineProps<{ ws: DevTool.WS }>();
53
+ defineProps<{ ws: DevTool.WS; zIndex?: number }>();
49
54
  const showDetail = ref(false);
50
55
 
51
56
  function onClose() {