adtec-core-package 3.0.8 → 3.0.9

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/AGENTS.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <!-- gitnexus:start -->
2
2
  # GitNexus — Code Intelligence
3
3
 
4
- This project is indexed by GitNexus as **adtec-front-end-core-package** (6158 symbols, 8961 relationships, 149 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
4
+ This project is indexed by GitNexus as **adtec-front-end-core-package** (6187 symbols, 9025 relationships, 155 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
5
5
 
6
6
  > If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
7
7
 
package/CLAUDE.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <!-- gitnexus:start -->
2
2
  # GitNexus — Code Intelligence
3
3
 
4
- This project is indexed by GitNexus as **adtec-front-end-core-package** (6158 symbols, 8961 relationships, 149 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
4
+ This project is indexed by GitNexus as **adtec-front-end-core-package** (6187 symbols, 9025 relationships, 155 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
5
5
 
6
6
  > If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
7
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adtec-core-package",
3
- "version": "3.0.8",
3
+ "version": "3.0.9",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -4,6 +4,10 @@ import type { IWfProcessInstVo, IWfTaskVo } from '../../interface/workflow/IWfTa
4
4
  import type { IWfTaskAskVo } from '../../interface/workflow/IWfTaskAskVo'
5
5
  import type { IWfTaskUsersVo } from '../../interface/workflow/IWfTaskUsersVo'
6
6
  import type { IWfReturnNodeVo } from '../../interface/workflow/IWfReturnNodeVo'
7
+ import type {
8
+ IWfNodeLastApprovalBatchVo,
9
+ IWfNodeLastApprovalQueryVo,
10
+ } from '../../interface/workflow/IWfNodeLastApprovalVo'
7
11
 
8
12
  /**
9
13
  * 创建人:xux
@@ -72,4 +76,12 @@ export default {
72
76
  getWfProcessInstByBusinessId(businessId: string) {
73
77
  return request.get<IWfTaskVo>(baseUrl + '/getUserTaskInfo', { businessId })
74
78
  },
79
+ /** 获取指定节点最后一轮审批人及审批意见(支持多节点,不限制流程是否结束) */
80
+ getLastNodeApprovalByBusinessId(businessId: string, nodeCodes: string | string[]) {
81
+ const query: IWfNodeLastApprovalQueryVo = {
82
+ businessId,
83
+ nodeCodes: Array.isArray(nodeCodes) ? nodeCodes : [nodeCodes],
84
+ }
85
+ return request.post<IWfNodeLastApprovalBatchVo>(baseUrl + '/lastNodeApproval', query)
86
+ },
75
87
  }
@@ -217,9 +217,7 @@ async function remountEditor() {
217
217
  if (remounting || !umoMountOptions.value) return
218
218
  remounting = true
219
219
  try {
220
- const html = ready.value
221
- ? finalizeHtml(getRawHtml(), getRootElement())
222
- : initHtml(model.value ?? '')
220
+ const html = ready.value ? getRawHtml() : (model.value ?? '')
223
221
  ready.value = false
224
222
  editorRef.value = null
225
223
  umoMountOptions.value = null
@@ -286,7 +284,7 @@ async function ensureBlockImageNodeView() {
286
284
  const editor = getEditorInstance()
287
285
  if (editor?.setContent && ready.value) {
288
286
  const html = initHtml(getRawHtml() || (model.value ?? ''))
289
- editor.setContent(html, { emitUpdate: false })
287
+ editor.setContent(html, { emitUpdate: false, parseOptions: { preserveWhitespace: 'full' } })
290
288
  await nextTick()
291
289
  await waitEditorPaintFrames()
292
290
  if (!usesPlainImageDom(rootRef.value)) {
@@ -296,7 +294,7 @@ async function ensureBlockImageNodeView() {
296
294
  }
297
295
 
298
296
  if (ready.value) {
299
- publishModelFromEditor(true)
297
+ publishModelFromEditor()
300
298
  }
301
299
  await remountEditor()
302
300
  await nextTick()
@@ -449,16 +447,15 @@ function applyEditorHtml(html: string, focus = false) {
449
447
  editor?.setContent?.(initHtml(html), {
450
448
  emitUpdate: false,
451
449
  focusPosition: focus ? 'end' : false,
450
+ parseOptions: { preserveWhitespace: 'full' },
452
451
  })
453
452
  }
454
453
 
455
- function publishModelFromEditor(finalize = false) {
454
+ /** 将编辑器 HTML 同步到 v-model;始终使用 getRawHtml,不经 finalizeHtml(避免保存/blur 路径折叠空白) */
455
+ function publishModelFromEditor() {
456
456
  const editor = getEditorInstance()
457
457
  if (!editor) return
458
- let html = getRawHtml()
459
- if (finalize) {
460
- html = finalizeHtml(html, getRootElement())
461
- }
458
+ const html = getRawHtml()
462
459
  syncingContent.value = true
463
460
  model.value = html
464
461
  text.value = getPlainText()
@@ -498,11 +495,11 @@ async function onEditorCreated() {
498
495
 
499
496
  function onEditorChanged() {
500
497
  if (!ready.value || syncingContent.value) return
501
- publishModelFromEditor(false)
498
+ publishModelFromEditor()
502
499
  }
503
500
 
504
501
  function onEditorBlur() {
505
- publishModelFromEditor(true)
502
+ publishModelFromEditor()
506
503
  emit('onBlur', { html: model.value ?? '', text: getPlainText() })
507
504
  }
508
505
 
@@ -537,7 +534,7 @@ watch(editable, async (now, prev) => {
537
534
  if (lastMountEditable.value === now) return
538
535
  if (!umoMountOptions.value) return
539
536
  if (ready.value) {
540
- publishModelFromEditor(true)
537
+ publishModelFromEditor()
541
538
  }
542
539
  await remountEditor()
543
540
  })
@@ -549,7 +546,7 @@ watch(
549
546
  if (now === prev) return
550
547
  if (!umoMountOptions.value) return
551
548
  if (ready.value) {
552
- publishModelFromEditor(true)
549
+ publishModelFromEditor()
553
550
  }
554
551
  await remountEditor()
555
552
  },
@@ -573,9 +570,11 @@ watch(
573
570
  )
574
571
 
575
572
  defineExpose({
576
- getHtml: () => {
573
+ /** 默认返回编辑器原始 HTML(保留空白);导出/含图存档时传 { finalize: true } */
574
+ getHtml: (options?: { finalize?: boolean }) => {
577
575
  if (!ready.value) return model.value ?? ''
578
- return finalizeHtml(getRawHtml(), getRootElement())
576
+ const html = getRawHtml()
577
+ return options?.finalize ? finalizeHtml(html, getRootElement()) : html
579
578
  },
580
579
  getText: () => {
581
580
  if (!ready.value) return text.value ?? ''
@@ -17,15 +17,23 @@ const fontSizes = [
17
17
  { name: '初号', pt: 42, px: 49 },
18
18
  ]
19
19
 
20
+ /** 纯字符串处理,避免 innerHTML 解析时合并连续空格 */
20
21
  function setDefaultPx(html: string) {
21
- const tempDiv = document.createElement('div')
22
- tempDiv.innerHTML = html
23
- tempDiv.querySelectorAll('p').forEach((p) => {
24
- if (!p.style.fontSize) {
25
- p.style.fontSize = '14px'
22
+ return html.replace(/<p\b([^>]*)>/gi, (full, attrs: string) => {
23
+ const attrStr = attrs ?? ''
24
+ if (/style\s*=\s*["'][^"']*font-size\s*:/i.test(attrStr)) {
25
+ return full
26
+ }
27
+ if (/style\s*=\s*(["'])(.*?)\1/i.test(attrStr)) {
28
+ return full.replace(
29
+ /style\s*=\s*(["'])(.*?)\1/i,
30
+ (_m, quote: string, style: string) =>
31
+ `style=${quote}${normalizeStyleString(style)}font-size: 14px;${quote}`,
32
+ )
26
33
  }
34
+ const trimmed = attrStr.trim()
35
+ return trimmed ? `<p ${trimmed} style="font-size: 14px;">` : '<p style="font-size: 14px;">'
27
36
  })
28
- return tempDiv.innerHTML
29
37
  }
30
38
 
31
39
  export function convertPxToPt(html: string) {
@@ -151,6 +159,45 @@ function srcMatchKey(src: string) {
151
159
  return src.length > 100 ? src.substring(0, 100) : src
152
160
  }
153
161
 
162
+ function upsertImgDimensionsInHtml(
163
+ html: string,
164
+ srcKey: string,
165
+ width: number,
166
+ height: number,
167
+ fallbackIndex: number,
168
+ ): string {
169
+ if (!srcKey) return html
170
+
171
+ const imgTagPattern = /<img\b[^>]*\/?>/gi
172
+ const matches = [...html.matchAll(imgTagPattern)]
173
+ if (matches.length === 0) return html
174
+
175
+ let targetIndex = matches.findIndex((match) => {
176
+ const tag = match[0]
177
+ const srcMatch = tag.match(/\ssrc=(["'])(.*?)\1/i) ?? tag.match(/\ssrc=([^\s>]+)/i)
178
+ const src = srcMatch?.[2] ?? srcMatch?.[1] ?? ''
179
+ if (!src) return false
180
+ return src.startsWith(srcKey) || srcKey.startsWith(srcMatchKey(src))
181
+ })
182
+ if (targetIndex < 0) {
183
+ targetIndex = fallbackIndex < matches.length ? fallbackIndex : -1
184
+ }
185
+ if (targetIndex < 0) return html
186
+
187
+ const target = matches[targetIndex]
188
+ const start = target.index ?? 0
189
+ const end = start + target[0].length
190
+ let nextTag = target[0]
191
+ .replace(/\swidth=(["'])[^"']*\1/gi, '')
192
+ .replace(/\sheight=(["'])[^"']*\1/gi, '')
193
+ .replace(/\swidth=[^\s>]+/gi, '')
194
+ .replace(/\sheight=[^\s>]+/gi, '')
195
+ .replace(/\sstyle=(["'])[^"']*\1/gi, '')
196
+ nextTag = nextTag.replace(/\/?>$/, ` width="${width}" height="${height}">`)
197
+
198
+ return html.slice(0, start) + nextTag + html.slice(end)
199
+ }
200
+
154
201
  /** 失焦/保存时把编辑器 DOM 中的图片尺寸写回 HTML(兜底 NodeView attrs 未同步) */
155
202
  export function syncImageDimensions(html: string, root?: DomRoot) {
156
203
  const domRoot = resolveDomRoot(root)
@@ -164,51 +211,26 @@ export function syncImageDimensions(html: string, root?: DomRoot) {
164
211
  const liveImages = Array.from(contentRoot.querySelectorAll('img'))
165
212
  if (liveImages.length === 0) return html
166
213
 
167
- const tempDiv = document.createElement('div')
168
- tempDiv.innerHTML = html
169
- const htmlImages = Array.from(tempDiv.querySelectorAll('img'))
170
- if (htmlImages.length === 0) return html
171
-
214
+ let result = html
172
215
  liveImages.forEach((liveImg, index) => {
173
216
  const width = Math.round(liveImg.offsetWidth)
174
217
  const height = Math.round(liveImg.offsetHeight)
175
218
  if (width <= 1 || height <= 1) return
176
219
 
177
220
  const liveKey = srcMatchKey(liveImg.getAttribute('src') || liveImg.src || '')
178
- let htmlImg =
179
- htmlImages.find((img) => {
180
- const src = img.getAttribute('src') || ''
181
- if (!src || !liveKey) return false
182
- return src.startsWith(liveKey) || liveKey.startsWith(srcMatchKey(src))
183
- }) ?? htmlImages[index]
184
-
185
- if (!htmlImg) return
186
-
187
- htmlImg.setAttribute('width', String(width))
188
- htmlImg.setAttribute('height', String(height))
189
- htmlImg.removeAttribute('style')
221
+ result = upsertImgDimensionsInHtml(result, liveKey, width, height, index)
190
222
  })
191
223
 
192
- return tempDiv.innerHTML
224
+ return result
193
225
  }
194
226
 
195
227
  function sanitizeBrokenImages(html: string) {
196
- if (typeof document === 'undefined') {
197
- return html
198
- .replace(/\ssrc=(["'])(null|undefined)\1/gi, '')
199
- .replace(/\ssrc=(null|undefined)(?=\s|>|\/)/gi, '')
200
- .replace(/\ssrc=(["'])\s*\1/gi, '')
201
- }
202
-
203
- const tempDiv = document.createElement('div')
204
- tempDiv.innerHTML = html
205
- tempDiv.querySelectorAll('img').forEach((img) => {
206
- const src = (img.getAttribute('src') ?? '').trim()
207
- if (!src || src === 'null' || src === 'undefined') {
208
- img.remove()
209
- }
210
- })
211
- return tempDiv.innerHTML
228
+ if (!html) return ''
229
+ // 仅用正则,避免 innerHTML 往返合并文本中的连续空格
230
+ return html
231
+ .replace(/<img\b[^>]*\ssrc=(["'])(null|undefined)\1[^>]*\/?>/gi, '')
232
+ .replace(/<img\b[^>]*\ssrc=(null|undefined)(?=\s|>|\/)[^>]*\/?>/gi, '')
233
+ .replace(/<img\b[^>]*\ssrc=(["'])\s*\1[^>]*\/?>/gi, '')
212
234
  }
213
235
 
214
236
  export function initHtml(html: string) {
@@ -219,6 +241,7 @@ export function initHtml(html: string) {
219
241
  return convertPtToPx(html)
220
242
  }
221
243
 
244
+ /** 导出/存档用:同步图片尺寸并将 px 字号转为 pt;全程正则/DOM 读尺寸,不经 innerHTML 文本往返 */
222
245
  export function finalizeHtml(html: string, root?: DomRoot) {
223
246
  let result = html || ''
224
247
  result = calcImagesHeight(result, root)
@@ -0,0 +1,25 @@
1
+ import type { IWfTaskVo } from './IWfTaskVo'
2
+
3
+ /** 单个节点最后一轮审批信息 */
4
+ export interface IWfNodeLastApprovalVo {
5
+ /** BPMN 节点 id(taskDefKey) */
6
+ nodeCode?: string
7
+ /** 该节点最后一轮审批记录(会签时可能多条) */
8
+ approvalList?: IWfTaskVo[]
9
+ }
10
+
11
+ /** 多节点最后一轮审批查询入参 */
12
+ export interface IWfNodeLastApprovalQueryVo {
13
+ businessId?: string
14
+ nodeCodes?: string[]
15
+ }
16
+
17
+ /** 多节点最后一轮审批查询结果 */
18
+ export interface IWfNodeLastApprovalBatchVo {
19
+ businessId?: string
20
+ procInsId?: string
21
+ procEndTime?: string
22
+ /** 流程是否已结束(仅信息字段,不影响查询) */
23
+ finished?: boolean
24
+ nodeApprovalList?: IWfNodeLastApprovalVo[]
25
+ }
@@ -30,7 +30,7 @@ const request = axios.create({
30
30
  })
31
31
  function setHeaders(config: any) {
32
32
  //数据防止篡改
33
- const Authorization = sessionStorage.getItem('Authorization')
33
+ const Authorization = config.skipAuthorization ? '' : sessionStorage.getItem('Authorization')
34
34
  const signa = 'F2E49299-D0D2-4AA1-87A3-270272EA3D6A'
35
35
  let dataJson: string = ''
36
36
  if (config.method === 'get') {
@@ -56,7 +56,7 @@ function setHeaders(config: any) {
56
56
  // @ts-ignore
57
57
  dataJson=dataJson.replace(/[^\u4E00-\u9FA5A-Za-z0-9]/g, '')
58
58
  dataJson = dataJson.split('').sort().join('').trim()
59
- config.headers.sessionId = sessionStorage.getItem('sessionId')
59
+ config.headers.sessionId = config.skipAuthorization ? '' : sessionStorage.getItem('sessionId')
60
60
  config.headers.Authorization = Authorization
61
61
  config.headers.signa = Md5.hashStr(Authorization + signa + dataJson)
62
62
  config.headers.antiShakeKey = Md5.hashStr(dataJson)