refactor(品牌工具页): 抽取 formatDateTime 与 uploadPathsToJava 公共工具

- 新增 shared/utils/datetime.ts:13 个品牌页逐字重复的 formatDateTime 收敛为一处;
  语义不同的 3 个变体(toLocaleString / 字符串切片 / 支持时间戳)保留不动
- 新增 shared/utils/upload-to-java.ts:10 个品牌页的上传循环收敛,api 依赖注入便于单测;
  保留 uploadOss(品牌Tab)与 returnEmptyWhenUnavailable(跟价)两处行为差异
- 补 datetime / upload-to-java 单测 10 例

净减约 327 行;vue-tsc 构建与 690 个前端单测全通过
This commit is contained in:
2026-09-13 23:16:59 +08:00
parent b70557a077
commit 882ccdac12
18 changed files with 210 additions and 377 deletions
@@ -125,7 +125,8 @@ import { getTaskPollIntervalMs } from '@/shared/task-progress-config'
import { createCategorizedTimers } from '@/shared/utils/categorized-timers'
import type { UploadFileVo } from '@/shared/api/upload.ts'
import type { UploadedFileRef } from '@/shared/api/types/upload.ts'
import type { BrandExpandFolderItem } from '@/shared/api/types/modules/brand'
import { formatDateTime } from '@/shared/utils/datetime'
import { uploadPathsToJava } from '@/shared/utils/upload-to-java'
const uploadedFiles = ref<UploadFileVo[]>([])
const strategy = ref<'Terms' | 'Simple'>('Simple')
@@ -342,38 +343,7 @@ function toBrandTaskView(item: BrandTaskItem): TaskItemView {
}
}
function formatDateTime(value?: string) {
if (!value) return '-'
const date = new Date(value)
if (Number.isNaN(date.getTime())) return value
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
/** 上传本地 xlsx 到 Java 临时目录,成功后回填 fileUrl(服务器本地路径,Java 直接读取) */
async function uploadBrandPathsToJava(paths: Array<string | BrandExpandFolderItem>) {
const api = getPywebviewApi()
if (!api?.upload_file_to_java) {
throw new Error('当前环境未提供文件上传能力')
}
const files: UploadFileVo[] = []
for (const item of paths) {
const filePath = typeof item === 'string' ? item : item.absolutePath
const relativePath = typeof item === 'string' ? undefined : item.relativePath
const uploaded = await api.upload_file_to_java(filePath, relativePath, true)
if (!uploaded?.success || !uploaded.data) {
throw new Error(uploaded?.error || uploaded?.message || `上传失败:${filePath}`)
}
files.push(uploaded.data)
}
return files
}
async function selectFiles() {
const bridge = getPywebviewApi()
if (!bridge?.select_brand_xlsx_files) {
@@ -384,7 +354,7 @@ async function selectFiles() {
if (!paths?.length) return
if (!(await passGuard(checkSelectedFiles(paths, { allowedExtensions: EXCEL_EXTENSIONS })))) return
try {
const files = await uploadBrandPathsToJava(paths)
const files = await uploadPathsToJava(getPywebviewApi(), paths, { uploadOss: true })
uploadedFiles.value = files
ElMessage.success(`已选择并上传 ${files.length} 个 Excel 文件`)
} catch (error) {
@@ -412,7 +382,7 @@ async function selectFolder() {
return
}
if (!(await passGuard(checkSelectedFiles(res.items.map((i) => i.absolutePath), { allowedExtensions: EXCEL_EXTENSIONS })))) return
const files = await uploadBrandPathsToJava(res.items)
const files = await uploadPathsToJava(getPywebviewApi(), res.items, { uploadOss: true })
uploadedFiles.value = files
ElMessage.success(`已选择并上传文件夹内 ${files.length} 个 Excel 文件`)
} catch (error) {