@hzab/form-render 1.7.16 → 1.7.17

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": "@hzab/form-render",
3
- "version": "1.7.16",
3
+ "version": "1.7.17",
4
4
  "description": "",
5
5
  "main": "src",
6
6
  "scripts": {
@@ -27,13 +27,26 @@
27
27
  | ossServerUrl | string | 否 | - | 获取 oss 参数的接口,默认 /api/v1/user/oss/getWebOssConfig |
28
28
  | ossOpt | Object | 否 | - | oss 上传的配置参数 |
29
29
  | fileListConf | Object | 否 | {} | 结果数据配置 |
30
- | previewConfig | Object | 否 | {} | 预览场景的配置 |
30
+ | previewConfig | Object | 否 | {} | 预览场景配置(见下表)。仅影响列表/弹窗预览,不进入 onChange / 表单提交 |
31
+ | previewBaseUrl | string | 否 | - | 仅预览使用的域名/路径前缀(糖衣)。与 `previewConfig.url` 并存时,以 `previewConfig.url` 为准;不进入表单提交 |
31
32
  | onCountExceed | Function | 否 | - | 数量超出 maxCount 时的回调 |
32
33
  | beforeUploadCheck | Function | 否 | - | 追加的 beforeUpload 检查,返回 Promise.reject() 进行拦截 |
33
34
  | templateUrl | string | 否 | - | 模板下载的地址 |
34
35
  | templateDownloadText | string | 否 | 模板下载 | 模板下载按钮的文案 |
35
36
  | uploadParams | Object | 否 | {} | 文件上传接口入参 |
36
37
 
38
+ ### previewConfig 预览配置
39
+
40
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
41
+ | ---- | ---- | ---- | ------ | ---- |
42
+ | url | string | 否 | - | 预览域名或路径前缀,如 `https://cdn.example.com`。相对路径会拼到此前缀后用于列表缩略图与弹窗预览 |
43
+ | query | object | 否 | - | 追加到预览地址的 query 对象,推荐写法,如 `{ loookType: 1 }` |
44
+ | search | string | 否 | - | `?` 后的原始字符串(可不含 `?`),会先解析再与 `query` 合并;同名键以 `query` 为准 |
45
+
46
+ 兼容:把 `query` 写成字符串(如 `"loookType=1"`)时,组件会解析为 `search`,无需立刻改业务 schema。
47
+
48
+ > **边界**:`previewConfig.url` / `previewBaseUrl` 只用于上传列表视图与弹窗预览;`onChange` 与表单提交仍使用后端返回的相对/原始路径,不会提交拼接后的完整地址。
49
+
37
50
  ### fileListConf 结果数据配置
38
51
 
39
52
  | 参数 | 类型 | 必填 | 默认值 | 说明 |
@@ -1,11 +1,12 @@
1
1
  import { getFileURL } from "@hzab/utils/src/file/file";
2
2
  import { getFileType } from "@hzab/utils/src/file/fileType";
3
- import { isBase64Str } from "@hzab/utils/src/base64Str";
4
3
  import { getUFileName, getFileName, getFullFileName, getFileExt } from "@hzab/utils/src/file/fileName";
5
- import { getFileNameObj } from "@hzab/utils/src/upload/uploadUtils";
4
+ import { getFileNameObj, mergePreviewConfig } from "@hzab/utils/src/upload/uploadUtils";
6
5
  import { nanoidNumALetters } from "@hzab/utils/src/nanoid";
7
6
  import { getFormRenderPCGlobalServeConfig } from "../../../globalConfig";
8
- import { addQuery } from "@hzab/utils/src/url"
7
+ import { addQuery } from "@hzab/utils/src/url";
8
+
9
+ export { mergePreviewConfig };
9
10
 
10
11
 
11
12
  /**
@@ -139,43 +140,6 @@ export const objStrToObj = function (objStr) {
139
140
  return _objStr;
140
141
  };
141
142
 
142
- /**
143
- * 预览 url 添加前缀
144
- * @param {*} uri
145
- * @param {*} previewConfig
146
- * @returns
147
- */
148
- export function mergePreviewConfig(uri, previewConfig) {
149
- let _uri = uri;
150
- let basePath = "";
151
- if (typeof _uri === "object") {
152
- basePath = _uri.basePath;
153
- _uri = _uri.previewUrl || _uri.url;
154
- }
155
- if (typeof _uri !== "string") {
156
- return _uri;
157
- }
158
- _uri = _uri?.trim();
159
- // base64 直接返回
160
- if (isBase64Str(_uri)) {
161
- return _uri;
162
- }
163
- const isUriPattern = /http[s]?:\/\/[^\s]+/.test(_uri);
164
- const query = previewConfig?.query?.trim() ? "?" + previewConfig?.query?.trim() : "";
165
-
166
- if (isUriPattern) {
167
- // 源地址为 http 地址,直接拼接 query 参数
168
- return `${_uri}${query}`;
169
- }
170
-
171
- if (previewConfig) {
172
- // 拼接前缀
173
- return `${previewConfig?.url?.trim()}/${_uri}${query}`?.trim();
174
- }
175
-
176
- return _uri;
177
- }
178
-
179
143
  /**
180
144
  * 子项数据归一化
181
145
  * 字符串:url、base64
@@ -1,5 +1,5 @@
1
- import { formatDirStr, mergeDirStr, handleMaxCount, mergePreviewConfig } from "@hzab/utils/upload/uploadUtils";
2
- import { getFileURL } from "@hzab/utils/file/file";
1
+ import { formatDirStr, mergeDirStr, handleMaxCount, mergePreviewConfig } from "@hzab/utils/src/upload/uploadUtils";
2
+ import { getFileURL } from "@hzab/utils/src/file/file";
3
3
  import { isBase64Str } from "@hzab/utils/src/base64Str";
4
4
  import {
5
5
  checkImageUrl,
@@ -7,6 +7,7 @@ import {
7
7
  checkAudioUrl,
8
8
  isValidMediaType,
9
9
  checkUrlSuffix,
10
+ getFileType,
10
11
  } from "@hzab/utils/src/file/fileType";
11
12
  import { getArr } from "@hzab/utils/src/array";
12
13
 
@@ -10,6 +10,7 @@ import { Button, Upload as AUpload, message } from "antd";
10
10
  import React, { useEffect, useState, useMemo } from "react";
11
11
 
12
12
  import { handleInputFileList, handleOutputFileList } from "./common/handleIOFileList";
13
+ import { mergePreviewConfig } from "@hzab/utils/src/upload/uploadUtils";
13
14
 
14
15
  import PreviewModal, { hasPreviewRender, hasPreviewMedium } from "./components/PreviewModal";
15
16
  import { getOssUploadRequest, getOfflineUploadRequest } from "./common/customRequest";
@@ -57,6 +58,8 @@ export function Uploader({ onChange, ...props }) {
57
58
  isResRemoveArr = true,
58
59
  /** 预览配置参数 */
59
60
  previewConfig = {},
61
+ /** 仅预览使用的域名/路径前缀,不参与 onChange / 表单提交;优先级低于 previewConfig.url */
62
+ previewBaseUrl = getFormRenderPCGlobalServeConfig()?.previewBaseUrl || "",
60
63
  onCountExceed,
61
64
  templateUrl,
62
65
  beforeUploadCheck,
@@ -69,6 +72,26 @@ export function Uploader({ onChange, ...props }) {
69
72
  const isPrivateStore =
70
73
  props.uploadParams?.fileAcl === "private" || props.ossOpt?.signatureParams?.fileAcl === "private";
71
74
 
75
+ /** 预览前缀配置:previewConfig.url 优先,其次 previewBaseUrl;*/
76
+ const resolvedPreviewConfig = useMemo(() => {
77
+ const url = previewConfig?.url || previewBaseUrl;
78
+ const { query, search, ...rest } = previewConfig || {};
79
+ const isQueryObject = query && typeof query === "object";
80
+ const legacyQueryStr = typeof query === "string" ? query.trim() : "";
81
+ const resolvedSearch = (search || legacyQueryStr || "").replace(/^\?/, "") || undefined;
82
+ const resolvedQuery = isQueryObject ? query : undefined;
83
+
84
+ if (!url && !resolvedQuery && !resolvedSearch) {
85
+ return previewConfig || {};
86
+ }
87
+ return {
88
+ ...rest,
89
+ url,
90
+ ...(resolvedQuery ? { query: resolvedQuery } : {}),
91
+ ...(resolvedSearch ? { search: resolvedSearch } : {}),
92
+ };
93
+ }, [previewConfig.url, previewConfig.query, previewConfig.search, previewBaseUrl]);
94
+
72
95
  /**
73
96
  * 数据格式配置
74
97
  */
@@ -135,7 +158,12 @@ export function Uploader({ onChange, ...props }) {
135
158
  };
136
159
 
137
160
  useEffect(() => {
138
- const list = handleInputFileList(value, { ...fileListConf, maxCount, previewConfig, thumbnailParams });
161
+ const list = handleInputFileList(value, {
162
+ ...fileListConf,
163
+ maxCount,
164
+ previewConfig: resolvedPreviewConfig,
165
+ thumbnailParams,
166
+ });
139
167
 
140
168
  async function handlePreview() {
141
169
  await handlePreviewUrls(list, {
@@ -150,7 +178,27 @@ export function Uploader({ onChange, ...props }) {
150
178
  } else {
151
179
  setFileList(list);
152
180
  }
153
- }, [value]);
181
+ }, [value, resolvedPreviewConfig]);
182
+
183
+ /** 仅用于列表展示:补齐 thumbUrl/previewUrl,不改动 url(提交仍用相对路径) */
184
+ const displayFileList = useMemo(() => {
185
+ if (!resolvedPreviewConfig?.url || !fileList?.length) {
186
+ return fileList;
187
+ }
188
+ return fileList.map((file) => {
189
+ if (!file || typeof file !== "object") {
190
+ return file;
191
+ }
192
+ // 用存储路径 url 拼前缀,避免已是完整 previewUrl 时语义混乱;无 url 时回退对象自身
193
+ const previewUrl = mergePreviewConfig(file.url || file, resolvedPreviewConfig);
194
+ const thumbUrl = file.thumbUrl ? mergePreviewConfig(file.thumbUrl, resolvedPreviewConfig) : previewUrl;
195
+ return {
196
+ ...file,
197
+ previewUrl,
198
+ thumbUrl,
199
+ };
200
+ });
201
+ }, [fileList, resolvedPreviewConfig]);
154
202
 
155
203
  const onRemove = (file) => {
156
204
  const files = (fileList || []).filter((v) => v.url !== file.url);
@@ -206,7 +254,7 @@ export function Uploader({ onChange, ...props }) {
206
254
  multiple: multiple,
207
255
  listType: listType,
208
256
  maxCount: maxCount,
209
- fileList: fileList,
257
+ fileList: displayFileList,
210
258
  onChange: handleChange,
211
259
  disabled,
212
260
  readOnly,
@@ -249,10 +297,14 @@ export function Uploader({ onChange, ...props }) {
249
297
  setChecking(false);
250
298
  },
251
299
  customRequest,
300
+ ...(props || {}),
301
+ // 保证展示列表与预览逻辑不被 props 覆盖丢失
302
+ fileList: displayFileList,
252
303
  onPreview(file) {
253
304
  // TODO: 逻辑合并到数据处理中
254
305
  const isShowPreview = hasPreviewRender(file) || hasPreviewMedium(props.accept);
255
- const fileUrl = file.previewUrl;
306
+ // 预览出口统一走 mergePreviewConfig;提交仍使用 file.url 相对路径
307
+ const fileUrl = mergePreviewConfig(file.url || file, resolvedPreviewConfig);
256
308
  if (isShowPreview) {
257
309
  setPreviewFile({
258
310
  ...file,
@@ -316,7 +368,7 @@ export function Uploader({ onChange, ...props }) {
316
368
  accept={props?.accept}
317
369
  setPreviewFile={setPreviewFile}
318
370
  modalConf={props.modalConf}
319
- previewConfig={previewConfig}
371
+ previewConfig={resolvedPreviewConfig}
320
372
  />
321
373
  </>
322
374
  );