@boteteam/utils 0.0.33 → 0.0.35
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 +175 -9
- package/dist/cjs/aiGenerateFill.d.ts +2 -0
- package/dist/cjs/aiGenerateFill.js +44 -0
- package/dist/cjs/aiGenerateFill.js.map +7 -0
- package/dist/cjs/copyToClipboard.d.ts +6 -0
- package/dist/cjs/copyToClipboard.js +55 -0
- package/dist/cjs/copyToClipboard.js.map +7 -0
- package/dist/cjs/dealStorageData.d.ts +35 -0
- package/dist/cjs/dealStorageData.js +331 -0
- package/dist/cjs/dealStorageData.js.map +7 -0
- package/dist/cjs/docchainContextFill.d.ts +2 -0
- package/dist/cjs/docchainContextFill.js +38 -0
- package/dist/cjs/docchainContextFill.js.map +7 -0
- package/dist/cjs/formatModule/formatModuleData.js +53 -10
- package/dist/cjs/formatModule/formatModuleData.js.map +2 -2
- package/dist/cjs/formatModule/helpers/formatDescriptionsProps.js +13 -2
- package/dist/cjs/formatModule/helpers/formatDescriptionsProps.js.map +3 -3
- package/dist/cjs/formatModule/helpers/formatEchartLineProps.js +12 -5
- package/dist/cjs/formatModule/helpers/formatEchartLineProps.js.map +3 -3
- package/dist/cjs/formatModule/helpers/formatEchartPieProps.d.ts +1 -0
- package/dist/cjs/formatModule/helpers/formatEchartPieProps.js +26 -2
- package/dist/cjs/formatModule/helpers/formatEchartPieProps.js.map +3 -3
- package/dist/cjs/formatModule/helpers/formatFormProps.js +11 -0
- package/dist/cjs/formatModule/helpers/formatFormProps.js.map +3 -3
- package/dist/cjs/formatModule/helpers/formatHighCodeProps.js +3 -0
- package/dist/cjs/formatModule/helpers/formatHighCodeProps.js.map +2 -2
- package/dist/cjs/formatModule/helpers/formatImageProps.js +9 -3
- package/dist/cjs/formatModule/helpers/formatImageProps.js.map +2 -2
- package/dist/cjs/getClassPrefix.d.ts +2 -0
- package/dist/cjs/getClassPrefix.js +43 -0
- package/dist/cjs/getClassPrefix.js.map +7 -0
- package/dist/cjs/http.d.ts +10 -0
- package/dist/cjs/http.js +18 -0
- package/dist/cjs/http.js.map +2 -2
- package/dist/cjs/index.d.ts +10 -2
- package/dist/cjs/index.js +33 -4
- package/dist/cjs/index.js.map +3 -3
- package/dist/cjs/onCallSkillEvent.d.ts +21 -0
- package/dist/cjs/onCallSkillEvent.js +81 -0
- package/dist/cjs/onCallSkillEvent.js.map +7 -0
- package/dist/cjs/treeUtils.js +1 -1
- package/dist/cjs/treeUtils.js.map +2 -2
- package/dist/cjs/unitConversion.d.ts +2 -0
- package/dist/cjs/unitConversion.js +45 -0
- package/dist/cjs/unitConversion.js.map +7 -0
- package/dist/cjs/watermark.d.ts +0 -28
- package/dist/cjs/watermark.js +4 -277
- package/dist/cjs/watermark.js.map +2 -2
- package/dist/esm/aiGenerateFill.d.ts +2 -0
- package/dist/esm/aiGenerateFill.js +17 -0
- package/dist/esm/aiGenerateFill.js.map +1 -0
- package/dist/esm/copyToClipboard.d.ts +6 -0
- package/dist/esm/copyToClipboard.js +23 -0
- package/dist/esm/copyToClipboard.js.map +1 -0
- package/dist/esm/dealStorageData.d.ts +35 -0
- package/dist/esm/dealStorageData.js +441 -0
- package/dist/esm/dealStorageData.js.map +1 -0
- package/dist/esm/docchainContextFill.d.ts +2 -0
- package/dist/esm/docchainContextFill.js +17 -0
- package/dist/esm/docchainContextFill.js.map +1 -0
- package/dist/esm/formatModule/formatModuleData.js +58 -11
- package/dist/esm/formatModule/formatModuleData.js.map +1 -1
- package/dist/esm/formatModule/helpers/formatDescriptionsProps.js +20 -3
- package/dist/esm/formatModule/helpers/formatDescriptionsProps.js.map +1 -1
- package/dist/esm/formatModule/helpers/formatEchartLineProps.js +12 -5
- package/dist/esm/formatModule/helpers/formatEchartLineProps.js.map +1 -1
- package/dist/esm/formatModule/helpers/formatEchartPieProps.d.ts +1 -0
- package/dist/esm/formatModule/helpers/formatEchartPieProps.js +30 -5
- package/dist/esm/formatModule/helpers/formatEchartPieProps.js.map +1 -1
- package/dist/esm/formatModule/helpers/formatFormProps.js +8 -0
- package/dist/esm/formatModule/helpers/formatFormProps.js.map +1 -1
- package/dist/esm/formatModule/helpers/formatHighCodeProps.js +6 -1
- package/dist/esm/formatModule/helpers/formatHighCodeProps.js.map +1 -1
- package/dist/esm/formatModule/helpers/formatImageProps.js +9 -3
- package/dist/esm/formatModule/helpers/formatImageProps.js.map +1 -1
- package/dist/esm/getClassPrefix.d.ts +2 -0
- package/dist/esm/getClassPrefix.js +15 -0
- package/dist/esm/getClassPrefix.js.map +1 -0
- package/dist/esm/http.d.ts +10 -0
- package/dist/esm/http.js +90 -58
- package/dist/esm/http.js.map +1 -1
- package/dist/esm/index.d.ts +10 -2
- package/dist/esm/index.js +9 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/onCallSkillEvent.d.ts +21 -0
- package/dist/esm/onCallSkillEvent.js +90 -0
- package/dist/esm/onCallSkillEvent.js.map +1 -0
- package/dist/esm/treeUtils.js +1 -3
- package/dist/esm/treeUtils.js.map +1 -1
- package/dist/esm/unitConversion.d.ts +2 -0
- package/dist/esm/unitConversion.js +21 -0
- package/dist/esm/unitConversion.js.map +1 -0
- package/dist/esm/watermark.d.ts +0 -28
- package/dist/esm/watermark.js +2 -411
- package/dist/esm/watermark.js.map +1 -1
- package/dist/umd/index.min.js +1 -1
- package/dist/umd/index.min.js.map +1 -1
- package/package.json +8 -3
package/dist/cjs/treeUtils.js
CHANGED
|
@@ -216,7 +216,7 @@ var getParamsContentByParamKeysForEvent = (paramNames, data = {}) => {
|
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
const result = loopNodeByParamsPath(paramNameList, data);
|
|
219
|
-
return result
|
|
219
|
+
return result;
|
|
220
220
|
};
|
|
221
221
|
var replaceParamsValueForEvent = (contentStr, data = {}) => {
|
|
222
222
|
var _a;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/treeUtils.ts"],
|
|
4
|
-
"sourcesContent": ["import { get, cloneDeep } from 'lodash';\nimport escapeString from './markdownEscape';\n\n/** 把${xxx.xxx.xxx} 转换为 [xxx,xxx,xxx] */\nexport const getParamsArr = (content: string) => {\n let matchArr:string[] = [];\n if (content && typeof content === 'string') {\n const escapeRegex = /\\$\\{\\{([^}]+)\\}\\}/gi; // 变量正则表达式,${{xxx}}\n const regex = /\\$\\{(.+?)\\}/gi; // 变量正则表达式,${xxx}\n let matchs = escapeRegex.exec(content);\n if (matchs?.[1]) {\n matchArr = matchs[1].split('.');\n } else {\n matchs = regex.exec(content);\n if (matchs?.[1]) {\n matchArr = matchs[1].split('.');\n }\n }\n return matchArr;\n }\n return matchArr;\n};\n\n/** 把${xxx.xxx.xxx} 转换为 [xxx,xxx,xxx],并过滤掉第一个root,pageParams */\nexport const getDataArr = (content: string) => {\n const matchArr:string[] = getParamsArr(content);\n return matchArr?.filter((item, idx) => !(idx === 0 && ['root', 'pageParams'].includes(item)) && !(idx === 1 && ['pageParams'].includes(item))); // 过滤掉第一个root,pageParams\n};\n\n/** 根据参数路径,逐级获取数据 */\nconst loopNodeByParamsPath:any = (\n paramsArr:string[],\n data: {[key:string]: any},\n escape:boolean = false\n) => {\n if (Array.isArray(paramsArr) && paramsArr.length > 0) {\n for (const keyword of paramsArr) {\n const dataNode = get(data, keyword);\n let nextParamsArr = paramsArr.slice(1); // 取下一个节点字段\n if (Array.isArray(dataNode)) {\n // 如果当前节点是数组,且下一个节点是数字,则取下标对应的值\n const idxRegex = /^\\[.*\\]$|^\\d+$/;\n if (idxRegex.test(nextParamsArr?.[0])) {\n const idxNum = nextParamsArr?.[0].replace(/\\[|\\]/g, '');\n if (dataNode?.[Number(idxNum)] instanceof Object) {\n return loopNodeByParamsPath(nextParamsArr.slice(1), dataNode?.[Number(idxNum)], escape);\n }\n return escape ? escapeString(dataNode?.[Number(idxNum)]) : dataNode?.[Number(idxNum)];\n }\n // 否则或缺中间节点,直接往下取值\n nextParamsArr = nextParamsArr.slice(1);\n if (nextParamsArr?.length >= 1) {\n return dataNode.map((item:any) => {\n // 如果数组节点是对象,则继续递归取值\n if (item instanceof Object && nextParamsArr?.length >= 1) {\n return loopNodeByParamsPath(nextParamsArr, item, escape);\n }\n // 否则直接返回数组值\n return escape ? escapeString(item) : item;\n });\n }\n return dataNode;\n } if (nextParamsArr?.length >= 1) {\n return loopNodeByParamsPath(nextParamsArr, dataNode, escape);\n }\n return escape ? escapeString(dataNode) : dataNode;\n }\n }\n return '';\n};\n\n\nexport const getParamsContentByParamKeys = (paramNames: string, data: {[key:string]: any} = {}) => {\n if (!paramNames || !data || Object.keys(data)?.length <= 0) {\n return undefined;\n }\n const escapeRegex = /\\$\\{\\{([^}]+)\\}\\}/gi; // 匹配${{}}格式的参数,属于需转义内容\n const paramNameList = getDataArr(paramNames);\n return loopNodeByParamsPath(paramNameList, data, escapeRegex.test(paramNames));\n};\n\n/**\n * 替换循环体内的参数值\n * 用于在循环体模板中替换 ${...} 格式的参数占位符为实际值\n *\n * @param contentStr - 包含参数占位符的字符串模板,例如: \"${item.name} - ${item.price}\"\n * @param options - 配置选项\n * @param options.loopParams - 循环体参数对象,包含当前循环项的字段值\n * @param options.loopSourceArr - 循环体数据源的键名数组,用于标识哪些参数属于循环体本身\n * @param options.loopData - 循环数据源的完整数据数组\n * @param options.parameters - 全量参数对象(可选),当循环体内找不到值时,会从这里查找\n * @param options.staticCodeMap - 静态数据映射(可选),当前未使用\n * @returns 替换后的字符串\n *\n * @example\n * // 示例:替换循环体内的参数\n * const result = replaceLoopBodyParamsValue(\n * \"${item.name} - ${item.price}\",\n * {\n * loopParams: { name: \"商品A\", price: 100 },\n * loopSourceArr: [\"item\"],\n * loopData: [{ name: \"商品A\", price: 100 }],\n * parameters: { globalVar: \"全局变量\" }\n * }\n * );\n * // 返回: \"商品A - 100\"\n */\nexport const replaceLoopBodyParamsValue = (\n contentStr: string,\n options: {\n loopIndex: number, // 循环索引\n loopParams: any // 循环体参数\n loopSourceArr: string[], // 循环体数据源\n loopData: {[key: string]: any}[], // 循环数据源数据\n parameters?: {[key: string]: any}, // 全量参数\n staticCodeMap?: {[key: string]: any}, // 静态数据\n },\n) => {\n const {\n loopIndex = 0,\n loopParams = {},\n loopSourceArr = [],\n loopData = [],\n parameters = {},\n } = options || {};\n let nowTemp = '';\n \n // 只有当输入是有效字符串且存在循环体参数时才进行处理\n if (typeof contentStr === 'string' && contentStr && loopParams) {\n // 使用正则表达式匹配所有 ${...} 格式的参数占位符\n nowTemp = contentStr.replace(/\\$\\{(.+?)\\}/gi, (match) => {\n // eslint-disable-next-line no-template-curly-in-string\n if (match === '${rowIndex}') {\n return String(loopIndex);\n }\n // 解析参数路径,并过滤掉循环源数组中的键(避免循环引用)\n const paramsPath = getDataArr(match).filter((itemKey) => !loopSourceArr.includes(itemKey));\n let filedVal:any = '';\n \n // 判断第一个参数是否为数组索引(如 [0] 或 0)\n // 如果当前节点是数组,且下一个节点是数字,则取下标对应的值\n const idxRegex = /^\\[.*\\]$|^\\d+$/;\n if (idxRegex.test(paramsPath?.[0])) {\n // 从数组索引中提取数字\n const idxNum = paramsPath?.[0].replace(/\\[|\\]/g, '');\n const idx = Number(idxNum);\n // 验证索引是否为有效数字(非 NaN 且非负数)\n if (!isNaN(idx) && idx >= 0 && Number.isInteger(idx)) {\n // 如果对应索引的数据是对象,则继续递归查找子属性\n if (loopData?.[idx] instanceof Object) {\n filedVal = loopNodeByParamsPath(paramsPath.slice(1), loopData[idx]);\n } else {\n // 否则直接返回该索引的值(可能为 undefined,会被后续逻辑处理)\n filedVal = loopData?.[idx];\n }\n } else {\n // 无效索引(如 [abc] 或负数),返回空字符串\n filedVal = '';\n }\n } else {\n // 非数组索引情况,从循环体参数中查找值\n // 兼容 loopParams 是非对象类型的情况(如字符串、数字、布尔值等)\n const remainingPath = paramsPath.slice(1);\n if (loopParams instanceof Object && !Array.isArray(loopParams)) {\n // loopParams 是对象类型,使用原有逻辑\n filedVal = loopNodeByParamsPath(remainingPath, loopParams);\n } else if (remainingPath.length === 0) {\n // loopParams 是非对象类型,且没有子路径,直接返回 loopParams 的值\n filedVal = loopParams;\n } else {\n // loopParams 是非对象类型,但有子路径,无法访问属性,返回空字符串\n // 后续会尝试从全局参数中查找\n filedVal = '';\n }\n\n // 如果循环体内查找不到值,则从全量参数中查找,但需要排除循环体本身的数据源\n // 这样可以避免循环引用,同时允许访问循环体外的全局参数\n // 注意:!filedVal 会将 0、false、'' 等假值也视为未找到,这是当前的设计逻辑\n if (!filedVal && parameters) {\n const _parameters = cloneDeep(parameters);\n // 从全量参数中删除循环体数据源,避免循环引用\n if (Array.isArray(loopSourceArr) && loopSourceArr.length > 0) {\n loopSourceArr.forEach((sourceKey:string) => {\n delete _parameters[sourceKey];\n });\n }\n // 使用完整的参数路径(不过滤循环源)从全量参数中查找\n const paramNameList = getDataArr(match);\n const globalVal = loopNodeByParamsPath(paramNameList, _parameters);\n // 如果从全量参数中找到的值是数组,则返回空字符串,避免返回整个数组\n // 只返回对象的值,不返回数组数据\n if (Array.isArray(globalVal)) {\n filedVal = '';\n } else {\n filedVal = globalVal;\n }\n }\n }\n // 返回找到的值,如果找不到则返回空字符串\n // 修复:当值为 0 时,应该正常返回 '0',而不是空字符串\n if (filedVal === null || filedVal === undefined) {\n return '';\n }\n return String(filedVal);\n });\n }\n return nowTemp;\n};\n\nexport const replaceParamsValue = (\n contentStr: string,\n pararms: { [key: string]: any } = {},\n isObject2String: boolean = false,\n) => {\n let nowContent:string = '';\n if (typeof contentStr === 'string' && contentStr && pararms) {\n nowContent = contentStr.replace(/\\$\\{\\{?[^{}]+}?\\}/g, (match) => {\n const filedVal = getParamsContentByParamKeys(match, pararms);\n if (isObject2String && typeof filedVal === 'object') {\n return JSON.stringify(filedVal);\n }\n // 修复:当值为 0 时,应该正常返回 '0',而不是空字符串\n if (filedVal === null || filedVal === undefined) {\n return '';\n }\n return String(filedVal);\n });\n }\n return nowContent;\n};\n\n\n/** ======下面几个方法主要提供给事件参数使用 勿共用 ===== */\nconst splitStringWithTemplateLiteral = (input: string) => {\n // 正则表达式:匹配 ${...} 模式\n const templateRegex = /\\$\\{[^}]*\\}/;\n\n // 检查字符串是否包含 ${...}\n if (!templateRegex.test(input)) {\n return [input]; // 返回原始字符串\n }\n\n // 匹配所有 ${...} 模式\n const matches = input.match(templateRegex);\n\n if (!matches || matches.length === 0) {\n return [input]; // 返回原始字符串\n }\n\n // 分割字符串,同时保留 ${...} 模式\n const result = input.split(templateRegex).filter(Boolean); // 去掉空字符串\n\n // 将匹配到的 ${...} 模式重新插入到结果数组中\n matches.forEach((match, index) => {\n result.splice(index * 2 + 1, 0, match); // 插入到对应位置\n });\n\n return result;\n};\n\nconst getParamsContentByParamKeysForEvent = (\n paramNames: string,\n data: { [key: string]: any } = {},\n) => {\n let paramNameList: string[] = [];\n const regex = /\\$\\{(.+?)\\}/gi; // 变量正则表达式,${xxx}\n if (paramNames && typeof paramNames === 'string') {\n const matchs = regex.exec(paramNames);\n if (matchs?.[1]) {\n paramNameList = matchs?.[1]?.split('.');\n }\n }\n\n if (paramNameList.length === 0) {\n return paramNames;\n }\n\n // 如果参数路径中没有 pageParams,先尝试在 data.pageParams 中查找\n // 因为根据注释,这个方法不能去掉 pageParams 那一层\n if (paramNameList[0] !== 'pageParams' && data?.pageParams) {\n const result = loopNodeByParamsPath(paramNameList, data.pageParams);\n if (result !== '' && result !== undefined) {\n return result;\n }\n }\n\n // 如果替换不成功,需要返回字符串原始的值\n const result = loopNodeByParamsPath(paramNameList, data);\n return result !== '' && result !== undefined ? result : paramNames;\n};\n\n\n/**\n * 提供给事件参数转换那边的方法\n * 和replaceParamsValue 区别,\n * 1、不能去掉pageParams那一层\n * 2、字符串拼对象,需要把对象做JSON.stringify转换\n * 3、如果替换不成功,需要返回字符串原始的值\n * @param contentStr \"你好\" ,\"你$好, ${pageParams.userName}\" , \"${pageData}, ${pageParams.userList[0]}\"\n * @param data 数据\n */\nexport const replaceParamsValueForEvent = (\n contentStr: string,\n data: { [key: string]: any } = {},\n) => {\n if (!contentStr || !data || Object.keys(data)?.length <= 0) {\n return undefined;\n }\n const valueArr = splitStringWithTemplateLiteral(contentStr);\n // 单个字符串, 没有拼接\n if (valueArr.length === 1) {\n return getParamsContentByParamKeysForEvent(valueArr[0], data);\n }\n\n\n let nowTemp = '';\n if (typeof contentStr === 'string' && contentStr && data) {\n nowTemp = contentStr.replace(/\\$\\{(.+?)\\}/g, (match) => {\n const filedVal = getParamsContentByParamKeysForEvent(match, data);\n if (typeof filedVal === 'string') {\n return filedVal;\n }\n // 字符串拼对象,需要把对象做JSON.stringify转换\n try {\n return JSON.stringify(filedVal);\n } catch {\n return '';\n }\n });\n }\n return nowTemp;\n};\n\n/** ======上面几个方法主要提供给事件参数使用 勿共用 ===== */\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { get, cloneDeep } from 'lodash';\nimport escapeString from './markdownEscape';\n\n/** 把${xxx.xxx.xxx} 转换为 [xxx,xxx,xxx] */\nexport const getParamsArr = (content: string) => {\n let matchArr:string[] = [];\n if (content && typeof content === 'string') {\n const escapeRegex = /\\$\\{\\{([^}]+)\\}\\}/gi; // 变量正则表达式,${{xxx}}\n const regex = /\\$\\{(.+?)\\}/gi; // 变量正则表达式,${xxx}\n let matchs = escapeRegex.exec(content);\n if (matchs?.[1]) {\n matchArr = matchs[1].split('.');\n } else {\n matchs = regex.exec(content);\n if (matchs?.[1]) {\n matchArr = matchs[1].split('.');\n }\n }\n return matchArr;\n }\n return matchArr;\n};\n\n/** 把${xxx.xxx.xxx} 转换为 [xxx,xxx,xxx],并过滤掉第一个root,pageParams */\nexport const getDataArr = (content: string) => {\n const matchArr:string[] = getParamsArr(content);\n return matchArr?.filter((item, idx) => !(idx === 0 && ['root', 'pageParams'].includes(item)) && !(idx === 1 && ['pageParams'].includes(item))); // 过滤掉第一个root,pageParams\n};\n\n/** 根据参数路径,逐级获取数据 */\nconst loopNodeByParamsPath:any = (\n paramsArr:string[],\n data: {[key:string]: any},\n escape:boolean = false\n) => {\n if (Array.isArray(paramsArr) && paramsArr.length > 0) {\n for (const keyword of paramsArr) {\n const dataNode = get(data, keyword);\n let nextParamsArr = paramsArr.slice(1); // 取下一个节点字段\n if (Array.isArray(dataNode)) {\n // 如果当前节点是数组,且下一个节点是数字,则取下标对应的值\n const idxRegex = /^\\[.*\\]$|^\\d+$/;\n if (idxRegex.test(nextParamsArr?.[0])) {\n const idxNum = nextParamsArr?.[0].replace(/\\[|\\]/g, '');\n if (dataNode?.[Number(idxNum)] instanceof Object) {\n return loopNodeByParamsPath(nextParamsArr.slice(1), dataNode?.[Number(idxNum)], escape);\n }\n return escape ? escapeString(dataNode?.[Number(idxNum)]) : dataNode?.[Number(idxNum)];\n }\n // 否则或缺中间节点,直接往下取值\n nextParamsArr = nextParamsArr.slice(1);\n if (nextParamsArr?.length >= 1) {\n return dataNode.map((item:any) => {\n // 如果数组节点是对象,则继续递归取值\n if (item instanceof Object && nextParamsArr?.length >= 1) {\n return loopNodeByParamsPath(nextParamsArr, item, escape);\n }\n // 否则直接返回数组值\n return escape ? escapeString(item) : item;\n });\n }\n return dataNode;\n } if (nextParamsArr?.length >= 1) {\n return loopNodeByParamsPath(nextParamsArr, dataNode, escape);\n }\n return escape ? escapeString(dataNode) : dataNode;\n }\n }\n return '';\n};\n\n\nexport const getParamsContentByParamKeys = (paramNames: string, data: {[key:string]: any} = {}) => {\n if (!paramNames || !data || Object.keys(data)?.length <= 0) {\n return undefined;\n }\n const escapeRegex = /\\$\\{\\{([^}]+)\\}\\}/gi; // 匹配${{}}格式的参数,属于需转义内容\n const paramNameList = getDataArr(paramNames);\n return loopNodeByParamsPath(paramNameList, data, escapeRegex.test(paramNames));\n};\n\n/**\n * 替换循环体内的参数值\n * 用于在循环体模板中替换 ${...} 格式的参数占位符为实际值\n *\n * @param contentStr - 包含参数占位符的字符串模板,例如: \"${item.name} - ${item.price}\"\n * @param options - 配置选项\n * @param options.loopParams - 循环体参数对象,包含当前循环项的字段值\n * @param options.loopSourceArr - 循环体数据源的键名数组,用于标识哪些参数属于循环体本身\n * @param options.loopData - 循环数据源的完整数据数组\n * @param options.parameters - 全量参数对象(可选),当循环体内找不到值时,会从这里查找\n * @param options.staticCodeMap - 静态数据映射(可选),当前未使用\n * @returns 替换后的字符串\n *\n * @example\n * // 示例:替换循环体内的参数\n * const result = replaceLoopBodyParamsValue(\n * \"${item.name} - ${item.price}\",\n * {\n * loopParams: { name: \"商品A\", price: 100 },\n * loopSourceArr: [\"item\"],\n * loopData: [{ name: \"商品A\", price: 100 }],\n * parameters: { globalVar: \"全局变量\" }\n * }\n * );\n * // 返回: \"商品A - 100\"\n */\nexport const replaceLoopBodyParamsValue = (\n contentStr: string,\n options: {\n loopIndex: number, // 循环索引\n loopParams: any // 循环体参数\n loopSourceArr: string[], // 循环体数据源\n loopData: {[key: string]: any}[], // 循环数据源数据\n parameters?: {[key: string]: any}, // 全量参数\n staticCodeMap?: {[key: string]: any}, // 静态数据\n },\n) => {\n const {\n loopIndex = 0,\n loopParams = {},\n loopSourceArr = [],\n loopData = [],\n parameters = {},\n } = options || {};\n let nowTemp = '';\n \n // 只有当输入是有效字符串且存在循环体参数时才进行处理\n if (typeof contentStr === 'string' && contentStr && loopParams) {\n // 使用正则表达式匹配所有 ${...} 格式的参数占位符\n nowTemp = contentStr.replace(/\\$\\{(.+?)\\}/gi, (match) => {\n // eslint-disable-next-line no-template-curly-in-string\n if (match === '${rowIndex}') {\n return String(loopIndex);\n }\n // 解析参数路径,并过滤掉循环源数组中的键(避免循环引用)\n const paramsPath = getDataArr(match).filter((itemKey) => !loopSourceArr.includes(itemKey));\n let filedVal:any = '';\n \n // 判断第一个参数是否为数组索引(如 [0] 或 0)\n // 如果当前节点是数组,且下一个节点是数字,则取下标对应的值\n const idxRegex = /^\\[.*\\]$|^\\d+$/;\n if (idxRegex.test(paramsPath?.[0])) {\n // 从数组索引中提取数字\n const idxNum = paramsPath?.[0].replace(/\\[|\\]/g, '');\n const idx = Number(idxNum);\n // 验证索引是否为有效数字(非 NaN 且非负数)\n if (!isNaN(idx) && idx >= 0 && Number.isInteger(idx)) {\n // 如果对应索引的数据是对象,则继续递归查找子属性\n if (loopData?.[idx] instanceof Object) {\n filedVal = loopNodeByParamsPath(paramsPath.slice(1), loopData[idx]);\n } else {\n // 否则直接返回该索引的值(可能为 undefined,会被后续逻辑处理)\n filedVal = loopData?.[idx];\n }\n } else {\n // 无效索引(如 [abc] 或负数),返回空字符串\n filedVal = '';\n }\n } else {\n // 非数组索引情况,从循环体参数中查找值\n // 兼容 loopParams 是非对象类型的情况(如字符串、数字、布尔值等)\n const remainingPath = paramsPath.slice(1);\n if (loopParams instanceof Object && !Array.isArray(loopParams)) {\n // loopParams 是对象类型,使用原有逻辑\n filedVal = loopNodeByParamsPath(remainingPath, loopParams);\n } else if (remainingPath.length === 0) {\n // loopParams 是非对象类型,且没有子路径,直接返回 loopParams 的值\n filedVal = loopParams;\n } else {\n // loopParams 是非对象类型,但有子路径,无法访问属性,返回空字符串\n // 后续会尝试从全局参数中查找\n filedVal = '';\n }\n\n // 如果循环体内查找不到值,则从全量参数中查找,但需要排除循环体本身的数据源\n // 这样可以避免循环引用,同时允许访问循环体外的全局参数\n // 注意:!filedVal 会将 0、false、'' 等假值也视为未找到,这是当前的设计逻辑\n if (!filedVal && parameters) {\n const _parameters = cloneDeep(parameters);\n // 从全量参数中删除循环体数据源,避免循环引用\n if (Array.isArray(loopSourceArr) && loopSourceArr.length > 0) {\n loopSourceArr.forEach((sourceKey:string) => {\n delete _parameters[sourceKey];\n });\n }\n // 使用完整的参数路径(不过滤循环源)从全量参数中查找\n const paramNameList = getDataArr(match);\n const globalVal = loopNodeByParamsPath(paramNameList, _parameters);\n // 如果从全量参数中找到的值是数组,则返回空字符串,避免返回整个数组\n // 只返回对象的值,不返回数组数据\n if (Array.isArray(globalVal)) {\n filedVal = '';\n } else {\n filedVal = globalVal;\n }\n }\n }\n // 返回找到的值,如果找不到则返回空字符串\n // 修复:当值为 0 时,应该正常返回 '0',而不是空字符串\n if (filedVal === null || filedVal === undefined) {\n return '';\n }\n return String(filedVal);\n });\n }\n return nowTemp;\n};\n\nexport const replaceParamsValue = (\n contentStr: string,\n pararms: { [key: string]: any } = {},\n isObject2String: boolean = false,\n) => {\n let nowContent:string = '';\n if (typeof contentStr === 'string' && contentStr && pararms) {\n nowContent = contentStr.replace(/\\$\\{\\{?[^{}]+}?\\}/g, (match) => {\n const filedVal = getParamsContentByParamKeys(match, pararms);\n if (isObject2String && typeof filedVal === 'object') {\n return JSON.stringify(filedVal);\n }\n // 修复:当值为 0 时,应该正常返回 '0',而不是空字符串\n if (filedVal === null || filedVal === undefined) {\n return '';\n }\n return String(filedVal);\n });\n }\n return nowContent;\n};\n\n\n/** ======下面几个方法主要提供给事件参数使用 勿共用 ===== */\nconst splitStringWithTemplateLiteral = (input: string) => {\n // 正则表达式:匹配 ${...} 模式\n const templateRegex = /\\$\\{[^}]*\\}/;\n\n // 检查字符串是否包含 ${...}\n if (!templateRegex.test(input)) {\n return [input]; // 返回原始字符串\n }\n\n // 匹配所有 ${...} 模式\n const matches = input.match(templateRegex);\n\n if (!matches || matches.length === 0) {\n return [input]; // 返回原始字符串\n }\n\n // 分割字符串,同时保留 ${...} 模式\n const result = input.split(templateRegex).filter(Boolean); // 去掉空字符串\n\n // 将匹配到的 ${...} 模式重新插入到结果数组中\n matches.forEach((match, index) => {\n result.splice(index * 2 + 1, 0, match); // 插入到对应位置\n });\n\n return result;\n};\n\nconst getParamsContentByParamKeysForEvent = (\n paramNames: string,\n data: { [key: string]: any } = {},\n) => {\n let paramNameList: string[] = [];\n const regex = /\\$\\{(.+?)\\}/gi; // 变量正则表达式,${xxx}\n if (paramNames && typeof paramNames === 'string') {\n const matchs = regex.exec(paramNames);\n if (matchs?.[1]) {\n paramNameList = matchs?.[1]?.split('.');\n }\n }\n\n if (paramNameList.length === 0) {\n return paramNames;\n }\n\n // 如果参数路径中没有 pageParams,先尝试在 data.pageParams 中查找\n // 因为根据注释,这个方法不能去掉 pageParams 那一层\n if (paramNameList[0] !== 'pageParams' && data?.pageParams) {\n const result = loopNodeByParamsPath(paramNameList, data.pageParams);\n if (result !== '' && result !== undefined) {\n return result;\n }\n }\n\n const result = loopNodeByParamsPath(paramNameList, data);\n return result;\n};\n\n\n/**\n * 提供给事件参数转换那边的方法\n * 和replaceParamsValue 区别,\n * 1、不能去掉pageParams那一层\n * 2、字符串拼对象,需要把对象做JSON.stringify转换\n * 3、如果替换不成功,需要返回字符串原始的值\n * @param contentStr \"你好\" ,\"你$好, ${pageParams.userName}\" , \"${pageData}, ${pageParams.userList[0]}\"\n * @param data 数据\n */\nexport const replaceParamsValueForEvent = (\n contentStr: string,\n data: { [key: string]: any } = {},\n) => {\n if (!contentStr || !data || Object.keys(data)?.length <= 0) {\n return undefined;\n }\n const valueArr = splitStringWithTemplateLiteral(contentStr);\n // 单个字符串, 没有拼接\n if (valueArr.length === 1) {\n return getParamsContentByParamKeysForEvent(valueArr[0], data);\n }\n\n\n let nowTemp = '';\n if (typeof contentStr === 'string' && contentStr && data) {\n nowTemp = contentStr.replace(/\\$\\{(.+?)\\}/g, (match) => {\n const filedVal = getParamsContentByParamKeysForEvent(match, data);\n if (typeof filedVal === 'string') {\n return filedVal;\n }\n // 字符串拼对象,需要把对象做JSON.stringify转换\n try {\n return JSON.stringify(filedVal);\n } catch {\n return '';\n }\n });\n }\n return nowTemp;\n};\n\n/** ======上面几个方法主要提供给事件参数使用 勿共用 ===== */\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["escapeString", "result"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/unitConversion.ts
|
|
20
|
+
var unitConversion_exports = {};
|
|
21
|
+
__export(unitConversion_exports, {
|
|
22
|
+
default: () => unitConversion_default
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(unitConversion_exports);
|
|
25
|
+
var unitConversion = (value) => {
|
|
26
|
+
const number = Number(value);
|
|
27
|
+
if (!isNaN(number)) {
|
|
28
|
+
const kbNum = number / 1024;
|
|
29
|
+
const mbNum = kbNum / 1024;
|
|
30
|
+
const gbNum = mbNum / 1024;
|
|
31
|
+
if (gbNum >= 1) {
|
|
32
|
+
return `${gbNum.toFixed(2)}GB`.replace(/\.00/, "");
|
|
33
|
+
}
|
|
34
|
+
if (mbNum >= 1) {
|
|
35
|
+
return `${mbNum.toFixed(2)}MB`.replace(/\.00/, "");
|
|
36
|
+
}
|
|
37
|
+
if (kbNum >= 1) {
|
|
38
|
+
return `${kbNum.toFixed(2)}KB`.replace(/\.00/, "");
|
|
39
|
+
}
|
|
40
|
+
return `${number.toString()}B`;
|
|
41
|
+
}
|
|
42
|
+
return value.toString();
|
|
43
|
+
};
|
|
44
|
+
var unitConversion_default = unitConversion;
|
|
45
|
+
//# sourceMappingURL=unitConversion.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/unitConversion.ts"],
|
|
4
|
+
"sourcesContent": ["const unitConversion = (value:string | number): string => {\n const number = Number(value);\n if (!isNaN(number)) {\n const kbNum = number / 1024;\n const mbNum = kbNum / 1024;\n const gbNum = mbNum / 1024;\n if (gbNum >= 1) {\n return `${gbNum.toFixed(2)}GB`.replace(/\\.00/, '');\n }\n if (mbNum >= 1) {\n return `${mbNum.toFixed(2)}MB`.replace(/\\.00/, '');\n }\n if (kbNum >= 1) {\n return `${kbNum.toFixed(2)}KB`.replace(/\\.00/, '');\n }\n return `${number.toString()}B`;\n }\n return value.toString();\n};\n\nexport default unitConversion;\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAM,iBAAiB,CAAC,UAAkC;AACxD,QAAM,SAAS,OAAO,KAAK;AAC3B,MAAI,CAAC,MAAM,MAAM,GAAG;AAClB,UAAM,QAAQ,SAAS;AACvB,UAAM,QAAQ,QAAQ;AACtB,UAAM,QAAQ,QAAQ;AACtB,QAAI,SAAS,GAAG;AACd,aAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,QAAQ,QAAQ,EAAE;AAAA,IACnD;AACA,QAAI,SAAS,GAAG;AACd,aAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,QAAQ,QAAQ,EAAE;AAAA,IACnD;AACA,QAAI,SAAS,GAAG;AACd,aAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,QAAQ,QAAQ,EAAE;AAAA,IACnD;AACA,WAAO,GAAG,OAAO,SAAS;AAAA,EAC5B;AACA,SAAO,MAAM,SAAS;AACxB;AAEA,IAAO,yBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/cjs/watermark.d.ts
CHANGED
|
@@ -35,43 +35,15 @@ export interface ContextVariable {
|
|
|
35
35
|
code: string;
|
|
36
36
|
name: string;
|
|
37
37
|
}
|
|
38
|
-
/**
|
|
39
|
-
* 会话信息类型
|
|
40
|
-
*/
|
|
41
|
-
export interface SessionInfo {
|
|
42
|
-
userId?: string;
|
|
43
|
-
userName?: string;
|
|
44
|
-
realName?: string;
|
|
45
|
-
}
|
|
46
38
|
/**
|
|
47
39
|
* XML 转义
|
|
48
40
|
*/
|
|
49
41
|
export declare function escapeXml(str: string): string;
|
|
50
|
-
/**
|
|
51
|
-
* 根据 key 获取变量的真实值
|
|
52
|
-
* @param key 变量 key,支持格式:${system.now}、${system.today}、${system.ip}、${session.userId}、${session.userName}、${session.realName}、${contextParams.xxx}
|
|
53
|
-
*/
|
|
54
|
-
export declare function getVariableRealValue(key: string): string;
|
|
55
42
|
/**
|
|
56
43
|
* 生成水印样式对象
|
|
57
44
|
* @param styles 样式配置
|
|
58
45
|
*/
|
|
59
46
|
export declare function generateWatermarkStyle(styles: WatermarkStyles): CSSProperties;
|
|
60
|
-
/**
|
|
61
|
-
* 异步获取客户端 IP(通过第三方 API)
|
|
62
|
-
* @returns Promise<string> 返回客户端 IP 地址
|
|
63
|
-
*/
|
|
64
|
-
export declare function fetchClientIp(): Promise<string>;
|
|
65
|
-
/**
|
|
66
|
-
* 获取客户端 IP(同步方法,从缓存读取)
|
|
67
|
-
* @returns string 返回客户端 IP 地址,如果缓存中没有则返回默认值 '127.0.0.1'
|
|
68
|
-
*/
|
|
69
|
-
export declare function getClientIp(): string;
|
|
70
|
-
/**
|
|
71
|
-
* 解析 content 中的所有变量并替换为真实值
|
|
72
|
-
* @param content 原始内容,可能包含变量如 ${system.now}、${session.userId}、${contextParams.userName} 等
|
|
73
|
-
*/
|
|
74
|
-
export declare function parseContentVariables(content: string): string;
|
|
75
47
|
/**
|
|
76
48
|
* 生成水印的 base64 数据 URL
|
|
77
49
|
* 当前环境localStore中存有数据 :key=userStores value={"state":{"userInfo":{"token":"16fe343c-78ae-4fd8-93eb-410256dd483b","userId":"1","userName":"admin","phoneNo":"13800138002","email":"admin@localhost.com","realName":"admin2","defaultTenantId":"0","avatar":"./images/avatar/img-user-avatar-10.png","userIcon":"./images/avatar/img-user-avatar-10.png"},"currentTenantId":"1273556018761138176","userSelectedBotOrder":["1211941633166168064","1212229286675095552"],"activeSession":null},"version":0}
|
package/dist/cjs/watermark.js
CHANGED
|
@@ -20,72 +20,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
var watermark_exports = {};
|
|
21
21
|
__export(watermark_exports, {
|
|
22
22
|
escapeXml: () => escapeXml,
|
|
23
|
-
fetchClientIp: () => fetchClientIp,
|
|
24
23
|
generateWatermarkBase64: () => generateWatermarkBase64,
|
|
25
|
-
generateWatermarkStyle: () => generateWatermarkStyle
|
|
26
|
-
getClientIp: () => getClientIp,
|
|
27
|
-
getVariableRealValue: () => getVariableRealValue,
|
|
28
|
-
parseContentVariables: () => parseContentVariables
|
|
24
|
+
generateWatermarkStyle: () => generateWatermarkStyle
|
|
29
25
|
});
|
|
30
26
|
module.exports = __toCommonJS(watermark_exports);
|
|
27
|
+
var import_dealStorageData = require("./dealStorageData");
|
|
31
28
|
function escapeXml(str) {
|
|
32
29
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
33
30
|
}
|
|
34
|
-
function getVariableRealValue(key) {
|
|
35
|
-
const sessionInfo = getUserInfoFromStorage();
|
|
36
|
-
const contextParams = getContextParamsFromStorage();
|
|
37
|
-
const clientIp = getClientIp();
|
|
38
|
-
const now = /* @__PURE__ */ new Date();
|
|
39
|
-
const systemMatch = key.match(/^\$\{system\.(\w+)\}$/);
|
|
40
|
-
if (systemMatch) {
|
|
41
|
-
const systemKey = systemMatch[1];
|
|
42
|
-
switch (systemKey) {
|
|
43
|
-
case "now": {
|
|
44
|
-
const year = now.getFullYear();
|
|
45
|
-
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
46
|
-
const day = String(now.getDate()).padStart(2, "0");
|
|
47
|
-
const hours = String(now.getHours()).padStart(2, "0");
|
|
48
|
-
const minutes = String(now.getMinutes()).padStart(2, "0");
|
|
49
|
-
const seconds = String(now.getSeconds()).padStart(2, "0");
|
|
50
|
-
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
51
|
-
}
|
|
52
|
-
case "today": {
|
|
53
|
-
const year = now.getFullYear();
|
|
54
|
-
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
55
|
-
const day = String(now.getDate()).padStart(2, "0");
|
|
56
|
-
return `${year}-${month}-${day}`;
|
|
57
|
-
}
|
|
58
|
-
case "ip":
|
|
59
|
-
return clientIp;
|
|
60
|
-
default:
|
|
61
|
-
return "";
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
const sessionMatch = key.match(/^\$\{session\.(\w+)\}$/);
|
|
65
|
-
if (sessionMatch) {
|
|
66
|
-
const sessionKey = sessionMatch[1];
|
|
67
|
-
switch (sessionKey) {
|
|
68
|
-
case "userId":
|
|
69
|
-
return sessionInfo.userId || "";
|
|
70
|
-
case "userName":
|
|
71
|
-
return sessionInfo.userName || "";
|
|
72
|
-
case "realName":
|
|
73
|
-
return sessionInfo.realName || "";
|
|
74
|
-
default:
|
|
75
|
-
return "";
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
const contextParamsMatch = key.match(/^\$\{contextParams\.(\w+)\}$/);
|
|
79
|
-
if (contextParamsMatch) {
|
|
80
|
-
const contextParamsKey = contextParamsMatch[1];
|
|
81
|
-
if (contextParams && typeof contextParams === "object") {
|
|
82
|
-
const value = contextParams[contextParamsKey];
|
|
83
|
-
return value != null ? String(value) : "";
|
|
84
|
-
}
|
|
85
|
-
return "";
|
|
86
|
-
}
|
|
87
|
-
return "";
|
|
88
|
-
}
|
|
89
31
|
function generateWatermarkStyle(styles) {
|
|
90
32
|
return {
|
|
91
33
|
color: styles.color,
|
|
@@ -96,220 +38,9 @@ function generateWatermarkStyle(styles) {
|
|
|
96
38
|
lineHeight: 1.2
|
|
97
39
|
};
|
|
98
40
|
}
|
|
99
|
-
function getUserInfoFromStorage() {
|
|
100
|
-
var _a;
|
|
101
|
-
try {
|
|
102
|
-
if (typeof window === "undefined") {
|
|
103
|
-
return {};
|
|
104
|
-
}
|
|
105
|
-
let userStoresStr = null;
|
|
106
|
-
if (window.sessionStorage) {
|
|
107
|
-
userStoresStr = window.sessionStorage.getItem("userStores");
|
|
108
|
-
}
|
|
109
|
-
if (!userStoresStr && window.localStorage) {
|
|
110
|
-
userStoresStr = window.localStorage.getItem("userStores");
|
|
111
|
-
}
|
|
112
|
-
if (!userStoresStr) {
|
|
113
|
-
return {};
|
|
114
|
-
}
|
|
115
|
-
const userStores = JSON.parse(userStoresStr);
|
|
116
|
-
const userInfo = (_a = userStores == null ? void 0 : userStores.state) == null ? void 0 : _a.userInfo;
|
|
117
|
-
if (!userInfo) {
|
|
118
|
-
return {};
|
|
119
|
-
}
|
|
120
|
-
return {
|
|
121
|
-
userId: userInfo.userId || "",
|
|
122
|
-
userName: userInfo.userName || "",
|
|
123
|
-
realName: userInfo.realName || ""
|
|
124
|
-
};
|
|
125
|
-
} catch (e) {
|
|
126
|
-
console.warn("Failed to get user info from storage:", e);
|
|
127
|
-
return {};
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
function getContextParamsFromStorage() {
|
|
131
|
-
try {
|
|
132
|
-
if (typeof window === "undefined") {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
let contextParamsStr = null;
|
|
136
|
-
if (window.sessionStorage) {
|
|
137
|
-
contextParamsStr = window.sessionStorage.getItem("contextParams");
|
|
138
|
-
}
|
|
139
|
-
if (!contextParamsStr && window.localStorage) {
|
|
140
|
-
contextParamsStr = window.localStorage.getItem("contextParams");
|
|
141
|
-
}
|
|
142
|
-
if (!contextParamsStr) {
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
return JSON.parse(contextParamsStr) || null;
|
|
146
|
-
} catch (e) {
|
|
147
|
-
console.warn("Failed to get contextParams from storage:", e);
|
|
148
|
-
return null;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
function getClientIpFromStorage() {
|
|
152
|
-
try {
|
|
153
|
-
if (typeof window === "undefined") {
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
let cachedIp = null;
|
|
157
|
-
if (window.sessionStorage) {
|
|
158
|
-
cachedIp = window.sessionStorage.getItem("clientIp");
|
|
159
|
-
}
|
|
160
|
-
if (!cachedIp && window.localStorage) {
|
|
161
|
-
cachedIp = window.localStorage.getItem("clientIp");
|
|
162
|
-
}
|
|
163
|
-
return cachedIp;
|
|
164
|
-
} catch (e) {
|
|
165
|
-
console.warn("Failed to get client IP from storage:", e);
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
function setClientIpToStorage(ip) {
|
|
170
|
-
try {
|
|
171
|
-
if (typeof window === "undefined") {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
if (window.sessionStorage) {
|
|
175
|
-
window.sessionStorage.setItem("clientIp", ip);
|
|
176
|
-
}
|
|
177
|
-
if (window.localStorage) {
|
|
178
|
-
window.localStorage.setItem("clientIp", ip);
|
|
179
|
-
}
|
|
180
|
-
} catch (e) {
|
|
181
|
-
console.warn("Failed to save client IP to storage:", e);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
async function fetchClientIp() {
|
|
185
|
-
const cachedIp = getClientIpFromStorage();
|
|
186
|
-
if (cachedIp) {
|
|
187
|
-
return cachedIp;
|
|
188
|
-
}
|
|
189
|
-
const ipServices = [
|
|
190
|
-
"https://api.ipify.org?format=json",
|
|
191
|
-
"https://api.ip.sb/ip",
|
|
192
|
-
"https://api.ipify.org"
|
|
193
|
-
];
|
|
194
|
-
for (const serviceUrl of ipServices) {
|
|
195
|
-
try {
|
|
196
|
-
const response = await fetch(serviceUrl, {
|
|
197
|
-
method: "GET",
|
|
198
|
-
headers: {
|
|
199
|
-
Accept: "application/json"
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
if (response.ok) {
|
|
203
|
-
let ip;
|
|
204
|
-
const contentType = response.headers.get("content-type");
|
|
205
|
-
if (contentType && contentType.includes("application/json")) {
|
|
206
|
-
const data = await response.json();
|
|
207
|
-
ip = data.ip || data.query || data.origin || "";
|
|
208
|
-
} else {
|
|
209
|
-
ip = (await response.text()).trim();
|
|
210
|
-
}
|
|
211
|
-
if (ip && /^(\d{1,3}\.){3}\d{1,3}$/.test(ip)) {
|
|
212
|
-
setClientIpToStorage(ip);
|
|
213
|
-
return ip;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
} catch (e) {
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
const defaultIp = "127.0.0.1";
|
|
220
|
-
console.warn("Failed to fetch client IP, using default:", defaultIp);
|
|
221
|
-
return defaultIp;
|
|
222
|
-
}
|
|
223
|
-
function getClientIp() {
|
|
224
|
-
const cachedIp = getClientIpFromStorage();
|
|
225
|
-
if (cachedIp) {
|
|
226
|
-
return cachedIp;
|
|
227
|
-
}
|
|
228
|
-
if (typeof window !== "undefined") {
|
|
229
|
-
fetchClientIp().catch(() => {
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
return "127.0.0.1";
|
|
233
|
-
}
|
|
234
|
-
function parseContentVariables(content) {
|
|
235
|
-
const variableRegex = /\$\{(system|session|contextParams)\.(\w+)\}/g;
|
|
236
|
-
let cachedSessionInfo = null;
|
|
237
|
-
let cachedContextParams = null;
|
|
238
|
-
let contextParamsRead = false;
|
|
239
|
-
return content.replace(variableRegex, (match, type, key) => {
|
|
240
|
-
const variableKey = `\${${type}.${key}}`;
|
|
241
|
-
if (type === "session" && cachedSessionInfo === null) {
|
|
242
|
-
cachedSessionInfo = getUserInfoFromStorage();
|
|
243
|
-
}
|
|
244
|
-
if (type === "contextParams" && !contextParamsRead) {
|
|
245
|
-
cachedContextParams = getContextParamsFromStorage();
|
|
246
|
-
contextParamsRead = true;
|
|
247
|
-
}
|
|
248
|
-
if (type === "session" || type === "contextParams") {
|
|
249
|
-
return getVariableRealValueWithCache(variableKey, cachedSessionInfo, cachedContextParams);
|
|
250
|
-
}
|
|
251
|
-
return getVariableRealValue(variableKey);
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
function getVariableRealValueWithCache(key, sessionInfo, contextParams) {
|
|
255
|
-
const clientIp = getClientIp();
|
|
256
|
-
const now = /* @__PURE__ */ new Date();
|
|
257
|
-
const systemMatch = key.match(/^\$\{system\.(\w+)\}$/);
|
|
258
|
-
if (systemMatch) {
|
|
259
|
-
const systemKey = systemMatch[1];
|
|
260
|
-
switch (systemKey) {
|
|
261
|
-
case "now": {
|
|
262
|
-
const year = now.getFullYear();
|
|
263
|
-
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
264
|
-
const day = String(now.getDate()).padStart(2, "0");
|
|
265
|
-
const hours = String(now.getHours()).padStart(2, "0");
|
|
266
|
-
const minutes = String(now.getMinutes()).padStart(2, "0");
|
|
267
|
-
const seconds = String(now.getSeconds()).padStart(2, "0");
|
|
268
|
-
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
269
|
-
}
|
|
270
|
-
case "today": {
|
|
271
|
-
const year = now.getFullYear();
|
|
272
|
-
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
273
|
-
const day = String(now.getDate()).padStart(2, "0");
|
|
274
|
-
return `${year}-${month}-${day}`;
|
|
275
|
-
}
|
|
276
|
-
case "ip":
|
|
277
|
-
return clientIp;
|
|
278
|
-
default:
|
|
279
|
-
return "";
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
const sessionMatch = key.match(/^\$\{session\.(\w+)\}$/);
|
|
283
|
-
if (sessionMatch) {
|
|
284
|
-
const sessionKey = sessionMatch[1];
|
|
285
|
-
if (sessionInfo) {
|
|
286
|
-
switch (sessionKey) {
|
|
287
|
-
case "userId":
|
|
288
|
-
return sessionInfo.userId || "";
|
|
289
|
-
case "userName":
|
|
290
|
-
return sessionInfo.userName || "";
|
|
291
|
-
case "realName":
|
|
292
|
-
return sessionInfo.realName || "";
|
|
293
|
-
default:
|
|
294
|
-
return "";
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
return "";
|
|
298
|
-
}
|
|
299
|
-
const contextParamsMatch = key.match(/^\$\{contextParams\.(\w+)\}$/);
|
|
300
|
-
if (contextParamsMatch) {
|
|
301
|
-
const contextParamsKey = contextParamsMatch[1];
|
|
302
|
-
if (contextParams && typeof contextParams === "object") {
|
|
303
|
-
const value = contextParams[contextParamsKey];
|
|
304
|
-
return value != null ? String(value) : "";
|
|
305
|
-
}
|
|
306
|
-
return "";
|
|
307
|
-
}
|
|
308
|
-
return "";
|
|
309
|
-
}
|
|
310
41
|
function generateWatermarkBase64(config) {
|
|
311
42
|
const { styles: styleConfig, layout, content } = config;
|
|
312
|
-
const realContent = parseContentVariables(content || "");
|
|
43
|
+
const realContent = (0, import_dealStorageData.parseContentVariables)(content || "");
|
|
313
44
|
const textLines = realContent.split("\n").filter((line) => line.trim() !== "");
|
|
314
45
|
if (textLines.length === 0) {
|
|
315
46
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="${layout.horizontalSpacing}" height="${layout.verticalSpacing}"></svg>`)}`;
|
|
@@ -340,11 +71,7 @@ function generateWatermarkBase64(config) {
|
|
|
340
71
|
// Annotate the CommonJS export names for ESM import in node:
|
|
341
72
|
0 && (module.exports = {
|
|
342
73
|
escapeXml,
|
|
343
|
-
fetchClientIp,
|
|
344
74
|
generateWatermarkBase64,
|
|
345
|
-
generateWatermarkStyle
|
|
346
|
-
getClientIp,
|
|
347
|
-
getVariableRealValue,
|
|
348
|
-
parseContentVariables
|
|
75
|
+
generateWatermarkStyle
|
|
349
76
|
});
|
|
350
77
|
//# sourceMappingURL=watermark.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/watermark.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * 水印工具函数\n */\n\nimport type { CSSProperties } from 'react';\n\nexport interface WatermarkStyles {\n color: string;\n opacity: number;\n fontSize: number;\n angle: number;\n}\n\nexport interface WatermarkLayout {\n density: string;\n horizontalSpacing: number;\n verticalSpacing: number;\n arrangement: string;\n}\n\n/**\n * 水印行配置\n */\nexport interface WatermarkRow {\n enabled: boolean;\n variable?: string;\n text?: string;\n}\n\nexport interface WatermarkConfig {\n content: string;\n styles: WatermarkStyles;\n layout: WatermarkLayout;\n rows?: WatermarkRow[]; // 可选,用于向后兼容\n}\n\n/**\n * 上下文变量类型\n */\nexport interface ContextVariable {\n code: string;\n name: string;\n}\n\n/**\n * 会话信息类型\n */\nexport interface SessionInfo {\n userId?: string;\n userName?: string;\n realName?: string;\n}\n\n/**\n * XML 转义\n */\nexport function escapeXml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * 根据 key 获取变量的真实值\n * @param key 变量 key,支持格式:${system.now}、${system.today}、${system.ip}、${session.userId}、${session.userName}、${session.realName}、${contextParams.xxx}\n */\nexport function getVariableRealValue(\n key: string,\n): string {\n // 从 sessionStorage 获取用户信息\n const sessionInfo = getUserInfoFromStorage();\n \n // 从 storage 获取 contextParams\n const contextParams = getContextParamsFromStorage();\n \n // 获取客户端 IP(从缓存读取,如果没有则返回默认值)\n const clientIp = getClientIp();\n\n const now = new Date();\n\n // 处理 ${system.xxx} 格式\n const systemMatch = key.match(/^\\$\\{system\\.(\\w+)\\}$/);\n if (systemMatch) {\n const systemKey = systemMatch[1];\n switch (systemKey) {\n case 'now': {\n // 当前时间:格式为 YYYY-MM-DD HH:mm:ss\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;\n }\n case 'today': {\n // 当前日期:格式为 YYYY-MM-DD\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n }\n case 'ip':\n return clientIp;\n default:\n return '';\n }\n }\n\n // 处理 ${session.xxx} 格式\n const sessionMatch = key.match(/^\\$\\{session\\.(\\w+)\\}$/);\n if (sessionMatch) {\n const sessionKey = sessionMatch[1];\n switch (sessionKey) {\n case 'userId':\n return sessionInfo.userId || '';\n case 'userName':\n return sessionInfo.userName || '';\n case 'realName':\n return sessionInfo.realName || '';\n default:\n return '';\n }\n }\n\n // 处理 ${contextParams.xxx} 格式\n const contextParamsMatch = key.match(/^\\$\\{contextParams\\.(\\w+)\\}$/);\n if (contextParamsMatch) {\n const contextParamsKey = contextParamsMatch[1];\n if (contextParams && typeof contextParams === 'object') {\n const value = contextParams[contextParamsKey];\n // 如果值是 null 或 undefined,返回空字符串;否则转换为字符串\n return value != null ? String(value) : '';\n }\n return '';\n }\n return '';\n}\n\n/**\n * 生成水印样式对象\n * @param styles 样式配置\n */\nexport function generateWatermarkStyle(styles: WatermarkStyles): CSSProperties {\n return {\n color: styles.color,\n fontSize: `${styles.fontSize}px`,\n opacity: styles.opacity / 100,\n transform: `rotate(${styles.angle}deg)`,\n whiteSpace: 'nowrap' as const,\n lineHeight: 1.2,\n };\n}\n\n/**\n * 从 storage 获取用户信息(优先从 sessionStorage,其次从 localStorage)\n */\nfunction getUserInfoFromStorage(): SessionInfo {\n try {\n if (typeof window === 'undefined') {\n return {};\n }\n\n // 优先从 sessionStorage 读取,如果没有则从 localStorage 读取\n let userStoresStr = null;\n if (window.sessionStorage) {\n userStoresStr = window.sessionStorage.getItem('userStores');\n }\n if (!userStoresStr && window.localStorage) {\n userStoresStr = window.localStorage.getItem('userStores');\n }\n\n if (!userStoresStr) {\n return {};\n }\n\n const userStores = JSON.parse(userStoresStr);\n const userInfo = userStores?.state?.userInfo;\n if (!userInfo) {\n return {};\n }\n return {\n userId: userInfo.userId || '',\n userName: userInfo.userName || '',\n realName: userInfo.realName || '',\n };\n } catch (e) {\n console.warn('Failed to get user info from storage:', e);\n return {};\n }\n}\n\n/**\n * 从 storage 获取 contextParams(优先从 sessionStorage,其次从 localStorage)\n */\nfunction getContextParamsFromStorage(): { [key: string]: any } | null {\n try {\n if (typeof window === 'undefined') {\n return null;\n }\n\n // 优先从 sessionStorage 读取,如果没有则从 localStorage 读取\n let contextParamsStr = null;\n if (window.sessionStorage) {\n contextParamsStr = window.sessionStorage.getItem('contextParams');\n }\n if (!contextParamsStr && window.localStorage) {\n contextParamsStr = window.localStorage.getItem('contextParams');\n }\n\n if (!contextParamsStr) {\n return null;\n }\n\n return JSON.parse(contextParamsStr) || null;\n } catch (e) {\n console.warn('Failed to get contextParams from storage:', e);\n return null;\n }\n}\n\n/**\n * 从 storage 获取缓存的客户端 IP\n */\nfunction getClientIpFromStorage(): string | null {\n try {\n if (typeof window === 'undefined') {\n return null;\n }\n\n // 优先从 sessionStorage 读取,如果没有则从 localStorage 读取\n let cachedIp = null;\n if (window.sessionStorage) {\n cachedIp = window.sessionStorage.getItem('clientIp');\n }\n if (!cachedIp && window.localStorage) {\n cachedIp = window.localStorage.getItem('clientIp');\n }\n\n return cachedIp;\n } catch (e) {\n console.warn('Failed to get client IP from storage:', e);\n return null;\n }\n}\n\n/**\n * 缓存客户端 IP 到 storage\n */\nfunction setClientIpToStorage(ip: string): void {\n try {\n if (typeof window === 'undefined') {\n return;\n }\n\n // 优先保存到 sessionStorage,同时保存到 localStorage 作为备份\n if (window.sessionStorage) {\n window.sessionStorage.setItem('clientIp', ip);\n }\n if (window.localStorage) {\n window.localStorage.setItem('clientIp', ip);\n }\n } catch (e) {\n console.warn('Failed to save client IP to storage:', e);\n }\n}\n\n/**\n * 异步获取客户端 IP(通过第三方 API)\n * @returns Promise<string> 返回客户端 IP 地址\n */\nexport async function fetchClientIp(): Promise<string> {\n // 先检查缓存\n const cachedIp = getClientIpFromStorage();\n if (cachedIp) {\n return cachedIp;\n }\n\n // 尝试多个 IP 查询服务(按优先级)\n const ipServices = [\n 'https://api.ipify.org?format=json',\n 'https://api.ip.sb/ip',\n 'https://api.ipify.org',\n ];\n\n for (const serviceUrl of ipServices) {\n try {\n const response = await fetch(serviceUrl, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n });\n\n if (response.ok) {\n let ip: string;\n const contentType = response.headers.get('content-type');\n \n if (contentType && contentType.includes('application/json')) {\n const data = await response.json();\n ip = data.ip || data.query || data.origin || '';\n } else {\n ip = (await response.text()).trim();\n }\n\n // 验证 IP 格式\n if (ip && /^(\\d{1,3}\\.){3}\\d{1,3}$/.test(ip)) {\n // 缓存 IP\n setClientIpToStorage(ip);\n return ip;\n }\n }\n } catch (e) {\n // 继续尝试下一个服务(静默失败)\n }\n }\n\n // 所有服务都失败,返回默认值\n const defaultIp = '127.0.0.1';\n console.warn('Failed to fetch client IP, using default:', defaultIp);\n return defaultIp;\n}\n\n/**\n * 获取客户端 IP(同步方法,从缓存读取)\n * @returns string 返回客户端 IP 地址,如果缓存中没有则返回默认值 '127.0.0.1'\n */\nexport function getClientIp(): string {\n const cachedIp = getClientIpFromStorage();\n if (cachedIp) {\n return cachedIp;\n }\n\n // 如果没有缓存,尝试异步获取(不阻塞当前调用)\n // 下次调用时会使用缓存的 IP\n if (typeof window !== 'undefined') {\n fetchClientIp().catch(() => {\n // 静默失败,不影响当前调用\n });\n }\n\n return '127.0.0.1';\n}\n\n/**\n * 解析 content 中的所有变量并替换为真实值\n * @param content 原始内容,可能包含变量如 ${system.now}、${session.userId}、${contextParams.userName} 等\n */\nexport function parseContentVariables(\n content: string,\n): string {\n // 匹配所有变量:${system.xxx}、${session.xxx} 或 ${contextParams.xxx}\n const variableRegex = /\\$\\{(system|session|contextParams)\\.(\\w+)\\}/g;\n \n // 缓存 storage 读取结果,避免在解析多个变量时重复读取\n let cachedSessionInfo: SessionInfo | null = null;\n let cachedContextParams: { [key: string]: any } | null = null;\n let contextParamsRead = false; // 标记是否已读取 contextParams\n \n return content.replace(variableRegex, (match, type, key) => {\n const variableKey = `\\${${type}.${key}}`;\n \n // 对于需要 storage 数据的变量类型,使用缓存\n if (type === 'session' && cachedSessionInfo === null) {\n cachedSessionInfo = getUserInfoFromStorage();\n }\n if (type === 'contextParams' && !contextParamsRead) {\n cachedContextParams = getContextParamsFromStorage();\n contextParamsRead = true;\n }\n \n // 如果变量需要 session 或 contextParams,使用缓存的版本\n if (type === 'session' || type === 'contextParams') {\n return getVariableRealValueWithCache(variableKey, cachedSessionInfo, cachedContextParams);\n }\n \n // 其他类型(system)直接调用\n return getVariableRealValue(variableKey);\n });\n}\n\n/**\n * 带缓存的变量值获取(内部使用)\n */\nfunction getVariableRealValueWithCache(\n key: string,\n sessionInfo: SessionInfo | null,\n contextParams: { [key: string]: any } | null\n): string {\n // 获取客户端 IP(从缓存读取,如果没有则返回默认值)\n const clientIp = getClientIp();\n const now = new Date();\n\n // 处理 ${system.xxx} 格式\n const systemMatch = key.match(/^\\$\\{system\\.(\\w+)\\}$/);\n if (systemMatch) {\n const systemKey = systemMatch[1];\n switch (systemKey) {\n case 'now': {\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;\n }\n case 'today': {\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n }\n case 'ip':\n return clientIp;\n default:\n return '';\n }\n }\n\n // 处理 ${session.xxx} 格式\n const sessionMatch = key.match(/^\\$\\{session\\.(\\w+)\\}$/);\n if (sessionMatch) {\n const sessionKey = sessionMatch[1];\n if (sessionInfo) {\n switch (sessionKey) {\n case 'userId':\n return sessionInfo.userId || '';\n case 'userName':\n return sessionInfo.userName || '';\n case 'realName':\n return sessionInfo.realName || '';\n default:\n return '';\n }\n }\n return '';\n }\n\n // 处理 ${contextParams.xxx} 格式\n const contextParamsMatch = key.match(/^\\$\\{contextParams\\.(\\w+)\\}$/);\n if (contextParamsMatch) {\n const contextParamsKey = contextParamsMatch[1];\n if (contextParams && typeof contextParams === 'object') {\n const value = contextParams[contextParamsKey];\n return value != null ? String(value) : '';\n }\n return '';\n }\n return '';\n}\n\n/**\n * 生成水印的 base64 数据 URL\n * 当前环境localStore中存有数据 :key=userStores value={\"state\":{\"userInfo\":{\"token\":\"16fe343c-78ae-4fd8-93eb-410256dd483b\",\"userId\":\"1\",\"userName\":\"admin\",\"phoneNo\":\"13800138002\",\"email\":\"admin@localhost.com\",\"realName\":\"admin2\",\"defaultTenantId\":\"0\",\"avatar\":\"./images/avatar/img-user-avatar-10.png\",\"userIcon\":\"./images/avatar/img-user-avatar-10.png\"},\"currentTenantId\":\"1273556018761138176\",\"userSelectedBotOrder\":[\"1211941633166168064\",\"1212229286675095552\"],\"activeSession\":null},\"version\":0}\n * config参考: {\"enabled\":true,\"content\":\"测试水印 ${session.userId}\",\"styles\":{\"color\":\"#999999\",\"opacity\":20,\"fontSize\":16,\"angle\":-15},\"layout\":{\"density\":\"medium\",\"horizontalSpacing\":100,\"verticalSpacing\":100,\"arrangement\":\"tile\"}}\n */\nexport function generateWatermarkBase64(\n config: WatermarkConfig,\n): string {\n const { styles: styleConfig, layout, content } = config;\n\n // 解析 content 中的所有变量并替换为真实值\n const realContent = parseContentVariables(content || '');\n \n // 处理多行文本(按换行符分割,保留非空行)\n const textLines = realContent.split('\\n').filter(line => line.trim() !== '');\n \n // 如果没有有效文本,使用空字符串\n if (textLines.length === 0) {\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${layout.horizontalSpacing}\" height=\"${layout.verticalSpacing}\"></svg>`)}`;\n }\n \n const escapedColor = escapeXml(styleConfig.color);\n const lineHeight = styleConfig.fontSize * 1.2; // 行高为字体大小的1.2倍\n \n // 计算文本总高度\n const textHeight = textLines.length * lineHeight;\n // 垂直居中:从垂直间距的中心位置开始,向上偏移文本高度的一半\n const startY = layout.verticalSpacing / 2 - textHeight / 2 + lineHeight;\n\n // 使用 tspan 来显示多行文本\n const tspanElements = textLines.map((line: string, index: number) => {\n const escapedLine = escapeXml(line);\n const y = startY + index * lineHeight;\n return `<tspan x=\"10\" y=\"${y}\">${escapedLine}</tspan>`;\n }).join('');\n\n const svgContent = `\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${layout.horizontalSpacing}\" height=\"${layout.verticalSpacing}\">\n <text\n font-size=\"${styleConfig.fontSize}\"\n fill=\"${escapedColor}\"\n fill-opacity=\"${styleConfig.opacity / 100}\"\n transform=\"rotate(${styleConfig.angle} ${layout.horizontalSpacing / 2} ${layout.verticalSpacing / 2})\"\n >\n ${tspanElements}\n </text>\n </svg>\n `.replace(/\\s+/g, ' ');\n\n // 使用 encodeURIComponent 而不是 btoa,以支持中文字符\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgContent)}`;\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["/**\n * 水印工具函数\n */\n\nimport type { CSSProperties } from 'react';\nimport { parseContentVariables } from './dealStorageData';\n\nexport interface WatermarkStyles {\n color: string;\n opacity: number;\n fontSize: number;\n angle: number;\n}\n\nexport interface WatermarkLayout {\n density: string;\n horizontalSpacing: number;\n verticalSpacing: number;\n arrangement: string;\n}\n\n/**\n * 水印行配置\n */\nexport interface WatermarkRow {\n enabled: boolean;\n variable?: string;\n text?: string;\n}\n\nexport interface WatermarkConfig {\n content: string;\n styles: WatermarkStyles;\n layout: WatermarkLayout;\n rows?: WatermarkRow[]; // 可选,用于向后兼容\n}\n\n/**\n * 上下文变量类型\n */\nexport interface ContextVariable {\n code: string;\n name: string;\n}\n\n/**\n * XML 转义\n */\nexport function escapeXml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * 生成水印样式对象\n * @param styles 样式配置\n */\nexport function generateWatermarkStyle(styles: WatermarkStyles): CSSProperties {\n return {\n color: styles.color,\n fontSize: `${styles.fontSize}px`,\n opacity: styles.opacity / 100,\n transform: `rotate(${styles.angle}deg)`,\n whiteSpace: 'nowrap' as const,\n lineHeight: 1.2,\n };\n}\n\n/**\n * 生成水印的 base64 数据 URL\n * 当前环境localStore中存有数据 :key=userStores value={\"state\":{\"userInfo\":{\"token\":\"16fe343c-78ae-4fd8-93eb-410256dd483b\",\"userId\":\"1\",\"userName\":\"admin\",\"phoneNo\":\"13800138002\",\"email\":\"admin@localhost.com\",\"realName\":\"admin2\",\"defaultTenantId\":\"0\",\"avatar\":\"./images/avatar/img-user-avatar-10.png\",\"userIcon\":\"./images/avatar/img-user-avatar-10.png\"},\"currentTenantId\":\"1273556018761138176\",\"userSelectedBotOrder\":[\"1211941633166168064\",\"1212229286675095552\"],\"activeSession\":null},\"version\":0}\n * config参考: {\"enabled\":true,\"content\":\"测试水印 ${session.userId}\",\"styles\":{\"color\":\"#999999\",\"opacity\":20,\"fontSize\":16,\"angle\":-15},\"layout\":{\"density\":\"medium\",\"horizontalSpacing\":100,\"verticalSpacing\":100,\"arrangement\":\"tile\"}}\n */\nexport function generateWatermarkBase64(\n config: WatermarkConfig,\n): string {\n const { styles: styleConfig, layout, content } = config;\n\n // 解析 content 中的所有变量并替换为真实值\n const realContent = parseContentVariables(content || '');\n \n // 处理多行文本(按换行符分割,保留非空行)\n const textLines = realContent.split('\\n').filter(line => line.trim() !== '');\n \n // 如果没有有效文本,使用空字符串\n if (textLines.length === 0) {\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${layout.horizontalSpacing}\" height=\"${layout.verticalSpacing}\"></svg>`)}`;\n }\n \n const escapedColor = escapeXml(styleConfig.color);\n const lineHeight = styleConfig.fontSize * 1.2; // 行高为字体大小的1.2倍\n \n // 计算文本总高度\n const textHeight = textLines.length * lineHeight;\n // 垂直居中:从垂直间距的中心位置开始,向上偏移文本高度的一半\n const startY = layout.verticalSpacing / 2 - textHeight / 2 + lineHeight;\n\n // 使用 tspan 来显示多行文本\n const tspanElements = textLines.map((line: string, index: number) => {\n const escapedLine = escapeXml(line);\n const y = startY + index * lineHeight;\n return `<tspan x=\"10\" y=\"${y}\">${escapedLine}</tspan>`;\n }).join('');\n\n const svgContent = `\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${layout.horizontalSpacing}\" height=\"${layout.verticalSpacing}\">\n <text\n font-size=\"${styleConfig.fontSize}\"\n fill=\"${escapedColor}\"\n fill-opacity=\"${styleConfig.opacity / 100}\"\n transform=\"rotate(${styleConfig.angle} ${layout.horizontalSpacing / 2} ${layout.verticalSpacing / 2})\"\n >\n ${tspanElements}\n </text>\n </svg>\n `.replace(/\\s+/g, ' ');\n\n // 使用 encodeURIComponent 而不是 btoa,以支持中文字符\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgContent)}`;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,6BAAsC;AA2C/B,SAAS,UAAU,KAAqB;AAC7C,SAAO,IACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,QAAQ;AAC3B;AAMO,SAAS,uBAAuB,QAAwC;AAC7E,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd,UAAU,GAAG,OAAO;AAAA,IACpB,SAAS,OAAO,UAAU;AAAA,IAC1B,WAAW,UAAU,OAAO;AAAA,IAC5B,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AAOO,SAAS,wBACd,QACQ;AACR,QAAM,EAAE,QAAQ,aAAa,QAAQ,QAAQ,IAAI;AAGjD,QAAM,kBAAc,8CAAsB,WAAW,EAAE;AAGvD,QAAM,YAAY,YAAY,MAAM,IAAI,EAAE,OAAO,UAAQ,KAAK,KAAK,MAAM,EAAE;AAG3E,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO,oCAAoC,mBAAmB,kDAAkD,OAAO,8BAA8B,OAAO,yBAAyB;AAAA,EACvL;AAEA,QAAM,eAAe,UAAU,YAAY,KAAK;AAChD,QAAM,aAAa,YAAY,WAAW;AAG1C,QAAM,aAAa,UAAU,SAAS;AAEtC,QAAM,SAAS,OAAO,kBAAkB,IAAI,aAAa,IAAI;AAG7D,QAAM,gBAAgB,UAAU,IAAI,CAAC,MAAc,UAAkB;AACnE,UAAM,cAAc,UAAU,IAAI;AAClC,UAAM,IAAI,SAAS,QAAQ;AAC3B,WAAO,oBAAoB,MAAM;AAAA,EACnC,CAAC,EAAE,KAAK,EAAE;AAEV,QAAM,aAAa;AAAA,qDACgC,OAAO,8BAA8B,OAAO;AAAA;AAAA,qBAE5E,YAAY;AAAA,gBACjB;AAAA,wBACQ,YAAY,UAAU;AAAA,4BAClB,YAAY,SAAS,OAAO,oBAAoB,KAAK,OAAO,kBAAkB;AAAA;AAAA,UAEhG;AAAA;AAAA;AAAA,IAGN,QAAQ,QAAQ,GAAG;AAGrB,SAAO,oCAAoC,mBAAmB,UAAU;AAC1E;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
var aiGenearteFill = function aiGenearteFill() {
|
|
2
|
+
// 使用 SVG 命名空间创建 SVG 元素,确保正确的 SVG 上下文
|
|
3
|
+
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
4
|
+
// 设置 SVG 为隐藏,作为渐变定义的容器(outlet)
|
|
5
|
+
svg.style.position = 'absolute';
|
|
6
|
+
svg.style.width = '0';
|
|
7
|
+
svg.style.height = '0';
|
|
8
|
+
svg.style.visibility = 'hidden';
|
|
9
|
+
svg.style.overflow = 'hidden';
|
|
10
|
+
svg.innerHTML = "\n <defs>\n <linearGradient id=\"icon-ai-generate_svg__a\" x1=\"-6.64737\" y1=\"3.91997\" x2=\"17.3507\" y2=\"13.7217\" gradientUnits=\"userSpaceOnUse\">\n <stop stop-color=\"#409DFF\" style=\"stop-color:#409DFF;stop-color:color(display-p3 0.2495 0.6157 1.0000);stop-opacity:1;\"></stop>\n <stop offset=\"0.5\" stop-color=\"#5279FF\" style=\"stop-color:#5279FF;stop-color:color(display-p3 0.3216 0.4745 1.0000);stop-opacity:1;\"></stop>\n <stop offset=\"1\" stop-color=\"#C173FF\" style=\"stop-color:#C173FF;stop-color:color(display-p3 0.7555 0.4512 1.0000);stop-opacity:1;\"></stop>\n </linearGradient>\n </defs>\n ";
|
|
11
|
+
|
|
12
|
+
// 将 SVG 元素添加到 body,作为渐变定义的出口(outlet)
|
|
13
|
+
// 这样其他 SVG 元素就可以通过 ID 引用其中的渐变
|
|
14
|
+
document.body.appendChild(svg);
|
|
15
|
+
};
|
|
16
|
+
export default aiGenearteFill;
|
|
17
|
+
//# sourceMappingURL=aiGenerateFill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["aiGenearteFill","svg","document","createElementNS","style","position","width","height","visibility","overflow","innerHTML","body","appendChild"],"sources":["../../src/aiGenerateFill.ts"],"sourcesContent":["const aiGenearteFill = () => {\n // 使用 SVG 命名空间创建 SVG 元素,确保正确的 SVG 上下文\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n // 设置 SVG 为隐藏,作为渐变定义的容器(outlet)\n svg.style.position = 'absolute';\n svg.style.width = '0';\n svg.style.height = '0';\n svg.style.visibility = 'hidden';\n svg.style.overflow = 'hidden';\n \n svg.innerHTML = `\n <defs>\n <linearGradient id=\"icon-ai-generate_svg__a\" x1=\"-6.64737\" y1=\"3.91997\" x2=\"17.3507\" y2=\"13.7217\" gradientUnits=\"userSpaceOnUse\">\n <stop stop-color=\"#409DFF\" style=\"stop-color:#409DFF;stop-color:color(display-p3 0.2495 0.6157 1.0000);stop-opacity:1;\"></stop>\n <stop offset=\"0.5\" stop-color=\"#5279FF\" style=\"stop-color:#5279FF;stop-color:color(display-p3 0.3216 0.4745 1.0000);stop-opacity:1;\"></stop>\n <stop offset=\"1\" stop-color=\"#C173FF\" style=\"stop-color:#C173FF;stop-color:color(display-p3 0.7555 0.4512 1.0000);stop-opacity:1;\"></stop>\n </linearGradient>\n </defs>\n `;\n \n // 将 SVG 元素添加到 body,作为渐变定义的出口(outlet)\n // 这样其他 SVG 元素就可以通过 ID 引用其中的渐变\n document.body.appendChild(svg);\n};\n\nexport default aiGenearteFill;\n"],"mappings":"AAAA,IAAMA,cAAc,GAAG,SAAjBA,cAAcA,CAAA,EAAS;EAC3B;EACA,IAAMC,GAAG,GAAGC,QAAQ,CAACC,eAAe,CAAC,4BAA4B,EAAE,KAAK,CAAC;EACzE;EACAF,GAAG,CAACG,KAAK,CAACC,QAAQ,GAAG,UAAU;EAC/BJ,GAAG,CAACG,KAAK,CAACE,KAAK,GAAG,GAAG;EACrBL,GAAG,CAACG,KAAK,CAACG,MAAM,GAAG,GAAG;EACtBN,GAAG,CAACG,KAAK,CAACI,UAAU,GAAG,QAAQ;EAC/BP,GAAG,CAACG,KAAK,CAACK,QAAQ,GAAG,QAAQ;EAE7BR,GAAG,CAACS,SAAS,mpBAQZ;;EAED;EACA;EACAR,QAAQ,CAACS,IAAI,CAACC,WAAW,CAACX,GAAG,CAAC;AAChC,CAAC;AAED,eAAeD,cAAc"}
|