poi-plugin-inventory-cleaner 1.12.2 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/i18n/en-US.json CHANGED
@@ -23,6 +23,12 @@
23
23
  "stock.verdictDepends": "Depends on fleet",
24
24
  "stock.verdictUnknown": "Not in guide",
25
25
  "stock.materialNote": "Used as material: {{text}}",
26
+ "stock.materialNoteTitle": "Used as material by",
27
+ "stock.consumeImprove": "improvement",
28
+ "stock.consumeQuestScrap": "quest (scrap)",
29
+ "stock.consumeQuestEquip": "quest (equip)",
30
+ "stock.consumeQuestStore": "quest (store)",
31
+ "stock.consumeOther": "other",
26
32
  "stock.keepLabel": "Keep",
27
33
  "stock.keepUnit": "",
28
34
  "stock.keepPlaceholder": "guide",
@@ -31,6 +37,7 @@
31
37
  "stock.keepPlus": "Keep one more",
32
38
  "stock.batchToggle": "Batch keep",
33
39
  "stock.categoryAll": "All categories",
40
+ "stock.backToTop": "Back to top",
34
41
  "stock.categoryTitle": "Filter by in-game equipment type",
35
42
  "stock.sortTitle": "Sort by",
36
43
  "stock.sortVerdict": "Guide verdict",
package/i18n/zh-CN.json CHANGED
@@ -23,6 +23,12 @@
23
23
  "stock.verdictDepends": "看舰队需求",
24
24
  "stock.verdictUnknown": "攻略未收录",
25
25
  "stock.materialNote": "素材用途:{{text}}",
26
+ "stock.materialNoteTitle": "素材用途",
27
+ "stock.consumeImprove": "改修",
28
+ "stock.consumeQuestScrap": "任务·拆",
29
+ "stock.consumeQuestEquip": "任务·装",
30
+ "stock.consumeQuestStore": "任务·库",
31
+ "stock.consumeOther": "其他",
26
32
  "stock.keepLabel": "保留",
27
33
  "stock.keepUnit": "件",
28
34
  "stock.keepPlaceholder": "攻略",
@@ -31,6 +37,7 @@
31
37
  "stock.keepPlus": "多留一件",
32
38
  "stock.batchToggle": "批量保留",
33
39
  "stock.categoryAll": "全部类别",
40
+ "stock.backToTop": "回到顶部",
34
41
  "stock.categoryTitle": "按游戏装备类型筛选",
35
42
  "stock.sortTitle": "排序方式",
36
43
  "stock.sortVerdict": "按攻略判定",
package/index.js CHANGED
@@ -115,6 +115,18 @@ const VIEWS = [
115
115
  { id: 'plan', labelKey: 'stock.filterPlan' },
116
116
  ]
117
117
 
118
+ const CONSUME_LABELS = {
119
+ 锤: 'stock.consumeImprove',
120
+ 拆: 'stock.consumeQuestScrap',
121
+ 装: 'stock.consumeQuestEquip',
122
+ 库: 'stock.consumeQuestStore',
123
+ }
124
+
125
+ function consumeLabel(tag) {
126
+ const key = CONSUME_LABELS[tag]
127
+ return key ? t(key) : t('stock.consumeOther')
128
+ }
129
+
118
130
  const VERDICT = {
119
131
  scrap: { className: 'is-scrap', labelKey: 'stock.verdictScrap' },
120
132
  keepSome: { className: 'is-keepsome', labelKey: 'stock.verdictKeepSome' },
@@ -345,11 +357,23 @@ function StockRow({ row, onKeepChange }) {
345
357
  row.usage
346
358
  ? h('p', { className: 'stock-note', title: row.usage }, row.usage)
347
359
  : null,
348
- row.consumed
360
+ row.consumedItems && row.consumedItems.length
349
361
  ? h(
350
- 'p',
351
- { className: 'stock-consume', title: row.consumed },
352
- t('stock.materialNote', { text: row.consumed }),
362
+ 'div',
363
+ { className: 'stock-consume' },
364
+ h('div', { className: 'stock-consume-title' }, t('stock.materialNoteTitle')),
365
+ h(
366
+ 'ol',
367
+ { className: 'stock-consume-list' },
368
+ row.consumedItems.map((item, index) =>
369
+ h(
370
+ 'li',
371
+ { key: index, className: 'is-' + item.kind },
372
+ h('span', { className: 'stock-consume-tag' }, consumeLabel(item.tag)),
373
+ h('span', { className: 'stock-consume-text' }, item.text),
374
+ ),
375
+ ),
376
+ ),
353
377
  )
354
378
  : null,
355
379
  )
@@ -403,6 +427,17 @@ function App() {
403
427
 
404
428
  const [batchOpen, setBatchOpen] = React.useState(false)
405
429
  const [batchValues, setBatchValues] = React.useState({})
430
+ const [showTop, setShowTop] = React.useState(false)
431
+ const rootRef = React.useRef(null)
432
+
433
+ const handleScroll = React.useCallback((event) => {
434
+ setShowTop(event.currentTarget.scrollTop > 400)
435
+ }, [])
436
+
437
+ const scrollToTop = React.useCallback(() => {
438
+ const element = rootRef.current
439
+ if (element) element.scrollTo({ top: 0, behavior: 'smooth' })
440
+ }, [])
406
441
 
407
442
  const firstKeepSave = React.useRef(true)
408
443
  React.useEffect(() => {
@@ -477,7 +512,7 @@ function App() {
477
512
 
478
513
  return h(
479
514
  'div',
480
- { className: 'stock-root' },
515
+ { className: 'stock-root', ref: rootRef, onScroll: handleScroll },
481
516
  h('style', null, CSS),
482
517
  h(
483
518
  'header',
@@ -658,7 +693,18 @@ function App() {
658
693
  ),
659
694
  h('p', { className: 'stock-warn' }, t('stock.warn')),
660
695
  h('p', { className: 'stock-source' }, t('stock.source')),
661
-
696
+ showTop
697
+ ? h(
698
+ 'button',
699
+ {
700
+ type: 'button',
701
+ className: 'stock-top',
702
+ title: t('stock.backToTop'),
703
+ onClick: scrollToTop,
704
+ },
705
+ '↑',
706
+ )
707
+ : null,
662
708
  )
663
709
  }
664
710
 
package/lib/inventory.js CHANGED
@@ -26,6 +26,39 @@ function toNumber(value, fallback = 0) {
26
26
  return Number.isFinite(number) ? number : fallback
27
27
  }
28
28
 
29
+ const CONSUME_KINDS = {
30
+ 锤: 'improve',
31
+ 拆: 'quest',
32
+ 装: 'quest',
33
+ 库: 'quest',
34
+ }
35
+
36
+ /**
37
+ * 把「《锤》xxx《拆》yyy」这种素材用途串拆成条目,任务类排在改修类前面。
38
+ */
39
+ function parseConsumed(text) {
40
+ const value = String(text || '').trim()
41
+ if (!value) return []
42
+
43
+ const parts = value
44
+ .split(/(?=《)/)
45
+ .map((part) => part.trim())
46
+ .filter(Boolean)
47
+
48
+ const items = parts.map((raw) => {
49
+ const matched = raw.match(/^《([^》]{1,3})》\s*(.*)$/)
50
+ const tag = matched ? matched[1] : ''
51
+ const detail = matched ? matched[2] : raw
52
+ return { tag, kind: CONSUME_KINDS[tag] || 'other', text: detail }
53
+ })
54
+
55
+ const rank = { quest: 0, improve: 1, other: 2 }
56
+ return items
57
+ .map((item, index) => ({ item, index }))
58
+ .sort((a, b) => rank[a.item.kind] - rank[b.item.kind] || a.index - b.index)
59
+ .map(({ item }) => item)
60
+ }
61
+
29
62
  function equipName(equipId) {
30
63
  const pair = INDEX[String(equipId)] || []
31
64
  return { jp: pair[0] || '', cn: pair[1] || '' }
@@ -118,6 +151,7 @@ function buildInventory(state, options = {}) {
118
151
  usage: rule ? rule.usage : '',
119
152
  obtain: rule ? rule.obtain : '',
120
153
  consumed,
154
+ consumedItems: parseConsumed(consumed),
121
155
  stage: guide ? guide.stage : '',
122
156
  note: guide ? guide.note : '',
123
157
  inPlan,
@@ -249,6 +283,7 @@ function filterRows(rows, options = {}) {
249
283
 
250
284
  module.exports = {
251
285
  OTHER_CATEGORY,
286
+ parseConsumed,
252
287
  SORTS,
253
288
  sortRows,
254
289
  applyCategoryKeep,
package/lib/style.js CHANGED
@@ -373,25 +373,75 @@ const CSS = `
373
373
  .stock-note {
374
374
  margin: 6px 0 0;
375
375
  font-size: 11px;
376
- line-height: 1.55;
377
- opacity: 0.65;
378
- overflow: hidden;
379
- text-overflow: ellipsis;
380
- display: -webkit-box;
381
- -webkit-line-clamp: 3;
382
- -webkit-box-orient: vertical;
376
+ line-height: 1.6;
377
+ opacity: 0.7;
378
+ white-space: normal;
379
+ overflow-wrap: anywhere;
380
+ word-break: break-word;
383
381
  }
384
382
 
385
383
  .stock-consume {
386
- margin: 4px 0 0;
384
+ margin: 6px 0 0;
385
+ font-size: 10.5px;
386
+ line-height: 1.55;
387
+ opacity: 0.55;
388
+ }
389
+
390
+ .stock-consume-title {
391
+ margin-bottom: 2px;
387
392
  font-size: 10px;
388
- line-height: 1.5;
393
+ opacity: 0.8;
394
+ }
395
+
396
+ .stock-consume-list {
397
+ margin: 0;
398
+ padding: 0;
399
+ list-style: none;
400
+ display: grid;
401
+ gap: 2px;
402
+ counter-reset: consume;
403
+ }
404
+
405
+ .stock-consume-list li {
406
+ display: flex;
407
+ align-items: baseline;
408
+ gap: 6px;
409
+ counter-increment: consume;
410
+ }
411
+
412
+ .stock-consume-list li::before {
413
+ content: counter(consume) '.';
414
+ flex: none;
415
+ min-width: 14px;
416
+ text-align: right;
389
417
  opacity: 0.45;
390
- overflow: hidden;
391
- text-overflow: ellipsis;
392
- display: -webkit-box;
393
- -webkit-line-clamp: 1;
394
- -webkit-box-orient: vertical;
418
+ font-variant-numeric: tabular-nums;
419
+ }
420
+
421
+ .stock-consume-tag {
422
+ flex: none;
423
+ padding: 0 5px;
424
+ border-radius: 4px;
425
+ background: var(--stock-surface-2);
426
+ font-size: 9px;
427
+ white-space: nowrap;
428
+ }
429
+
430
+ .stock-consume-list li.is-quest .stock-consume-tag {
431
+ color: var(--stock-amber);
432
+ background: rgba(245, 158, 11, 0.16);
433
+ }
434
+
435
+ .stock-consume-list li.is-improve .stock-consume-tag {
436
+ color: var(--stock-cyan);
437
+ background: rgba(6, 182, 212, 0.14);
438
+ }
439
+
440
+ .stock-consume-text {
441
+ flex: 1 1 auto;
442
+ min-width: 0;
443
+ overflow-wrap: anywhere;
444
+ word-break: break-word;
395
445
  }
396
446
 
397
447
  .stock-batchbar {
@@ -645,6 +695,53 @@ const CSS = `
645
695
  opacity: 0.42;
646
696
  }
647
697
 
698
+ .stock-root::-webkit-scrollbar {
699
+ width: 12px;
700
+ height: 12px;
701
+ }
702
+
703
+ .stock-root::-webkit-scrollbar-track {
704
+ background: rgba(255, 255, 255, 0.06);
705
+ border-radius: 6px;
706
+ }
707
+
708
+ .stock-root::-webkit-scrollbar-thumb {
709
+ background: rgba(170, 180, 195, 0.6);
710
+ border: 2px solid transparent;
711
+ border-radius: 6px;
712
+ background-clip: padding-box;
713
+ }
714
+
715
+ .stock-root::-webkit-scrollbar-thumb:hover {
716
+ background: rgba(205, 215, 230, 0.8);
717
+ border: 2px solid transparent;
718
+ background-clip: padding-box;
719
+ }
720
+
721
+ .stock-top {
722
+ position: fixed;
723
+ right: 22px;
724
+ bottom: 22px;
725
+ z-index: 70;
726
+ width: 42px;
727
+ height: 42px;
728
+ padding: 0;
729
+ border: 1px solid rgba(150, 160, 175, 0.55);
730
+ border-radius: 50%;
731
+ color: #e8edf4;
732
+ background: rgba(38, 44, 54, 0.94);
733
+ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
734
+ font-family: inherit;
735
+ font-size: 18px;
736
+ line-height: 1;
737
+ cursor: pointer;
738
+ }
739
+
740
+ .stock-top:hover {
741
+ border-color: #818cf8;
742
+ color: #818cf8;
743
+ }
744
+
648
745
  `
649
746
 
650
747
  module.exports = { CSS }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poi-plugin-inventory-cleaner",
3
- "version": "1.12.2",
3
+ "version": "1.14.0",
4
4
  "description": "库存清理大师:对照改修攻略与保留上限,找出囤积过量、可以清理的装备,并标出不能拆的改修材料。",
5
5
  "main": "index.js",
6
6
  "files": [