feat(worker-platform): 接单模板列表支持一键导出到本地 CSV
后台接单平台「接单模板列表」右上角新增「导出」按钮: - 按当前筛选(搜索关键词 + 一级/二级分类)导出全部模板,服务端分页的 情况按每页 100 条循环拉全量(页数上限兜底),不会只导出当前页; - 导出 UTF-8 带 BOM 的 CSV,Excel/WPS 双击直接打开,文件名带时间戳 (接单模板_YYYYMMDD_HHmm.csv);逗号/引号/换行按 CSV 规范转义; - 22 列:模板名称/标识/分类/系统/平台/商品SKU/接单金额/按件价/拼单配置/ 验收模式/自动建单/状态/超时策略/资料字段/已绑定商品与绑定明细/时间等; - 空结果、超出上限、浏览器不支持下载分别给出明确提示。 导出逻辑集中在 apps/frontend/src/utils/product-rules-export.ts(纯函数, 无 @/ 别名与运行时相对导入,便于 node --experimental-strip-types 单测), 新增 tests/product-rules-export.test.ts 覆盖分类回退、金额与拼单转换、 绑定明细、CSV 转义、文件名、空列表与非浏览器环境。
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
DeleteOutlined,
|
||||
DownloadOutlined,
|
||||
EditOutlined,
|
||||
FolderOpenOutlined,
|
||||
FormOutlined,
|
||||
@@ -50,9 +51,18 @@ import type {
|
||||
} from '@/types/worker-platform'
|
||||
import type { AdminKuaishouIndustryShopOption } from '@/types/admin'
|
||||
import { ADMIN_DEFAULT_PAGE_SIZE, buildAdminTablePagination } from '@/utils/admin-pagination'
|
||||
import {
|
||||
buildProductRuleExportRows,
|
||||
buildProductRulesExportFilename,
|
||||
downloadProductRulesCsv,
|
||||
} from '@/utils/product-rules-export'
|
||||
import { formatMoney } from './shared'
|
||||
import { WorkProductBindingForm, type SourcePrefill } from './WorkProductBindingForm'
|
||||
|
||||
/** 导出是一次性拉全量,单页取后端上限 100;页数上限兜底,防止异常数据下无限翻页。 */
|
||||
const PRODUCT_RULES_EXPORT_PAGE_SIZE = 100
|
||||
const PRODUCT_RULES_EXPORT_MAX_PAGES = 200
|
||||
|
||||
export default function ProductRulesPanel() {
|
||||
const { message } = App.useApp()
|
||||
const queryClient = useQueryClient()
|
||||
@@ -63,6 +73,7 @@ export default function ProductRulesPanel() {
|
||||
|
||||
const [editingRule, setEditingRule] = useState<WorkProductRule | null>(null)
|
||||
const [syncingPrice, setSyncingPrice] = useState(false)
|
||||
const [exportingRules, setExportingRules] = useState(false)
|
||||
const [activeMappingId, setActiveMappingId] = useState<number | 'new' | null>(null)
|
||||
const [sourcePrefill, setSourcePrefill] = useState<SourcePrefill | null>(null)
|
||||
|
||||
@@ -526,6 +537,59 @@ export default function ProductRulesPanel() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出当前筛选(关键词 + 分类)下的全部接单模板到本地 CSV。
|
||||
* 列表是服务端分页的,所以这里按页循环拉全量,避免「只导出当前页」。
|
||||
*/
|
||||
async function exportProductRules() {
|
||||
setExportingRules(true)
|
||||
try {
|
||||
const collected: WorkProductRule[] = []
|
||||
let total = 0
|
||||
let truncated = false
|
||||
for (let nextPage = 1; nextPage <= PRODUCT_RULES_EXPORT_MAX_PAGES; nextPage += 1) {
|
||||
const response = await fetchAdminWorkProductRules({
|
||||
keyword,
|
||||
categoryId,
|
||||
page: nextPage,
|
||||
pageSize: PRODUCT_RULES_EXPORT_PAGE_SIZE,
|
||||
})
|
||||
const items = response.data?.items || []
|
||||
total = response.data?.pagination?.total ?? total
|
||||
collected.push(...items)
|
||||
if (items.length < PRODUCT_RULES_EXPORT_PAGE_SIZE || collected.length >= total) {
|
||||
break
|
||||
}
|
||||
if (nextPage === PRODUCT_RULES_EXPORT_MAX_PAGES) {
|
||||
truncated = true
|
||||
}
|
||||
}
|
||||
|
||||
if (collected.length === 0) {
|
||||
message.warning('当前筛选条件下没有可导出的接单模板')
|
||||
return
|
||||
}
|
||||
|
||||
const rows = buildProductRuleExportRows(collected, mappingsByRuleId, categoryMap)
|
||||
const filename = buildProductRulesExportFilename()
|
||||
if (!downloadProductRulesCsv(rows, filename)) {
|
||||
message.error('当前浏览器环境不支持本地文件下载')
|
||||
return
|
||||
}
|
||||
if (truncated) {
|
||||
message.warning(
|
||||
`共 ${total} 条接单模板,本次已导出前 ${rows.length} 条,请缩小筛选范围后再导出剩余部分`,
|
||||
)
|
||||
return
|
||||
}
|
||||
message.success(`已导出 ${rows.length} 条接单模板到本地:${filename}`)
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '导出接单模板失败')
|
||||
} finally {
|
||||
setExportingRules(false)
|
||||
}
|
||||
}
|
||||
|
||||
function syncSharingRuleForm(next: {
|
||||
sharingTotalQuantity?: number
|
||||
sharingUnitReward?: number
|
||||
@@ -1190,6 +1254,15 @@ export default function ProductRulesPanel() {
|
||||
<Button size="middle" onClick={reprocessKuaishouOrders}>
|
||||
重匹配
|
||||
</Button>
|
||||
<Button
|
||||
size="middle"
|
||||
icon={<DownloadOutlined />}
|
||||
loading={exportingRules}
|
||||
onClick={exportProductRules}
|
||||
title="按当前筛选条件导出全部接单模板到本地 CSV"
|
||||
>
|
||||
导出
|
||||
</Button>
|
||||
<Button type="primary" size="middle" icon={<PlusOutlined />} onClick={resetRuleForm}>
|
||||
新建
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user