Selaa lähdekoodia

feat(web-admin): add apply attachment display name helper

Co-authored-by: Cursor <cursoragent@cursor.com>
wuzilong 1 kuukausi sitten
vanhempi
commit
a564bfe733

+ 63 - 0
web-admin/src/utils/bx/attachment-display-name.test.ts

@@ -0,0 +1,63 @@
+import assert from 'node:assert/strict'
+import { describe, it } from 'node:test'
+import {
+  sanitizeRemarkBaseName,
+  buildApplyAttachmentDisplayName,
+  mapApplyAttachmentDisplayNames
+} from './attachment-display-name'
+
+describe('sanitizeRemarkBaseName', () => {
+  it('trims and replaces illegal chars and spaces', () => {
+    assert.equal(sanitizeRemarkBaseName('  差旅/说明  A  '), '差旅_说明_A')
+  })
+
+  it('truncates to 40 chars', () => {
+    const long = '啊'.repeat(50)
+    assert.equal(sanitizeRemarkBaseName(long).length, 40)
+  })
+
+  it('returns empty for blank', () => {
+    assert.equal(sanitizeRemarkBaseName('   '), '')
+  })
+})
+
+describe('buildApplyAttachmentDisplayName', () => {
+  it('falls back to original when remark empty', () => {
+    assert.equal(
+      buildApplyAttachmentDisplayName({ remark: '', originalFileName: 'a.pdf', index1: 1 }),
+      'a.pdf'
+    )
+  })
+
+  it('uses remark_index + ext', () => {
+    assert.equal(
+      buildApplyAttachmentDisplayName({
+        remark: '差旅说明',
+        originalFileName: 'photo.JPG',
+        index1: 2
+      }),
+      '差旅说明_2.JPG'
+    )
+  })
+
+  it('handles missing extension', () => {
+    assert.equal(
+      buildApplyAttachmentDisplayName({
+        remark: '说明',
+        originalFileName: 'readme',
+        index1: 1
+      }),
+      '说明_1'
+    )
+  })
+})
+
+describe('mapApplyAttachmentDisplayNames', () => {
+  it('maps list with 1-based indices', () => {
+    const out = mapApplyAttachmentDisplayNames('备注', [
+      { fileName: 'a.pdf' },
+      { fileName: 'b.jpg' }
+    ])
+    assert.deepEqual(out, ['备注_1.pdf', '备注_2.jpg'])
+  })
+})

+ 45 - 0
web-admin/src/utils/bx/attachment-display-name.ts

@@ -0,0 +1,45 @@
+const ILLEGAL = /[/\\:*?"<>|\u0000-\u001f]/g
+
+export function sanitizeRemarkBaseName(remark: string): string {
+  const cleaned = String(remark || '')
+    .trim()
+    .replace(ILLEGAL, '_')
+    .replace(/\s+/g, '_')
+    .replace(/_+/g, '_')
+    .replace(/^_|_$/g, '')
+  if (!cleaned) return ''
+  return cleaned.length > 40 ? cleaned.slice(0, 40) : cleaned
+}
+
+function splitExt(fileName: string): { base: string; ext: string } {
+  const name = String(fileName || '')
+  const i = name.lastIndexOf('.')
+  if (i <= 0 || i === name.length - 1) return { base: name, ext: '' }
+  return { base: name.slice(0, i), ext: name.slice(i) }
+}
+
+export function buildApplyAttachmentDisplayName(opts: {
+  remark: string
+  originalFileName: string
+  index1: number
+}): string {
+  const original = String(opts.originalFileName || '').trim() || '申请附件'
+  const base = sanitizeRemarkBaseName(opts.remark)
+  if (!base) return original
+  const { ext } = splitExt(original)
+  const n = Math.max(1, Math.floor(Number(opts.index1) || 1))
+  return `${base}_${n}${ext}`
+}
+
+export function mapApplyAttachmentDisplayNames(
+  remark: string,
+  files: Array<{ fileName?: string | null }>
+): string[] {
+  return (files || []).map((f, i) =>
+    buildApplyAttachmentDisplayName({
+      remark,
+      originalFileName: f.fileName || '',
+      index1: i + 1
+    })
+  )
+}