feat: 横向对比改为会员阶梯式排列
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 4s
PR Preview / deploy-preview (pull_request) Successful in 12s
Test / e2e-test (push) Has been cancelled
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 4s
PR Preview / deploy-preview (pull_request) Successful in 12s
Test / e2e-test (push) Has been cancelled
- 列按套装可做配方数从少到多排(小套装左,大套装右) - 行按可用套装数从多到少排(所有套装都能做的在上,独占的在下) - 形成左上到右下的阶梯视觉效果 - 有值格子绿色背景,无值格子灰色,区分更明显 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -74,7 +74,7 @@ export function useKitCost() {
|
||||
.sort((a, b) => a.name.localeCompare(b.name, 'zh'))
|
||||
}
|
||||
|
||||
// Build full analysis for all kits
|
||||
// Build full analysis for all kits, sorted by recipe count ascending (fewest recipes first)
|
||||
const kitAnalysis = computed(() => {
|
||||
return KITS.map(kit => {
|
||||
const perDrop = calcKitPerDrop(kit)
|
||||
@@ -85,12 +85,17 @@ export function useKitCost() {
|
||||
recipes,
|
||||
recipeCount: recipes.length,
|
||||
}
|
||||
})
|
||||
}).sort((a, b) => a.recipeCount - b.recipeCount)
|
||||
})
|
||||
|
||||
// Cross-kit comparison: all recipes that at least one kit can make
|
||||
// Cross-kit comparison: membership-tier style
|
||||
// Columns: kits ordered by recipe count (fewest→most, from kitAnalysis)
|
||||
// Rows: recipes available to most kits at top, exclusive recipes at bottom (staircase pattern)
|
||||
const crossComparison = computed(() => {
|
||||
const analysis = kitAnalysis.value
|
||||
// Kit order for staircase: index in sorted analysis (0 = smallest kit)
|
||||
const kitOrder = analysis.map(ka => ka.id)
|
||||
|
||||
const allRecipeIds = new Set()
|
||||
for (const ka of analysis) {
|
||||
for (const r of ka.recipes) allRecipeIds.add(r._id)
|
||||
@@ -98,16 +103,21 @@ export function useKitCost() {
|
||||
|
||||
const rows = []
|
||||
for (const id of allRecipeIds) {
|
||||
// Find recipe info from any kit that has it
|
||||
let recipe = null
|
||||
const costs = {}
|
||||
for (const ka of analysis) {
|
||||
let availCount = 0
|
||||
// Track which kit columns have this recipe (by index in sorted order)
|
||||
let smallestKitIdx = kitOrder.length
|
||||
for (let i = 0; i < analysis.length; i++) {
|
||||
const ka = analysis[i]
|
||||
const found = ka.recipes.find(r => r._id === id)
|
||||
if (found) {
|
||||
if (!recipe) recipe = found
|
||||
costs[ka.id] = found.kitCost
|
||||
availCount++
|
||||
if (i < smallestKitIdx) smallestKitIdx = i
|
||||
} else {
|
||||
costs[ka.id] = null // kit can't make this recipe
|
||||
costs[ka.id] = null
|
||||
}
|
||||
}
|
||||
rows.push({
|
||||
@@ -116,14 +126,15 @@ export function useKitCost() {
|
||||
tags: recipe.tags,
|
||||
ingredients: recipe.ingredients,
|
||||
originalCost: recipe.originalCost,
|
||||
costs, // { aroma: 12.3, family: null, home3988: 10.8, full: 9.5 }
|
||||
costs,
|
||||
availCount,
|
||||
smallestKitIdx,
|
||||
})
|
||||
}
|
||||
// Sort by number of kits that can make the recipe (fewest first), then by name
|
||||
// Staircase sort: most available first, then by smallest kit that has it, then by name
|
||||
rows.sort((a, b) => {
|
||||
const aCount = Object.values(a.costs).filter(v => v != null).length
|
||||
const bCount = Object.values(b.costs).filter(v => v != null).length
|
||||
if (aCount !== bCount) return aCount - bCount
|
||||
if (a.availCount !== b.availCount) return b.availCount - a.availCount
|
||||
if (a.smallestKitIdx !== b.smallestKitIdx) return a.smallestKitIdx - b.smallestKitIdx
|
||||
return a.name.localeCompare(b.name, 'zh')
|
||||
})
|
||||
return rows
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
<tbody>
|
||||
<tr v-for="row in crossComparison" :key="row.id">
|
||||
<td class="td-name">{{ row.name }}</td>
|
||||
<td v-for="ka in kitAnalysis" :key="ka.id" class="td-kit-cost">
|
||||
<td v-for="ka in kitAnalysis" :key="ka.id" :class="row.costs[ka.id] != null ? 'td-kit-available' : 'td-kit-na'">
|
||||
<template v-if="row.costs[ka.id] != null">{{ fmtPrice(row.costs[ka.id]) }}</template>
|
||||
<template v-else><span class="na">—</span></template>
|
||||
</td>
|
||||
@@ -404,8 +404,9 @@ async function exportExcel(mode) {
|
||||
.td-cost.original { color: #999; font-weight: 400; }
|
||||
.td-profit { font-weight: 600; color: #4a9d7e; }
|
||||
.td-profit.negative { color: #ef5350; }
|
||||
.td-kit-cost { font-weight: 500; }
|
||||
.na { color: #ccc; }
|
||||
.td-kit-available { font-weight: 500; color: #4a9d7e; background: #f0faf5; }
|
||||
.td-kit-na { background: #fafafa; }
|
||||
.na { color: #ddd; }
|
||||
|
||||
.price-input-wrap {
|
||||
display: inline-flex; align-items: center; gap: 2px; font-size: 13px; color: #3e3a44;
|
||||
|
||||
Reference in New Issue
Block a user