xydata-tools 1.0.48 → 1.0.49

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/README.md CHANGED
@@ -3,50 +3,44 @@
3
3
  内网文档:[http://172.16.1.254:8090/display/UX/xydata-tools](http://172.16.1.254:8090/display/UX/xydata-tools)
4
4
 
5
5
  # xydata-tools 文档索引
6
-
7
6
 
8
- #### Web 端组件
7
+ > **注意**:如果您在 NPM 上查看此文档,链接可能无法正常工作。请访问 [GitLab 仓库](https://172.16.1.252/wuxiaohu/xydata-tools) 查看完整文档。
9
8
 
10
- - [附件上传组件](./docs/组件使用文档/附件上传组件.md)
9
+ #### Web 端组件
11
10
 
11
+ - **附件上传组件** - [查看文档](https://172.16.1.252/wuxiaohu/xydata-tools/-/blob/new/docs/组件使用文档/附件上传组件.md)
12
12
  - 支持图片、文件上传
13
13
  - 内置文件大小、格式校验
14
14
  - 支持预览功能
15
15
 
16
- - [附件下载组件](./docs/组件使用文档/附件下载组件.md)
17
-
16
+ - **附件下载组件** - [查看文档](https://172.16.1.252/wuxiaohu/xydata-tools/-/blob/new/docs/组件使用文档/附件下载组件.md)
18
17
  - 支持链接和流式文件下载
19
18
  - 兼容原生按钮功能
20
19
 
21
- - [数据字典组件](./docs/组件使用文档/数据字典.md)
22
-
20
+ - **数据字典组件** - [查看文档](https://172.16.1.252/wuxiaohu/xydata-tools/-/blob/new/docs/组件使用文档/数据字典.md)
23
21
  - 完整的数据字典管理功能
24
22
  - 支持分类管理
25
23
 
26
- - [组织机构组件](./docs/组件使用文档/组织机构.md)
27
-
24
+ - **组织机构组件** - [查看文档](https://172.16.1.252/wuxiaohu/xydata-tools/-/blob/new/docs/组件使用文档/组织机构.md)
28
25
  - 树形结构展示
29
26
  - 人员管理功能
30
27
 
31
28
  #### uni-app 组件
32
29
 
33
- - [MediaPicker - 媒体选择器](./docs/uniapp/MediaPicker.md)
34
- - [FilePicker - 文件选择器](./docs/uniapp/FilePicker.md)
35
-
36
- ### 模版使用文档
30
+ - **MediaPicker - 媒体选择器** - [查看文档](https://172.16.1.252/wuxiaohu/xydata-tools/-/blob/new/docs/uniapp/MediaPicker.md)
31
+ - **FilePicker - 文件选择器** - [查看文档](https://172.16.1.252/wuxiaohu/xydata-tools/-/blob/new/docs/uniapp/FilePicker.md)
37
32
 
38
- - [AAA 模版](./docs/模版使用文档/AAA模版.md)
33
+ #### 模版使用文档
39
34
 
35
+ - **AAA 模版** - [查看文档](https://172.16.1.252/wuxiaohu/xydata-tools/-/blob/new/docs/模版使用文档/AAA模版.md)
40
36
  - 适用场景:有独立登录页面,不支持统一登录
41
37
  - 包含:SecurityLayout、系统管理模块
42
38
 
43
- - [SSO 模版](./docs/模版使用文档/SSO模版.md)
44
-
39
+ - **SSO 模版** - [查看文档](https://172.16.1.252/wuxiaohu/xydata-tools/-/blob/new/docs/模版使用文档/SSO模版.md)
45
40
  - 适用场景:没有独立登录页面,支持统一登录
46
41
  - 包含:SecurityLayout、系统管理模块
47
42
 
48
- - [Both 模版](./docs/模版使用文档/Both模版.md)
49
-
43
+ - **Both 模版** - [查看文档](https://172.16.1.252/wuxiaohu/xydata-tools/-/blob/new/docs/模版使用文档/Both模版.md)
50
44
  - 适用场景:同时支持独立登录和统一登录
51
45
  - 包含:SecurityLayout
52
46
 
@@ -21,9 +21,6 @@ var BothSecurityLayout = function BothSecurityLayout(props) {
21
21
  var LOGIN_URI = AAALOGIN ? "".concat(window.publicPath, "user/login") : "".concat(window.publicPath);
22
22
  var pathName = window.location.pathname;
23
23
  useEffect(function () {
24
- console.error("构建参数,开发完成,记得删除!");
25
- console.log("ENV_DATA:", JSON.stringify(envData));
26
- console.log("service:", service);
27
24
  if (!token) {
28
25
  if (pathName.indexOf("/sso") >= 0 || !AAALOGIN) {
29
26
  setSessionStorage("r", window.location.href);
@@ -107,8 +107,8 @@
107
107
 
108
108
  <!-- 图片 -->
109
109
  <template v-else>
110
- <image v-if="file.type === 'image'" :src="file.url" mode="aspectFill"
111
- :style="{ borderRadius: itemBorderRadius + 'rpx' }" :lazy-load="true"
110
+ <image v-if="file.type === 'image'" :src="lazyLoadImageSrcs[i]" mode="aspectFill"
111
+ :style="{ borderRadius: itemBorderRadius + 'rpx' }" :id="componentId + '-imgview-' + i"
112
112
  @load="onMediaLoad('readonly-' + i)" @error="onMediaError('readonly-' + i)">
113
113
  </image>
114
114
 
@@ -147,9 +147,9 @@
147
147
  @click="handlePopupItemClick(file, i)">
148
148
 
149
149
  <!-- 图片 -->
150
- <image v-if="file.type === 'image'" :src="file.url" mode="aspectFill"
151
- :style="{ borderRadius: itemBorderRadius + 'rpx' }" @load="onMediaLoad('popup-' + i)"
152
- @error="onMediaError('popup-' + i)">
150
+ <image v-if="file.type === 'image'" :src="popupLazyLoadImageSrcs[i]" mode="aspectFill"
151
+ :style="{ borderRadius: itemBorderRadius + 'rpx' }" :id="componentId + '-popup-imgview-' + i"
152
+ @load="onMediaLoad('popup-' + i)" @error="onMediaError('popup-' + i)">
153
153
  </image>
154
154
 
155
155
  <!-- 视频 -->
@@ -334,8 +334,16 @@ export default {
334
334
  mediaLoadingStatus: {},
335
335
  fullscreenVideoSrc: '', // 专门用于全屏播放的视频源
336
336
  windowWidth: uni.getSystemInfoSync ? uni.getSystemInfoSync().windowWidth : 375,
337
+ lazyLoadImageSrcs: [], // 用于图片懒加载,存储进入视图的图片src
338
+ observer: null,
339
+ componentId: null, // 组件实例的唯一ID
340
+ popupLazyLoadImageSrcs: [], // 用于弹窗中图片懒加载,存储进入视图的图片src
341
+ popupObserver: null, // 弹窗图片懒加载观察器
337
342
  }
338
343
  },
344
+ created() {
345
+ this.componentId = 'mp-' + Date.now() + Math.random().toString(36).substr(2, 9);
346
+ },
339
347
  computed: {
340
348
  // ==================== 媒体类型判断 ====================
341
349
  /** 是否启用图片上传 */
@@ -475,12 +483,27 @@ export default {
475
483
  this.videoFileList = val || []
476
484
  },
477
485
  immediate: true
486
+ },
487
+ allFileList: {
488
+ handler() {
489
+ this.initLazyObserver(); // 当文件列表变化时重新初始化观察器
490
+ }
478
491
  }
479
492
  },
480
493
  mounted() {
481
494
  if (!this.uploadUrl) {
482
495
  this.actualUploadUrl = (getApp().globalData && getApp().globalData.uploadUrl) || ''
483
496
  }
497
+ this.initLazyObserver(); // 在mounted时初始化观察器
498
+ },
499
+ onShow() {
500
+ this.initLazyObserver();
501
+ },
502
+ beforeDestroy() {
503
+ if (this.observer) {
504
+ this.observer.disconnect();
505
+ this.observer = null;
506
+ }
484
507
  },
485
508
  methods: {
486
509
  // ==================== 事件监听辅助方法 ====================
@@ -1092,6 +1115,7 @@ export default {
1092
1115
  this.$nextTick(() => {
1093
1116
  setTimeout(() => {
1094
1117
  this.popupAnimated = true
1118
+ this.initPopupLazyObserver(); // 弹窗打开时初始化懒加载观察器
1095
1119
  }, 50)
1096
1120
  })
1097
1121
  },
@@ -1100,6 +1124,10 @@ export default {
1100
1124
  this.popupAnimated = false
1101
1125
  setTimeout(() => {
1102
1126
  this.popupVisible = false
1127
+ if (this.popupObserver) {
1128
+ this.popupObserver.disconnect(); // 弹窗关闭时断开观察器
1129
+ this.popupObserver = null;
1130
+ }
1103
1131
  }, 300)
1104
1132
  },
1105
1133
 
@@ -1112,6 +1140,92 @@ export default {
1112
1140
  this.$set(this.mediaLoadingStatus, key, true)
1113
1141
  },
1114
1142
 
1143
+ // ==================== 初始化图片懒加载观察器 ====================
1144
+ /**
1145
+ * 初始化图片懒加载观察器
1146
+ */
1147
+ initLazyObserver() {
1148
+ if (this.readonly && this.allFileList.length > 0) {
1149
+ // 确保 observer 每次都被重新创建,以防元素变化
1150
+ if (this.observer) {
1151
+ this.observer.disconnect();
1152
+ this.observer = null;
1153
+ }
1154
+
1155
+ this.lazyLoadImageSrcs = Array(this.allFileList.length).fill(null);
1156
+
1157
+ this.$nextTick(() => {
1158
+ const currentObserver = uni.createIntersectionObserver(this, { observeAll: true });
1159
+ this.observer = currentObserver;
1160
+
1161
+ if (!this.observer) {
1162
+ console.warn("IntersectionObserver failed to create.");
1163
+ return;
1164
+ }
1165
+
1166
+ this.observer.relativeToViewport({ top: 0, bottom: 50 });
1167
+
1168
+ this.allFileList.forEach((file, index) => {
1169
+ if (file.type === 'image') {
1170
+ const sel = '#' + this.componentId + '-imgview-' + index;
1171
+ currentObserver.observe(sel, (res) => {
1172
+ const isVisible = res.intersectionRatio > 0;
1173
+ if (isVisible && !this.lazyLoadImageSrcs[index]) {
1174
+ this.$set(this.lazyLoadImageSrcs, index, file.url);
1175
+ }
1176
+ });
1177
+ }
1178
+ });
1179
+ });
1180
+ } else if (this.observer) {
1181
+ this.observer.disconnect();
1182
+ this.observer = null;
1183
+ }
1184
+ },
1185
+
1186
+ /**
1187
+ * 初始化弹窗图片懒加载观察器
1188
+ */
1189
+ initPopupLazyObserver() {
1190
+ if (this.popupVisible && this.allFileList.length > 0) {
1191
+ if (this.popupObserver) {
1192
+ this.popupObserver.disconnect();
1193
+ this.popupObserver = null;
1194
+ }
1195
+
1196
+ this.popupLazyLoadImageSrcs = Array(this.allFileList.length).fill(null);
1197
+
1198
+ this.$nextTick(() => {
1199
+ const currentPopupObserver = uni.createIntersectionObserver(this, { observeAll: true });
1200
+ this.popupObserver = currentPopupObserver;
1201
+
1202
+ if (!this.popupObserver) {
1203
+ console.warn("Popup IntersectionObserver failed to create.");
1204
+ return;
1205
+ }
1206
+
1207
+ // 在弹窗的scroll-view中创建观察器
1208
+ // 注意:这里需要确保scroll-view的selector是唯一的,或者使用组件内实例
1209
+ this.popupObserver.relativeToViewport({ top: 0, bottom: 50 });
1210
+
1211
+ this.allFileList.forEach((file, index) => {
1212
+ if (file.type === 'image') {
1213
+ const sel = '#' + this.componentId + '-popup-imgview-' + index;
1214
+ currentPopupObserver.observe(sel, (res) => {
1215
+ const isVisible = res.intersectionRatio > 0;
1216
+ if (isVisible && !this.popupLazyLoadImageSrcs[index]) {
1217
+ this.$set(this.popupLazyLoadImageSrcs, index, file.url);
1218
+ }
1219
+ });
1220
+ }
1221
+ });
1222
+ });
1223
+ } else if (this.popupObserver) {
1224
+ this.popupObserver.disconnect();
1225
+ this.popupObserver = null;
1226
+ }
1227
+ },
1228
+
1115
1229
  // ==================== 通用方法 ====================
1116
1230
  /**
1117
1231
  * 获取所有文件列表