feat: 导出Excel多sheet,按标签分页
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Successful in 5s
Test / e2e-test (push) Failing after 56s
PR Preview / deploy-preview (pull_request) Successful in 1m4s
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Successful in 5s
Test / e2e-test (push) Failing after 56s
PR Preview / deploy-preview (pull_request) Successful in 1m4s
- 文件名:精油配方YYYY-MM-DD.xlsx - 第一个sheet"全部"包含所有配方 - 每个标签一个单独的sheet - 使用SheetJS生成真正的xlsx格式 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1109,25 +1109,36 @@ async function rejectRecipe(recipe) {
|
||||
}
|
||||
}
|
||||
|
||||
function exportExcel() {
|
||||
async function exportExcel() {
|
||||
const recipes = recipeStore.recipes
|
||||
if (!recipes.length) { ui.showToast('没有配方可导出'); return }
|
||||
// BOM for UTF-8 Excel compatibility
|
||||
let csv = '\uFEFF配方名称,标签,精油成分,滴数,成本\n'
|
||||
for (const r of recipes) {
|
||||
const tags = (r.tags || []).join('/')
|
||||
const ings = r.ingredients.map(i => i.oil).join('、')
|
||||
const drops = r.ingredients.map(i => `${i.oil}${i.drops}滴`).join('、')
|
||||
const cost = oils.fmtPrice(oils.calcCost(r.ingredients))
|
||||
csv += `"${r.name}","${tags}","${ings}","${drops}","${cost}"\n`
|
||||
const XLSX = (await import('xlsx')).default || await import('xlsx')
|
||||
|
||||
function recipesToRows(list) {
|
||||
return list.map(r => ({
|
||||
'配方名称': r.name,
|
||||
'标签': (r.tags || []).join('/'),
|
||||
'精油成分': r.ingredients.map(i => `${i.oil}${i.drops}滴`).join('、'),
|
||||
'成本': oils.fmtPrice(oils.calcCost(r.ingredients)),
|
||||
'备注': r.note || '',
|
||||
}))
|
||||
}
|
||||
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = '配方导出.csv'
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
|
||||
const wb = XLSX.utils.book_new()
|
||||
// Sheet 1: 全部
|
||||
XLSX.utils.book_append_sheet(wb, XLSX.utils.json_to_sheet(recipesToRows(recipes)), '全部')
|
||||
// Per tag sheets
|
||||
const allTags = [...new Set(recipes.flatMap(r => r.tags || []))].sort((a, b) => a.localeCompare(b, 'zh'))
|
||||
for (const tag of allTags) {
|
||||
const tagged = recipes.filter(r => r.tags && r.tags.includes(tag))
|
||||
if (tagged.length) {
|
||||
const name = tag.substring(0, 31) // Excel sheet name max 31 chars
|
||||
XLSX.utils.book_append_sheet(wb, XLSX.utils.json_to_sheet(recipesToRows(tagged)), name)
|
||||
}
|
||||
}
|
||||
|
||||
const today = new Date().toISOString().slice(0, 10)
|
||||
XLSX.writeFile(wb, `精油配方${today}.xlsx`)
|
||||
ui.showToast('导出成功')
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user