poi-plugin-koushu-rate 2.0.12 → 2.0.13
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/index.js +670 -48
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -17,8 +17,8 @@ const LEVEL_TWO_ROWS = [
|
|
|
17
17
|
{ range: "★6→7", label: "90%", p: 0.90, source: "phase1" },
|
|
18
18
|
{ range: "★7→8", label: "82%", p: 0.82, source: "phase1" },
|
|
19
19
|
{ range: "★8→9", label: "77%", p: 0.77, source: "phase1" },
|
|
20
|
-
{ range: "★9→
|
|
21
|
-
{ range: "
|
|
20
|
+
{ range: "★9→max", label: "67%", p: 0.67, source: "phase1" },
|
|
21
|
+
{ range: "max→进化", label: "62%", p: 0.62, source: "upgrade" },
|
|
22
22
|
];
|
|
23
23
|
|
|
24
24
|
const PLAN_LEVELS_6 = [
|
|
@@ -160,10 +160,10 @@ const CSS = `
|
|
|
160
160
|
}
|
|
161
161
|
.kr2-title-row {
|
|
162
162
|
display: flex;
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
flex-direction: column;
|
|
164
|
+
align-items: stretch;
|
|
165
|
+
justify-content: flex-start;
|
|
165
166
|
gap: 12px;
|
|
166
|
-
flex-wrap: wrap;
|
|
167
167
|
}
|
|
168
168
|
.kr2-title {
|
|
169
169
|
font-size: 18px;
|
|
@@ -202,7 +202,7 @@ const CSS = `
|
|
|
202
202
|
display: flex;
|
|
203
203
|
gap: 6px;
|
|
204
204
|
flex-wrap: wrap;
|
|
205
|
-
margin-top:
|
|
205
|
+
margin-top: 12px;
|
|
206
206
|
}
|
|
207
207
|
.kr2-day {
|
|
208
208
|
padding: 5px 12px;
|
|
@@ -224,10 +224,10 @@ const CSS = `
|
|
|
224
224
|
.kr2-nav {
|
|
225
225
|
display: flex;
|
|
226
226
|
gap: 6px;
|
|
227
|
-
margin
|
|
228
|
-
margin-bottom: 20px;
|
|
227
|
+
margin: 0;
|
|
229
228
|
}
|
|
230
229
|
.kr2-nav-btn {
|
|
230
|
+
min-width: 110px;
|
|
231
231
|
padding: 7px 18px;
|
|
232
232
|
border: 1px solid #5f6b7c;
|
|
233
233
|
border-radius: 6px;
|
|
@@ -235,6 +235,7 @@ const CSS = `
|
|
|
235
235
|
color: #f6f7f9;
|
|
236
236
|
cursor: pointer;
|
|
237
237
|
font-size: 13px;
|
|
238
|
+
text-align: center;
|
|
238
239
|
}
|
|
239
240
|
.kr2-nav-btn:hover {
|
|
240
241
|
background: #383e47;
|
|
@@ -333,6 +334,40 @@ const CSS = `
|
|
|
333
334
|
.kr2-plan-table tbody tr:last-child td {
|
|
334
335
|
border-bottom: 0;
|
|
335
336
|
}
|
|
337
|
+
.kr2-plan-main-table {
|
|
338
|
+
table-layout: fixed;
|
|
339
|
+
width: 100%;
|
|
340
|
+
}
|
|
341
|
+
.kr2-plan-main-table th,
|
|
342
|
+
.kr2-plan-main-table td {
|
|
343
|
+
vertical-align: middle;
|
|
344
|
+
}
|
|
345
|
+
.kr2-plan-main-table th:nth-child(1),
|
|
346
|
+
.kr2-plan-main-table td:nth-child(1) { width: 40px; }
|
|
347
|
+
.kr2-plan-main-table th:nth-child(2),
|
|
348
|
+
.kr2-plan-main-table td:nth-child(2) { width: 170px; }
|
|
349
|
+
.kr2-plan-main-table th:nth-child(3),
|
|
350
|
+
.kr2-plan-main-table td:nth-child(3) { width: 90px; }
|
|
351
|
+
.kr2-plan-main-table th:nth-child(4),
|
|
352
|
+
.kr2-plan-main-table td:nth-child(4) { width: 190px; }
|
|
353
|
+
.kr2-plan-main-table th:nth-child(5),
|
|
354
|
+
.kr2-plan-main-table td:nth-child(5) { width: 105px; }
|
|
355
|
+
.kr2-plan-main-table th:nth-child(6),
|
|
356
|
+
.kr2-plan-main-table td:nth-child(6) { width: 90px; }
|
|
357
|
+
.kr2-plan-main-table th:nth-child(7),
|
|
358
|
+
.kr2-plan-main-table td:nth-child(7) { width: 90px; }
|
|
359
|
+
.kr2-plan-main-table td.kr2-plan-mat-col {
|
|
360
|
+
white-space: normal;
|
|
361
|
+
word-break: break-word;
|
|
362
|
+
}
|
|
363
|
+
.kr2-plan-target-group {
|
|
364
|
+
display: inline-flex;
|
|
365
|
+
align-items: center;
|
|
366
|
+
justify-content: center;
|
|
367
|
+
gap: 4px;
|
|
368
|
+
flex-wrap: wrap;
|
|
369
|
+
width: 100%;
|
|
370
|
+
}
|
|
336
371
|
.kr2-plan-current {
|
|
337
372
|
font-size: 12px;
|
|
338
373
|
}
|
|
@@ -368,7 +403,17 @@ const CSS = `
|
|
|
368
403
|
.kr2-plan-table .kr2-plan-name-inner {
|
|
369
404
|
display: flex;
|
|
370
405
|
align-items: center;
|
|
371
|
-
|
|
406
|
+
flex-wrap: wrap;
|
|
407
|
+
gap: 4px 8px;
|
|
408
|
+
}
|
|
409
|
+
.kr2-plan-evo-target-line {
|
|
410
|
+
color: #4fc3f7;
|
|
411
|
+
font-weight: 700;
|
|
412
|
+
white-space: normal;
|
|
413
|
+
word-break: break-word;
|
|
414
|
+
}
|
|
415
|
+
.kr2-plan-evo-target-name {
|
|
416
|
+
color: #4fc3f7;
|
|
372
417
|
}
|
|
373
418
|
.kr2-plan-table .kr2-icon {
|
|
374
419
|
width: 24px;
|
|
@@ -443,6 +488,212 @@ const CSS = `
|
|
|
443
488
|
color: #d6dce3;
|
|
444
489
|
margin-bottom: 8px;
|
|
445
490
|
}
|
|
491
|
+
.kr2-plan-target-btn {
|
|
492
|
+
min-width: 56px;
|
|
493
|
+
height: 24px;
|
|
494
|
+
padding: 0 8px;
|
|
495
|
+
border: 1px solid #5f6b7c;
|
|
496
|
+
border-radius: 4px;
|
|
497
|
+
background: #2f343c;
|
|
498
|
+
color: #f6f7f9;
|
|
499
|
+
font-size: 12px;
|
|
500
|
+
text-align: center;
|
|
501
|
+
cursor: pointer;
|
|
502
|
+
}
|
|
503
|
+
.kr2-plan-target-btn.kr2-plan-target-active {
|
|
504
|
+
background: #2d72d2;
|
|
505
|
+
border-color: #2d72d2;
|
|
506
|
+
color: #fff;
|
|
507
|
+
}
|
|
508
|
+
.kr2-level-max-blue {
|
|
509
|
+
color: #4fc3f7;
|
|
510
|
+
font-weight: 700;
|
|
511
|
+
}
|
|
512
|
+
.kr2-plan-evo-wrap {
|
|
513
|
+
display: inline-block;
|
|
514
|
+
vertical-align: middle;
|
|
515
|
+
}
|
|
516
|
+
.kr2-plan-evo-btn {
|
|
517
|
+
min-width: 56px;
|
|
518
|
+
height: 24px;
|
|
519
|
+
padding: 0 8px;
|
|
520
|
+
border: 1px solid #5f6b7c;
|
|
521
|
+
border-radius: 4px;
|
|
522
|
+
background: #2f343c;
|
|
523
|
+
color: #f6f7f9;
|
|
524
|
+
font-size: 12px;
|
|
525
|
+
text-align: center;
|
|
526
|
+
white-space: nowrap;
|
|
527
|
+
cursor: pointer;
|
|
528
|
+
}
|
|
529
|
+
.kr2-plan-evo-btn:disabled {
|
|
530
|
+
opacity: 0.4;
|
|
531
|
+
cursor: not-allowed;
|
|
532
|
+
}
|
|
533
|
+
.kr2-plan-evo-btn.kr2-plan-evo-active {
|
|
534
|
+
background: #2d72d2;
|
|
535
|
+
border-color: #2d72d2;
|
|
536
|
+
color: #fff;
|
|
537
|
+
}
|
|
538
|
+
.kr2-evo-modal {
|
|
539
|
+
width: 420px;
|
|
540
|
+
max-width: 100%;
|
|
541
|
+
}
|
|
542
|
+
.kr2-evo-scroll {
|
|
543
|
+
max-height: 280px;
|
|
544
|
+
overflow-y: auto;
|
|
545
|
+
display: flex;
|
|
546
|
+
flex-direction: column;
|
|
547
|
+
gap: 6px;
|
|
548
|
+
padding: 12px;
|
|
549
|
+
}
|
|
550
|
+
.kr2-evo-option {
|
|
551
|
+
padding: 8px 10px;
|
|
552
|
+
border: 1px solid #5f6b7c;
|
|
553
|
+
border-radius: 4px;
|
|
554
|
+
background: #2f343c;
|
|
555
|
+
color: #f6f7f9;
|
|
556
|
+
text-align: left;
|
|
557
|
+
font-size: 13px;
|
|
558
|
+
cursor: pointer;
|
|
559
|
+
}
|
|
560
|
+
.kr2-evo-option:hover {
|
|
561
|
+
background: #383e47;
|
|
562
|
+
}
|
|
563
|
+
.kr2-evo-option.kr2-evo-option-active {
|
|
564
|
+
background: #1d3048;
|
|
565
|
+
border-color: #4f9dcc;
|
|
566
|
+
color: #d6e4f5;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
.kr2-strong {
|
|
570
|
+
margin-top: 12px;
|
|
571
|
+
flex: 1;
|
|
572
|
+
min-height: 60vh;
|
|
573
|
+
overflow-x: hidden;
|
|
574
|
+
overflow-y: auto;
|
|
575
|
+
}
|
|
576
|
+
.kr2-strong-table {
|
|
577
|
+
border-collapse: separate;
|
|
578
|
+
border-spacing: 0;
|
|
579
|
+
}
|
|
580
|
+
.kr2-strong-cat-th {
|
|
581
|
+
position: relative;
|
|
582
|
+
cursor: pointer;
|
|
583
|
+
user-select: none;
|
|
584
|
+
}
|
|
585
|
+
.kr2-strong-cat-title {
|
|
586
|
+
margin-right: 4px;
|
|
587
|
+
}
|
|
588
|
+
.kr2-strong-cat-arrow {
|
|
589
|
+
color: #abb3bf;
|
|
590
|
+
font-size: 11px;
|
|
591
|
+
}
|
|
592
|
+
.kr2-strong-cat-menu {
|
|
593
|
+
position: absolute;
|
|
594
|
+
top: calc(100% + 4px);
|
|
595
|
+
left: 0;
|
|
596
|
+
z-index: 40;
|
|
597
|
+
min-width: 180px;
|
|
598
|
+
background: #252a31;
|
|
599
|
+
border: 1px solid #5f6b7c;
|
|
600
|
+
border-radius: 6px;
|
|
601
|
+
padding: 6px;
|
|
602
|
+
display: flex;
|
|
603
|
+
flex-direction: column;
|
|
604
|
+
gap: 4px;
|
|
605
|
+
}
|
|
606
|
+
.kr2-strong-cat-option {
|
|
607
|
+
display: flex;
|
|
608
|
+
align-items: center;
|
|
609
|
+
gap: 6px;
|
|
610
|
+
color: #f6f7f9;
|
|
611
|
+
font-size: 12px;
|
|
612
|
+
white-space: nowrap;
|
|
613
|
+
cursor: pointer;
|
|
614
|
+
}
|
|
615
|
+
.kr2-strong-cat-option input {
|
|
616
|
+
margin: 0;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
.kr2-strong-cat {
|
|
620
|
+
white-space: nowrap;
|
|
621
|
+
}
|
|
622
|
+
.kr2-strong-table th,
|
|
623
|
+
.kr2-strong-table td {
|
|
624
|
+
text-align: center;
|
|
625
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.12);
|
|
626
|
+
}
|
|
627
|
+
.kr2-strong-table tbody tr:last-child td {
|
|
628
|
+
border-bottom: 0;
|
|
629
|
+
}
|
|
630
|
+
.kr2-strong-equip {
|
|
631
|
+
text-align: left !important;
|
|
632
|
+
white-space: normal;
|
|
633
|
+
}
|
|
634
|
+
.kr2-strong-level {
|
|
635
|
+
display: inline-flex;
|
|
636
|
+
align-items: center;
|
|
637
|
+
justify-content: center;
|
|
638
|
+
vertical-align: middle;
|
|
639
|
+
min-width: 30px;
|
|
640
|
+
height: 20px;
|
|
641
|
+
color: #4fc3f7;
|
|
642
|
+
font-weight: 700;
|
|
643
|
+
}
|
|
644
|
+
.kr2-strong-target {
|
|
645
|
+
color: #ffffff;
|
|
646
|
+
font-weight: 700;
|
|
647
|
+
}
|
|
648
|
+
.kr2-strong-stock {
|
|
649
|
+
white-space: normal;
|
|
650
|
+
}
|
|
651
|
+
.kr2-strong-stock-name {
|
|
652
|
+
color: #ffffff;
|
|
653
|
+
font-weight: 700;
|
|
654
|
+
}
|
|
655
|
+
.kr2-strong-stock-ok {
|
|
656
|
+
color: #f6f7f9;
|
|
657
|
+
}
|
|
658
|
+
.kr2-strong-stock-short {
|
|
659
|
+
color: #ff6b6b;
|
|
660
|
+
font-weight: 700;
|
|
661
|
+
}
|
|
662
|
+
.kr2-strong-stock-missing {
|
|
663
|
+
color: #abb3bf;
|
|
664
|
+
}
|
|
665
|
+
.kr2-strong-stock-notfound {
|
|
666
|
+
color: #ff6b6b;
|
|
667
|
+
font-weight: 700;
|
|
668
|
+
}
|
|
669
|
+
.kr2-strong-stock-notfound .kr2-strong-stock-name {
|
|
670
|
+
color: #ff6b6b;
|
|
671
|
+
}
|
|
672
|
+
.kr2-strong-stock-clear {
|
|
673
|
+
color: #4fc3f7;
|
|
674
|
+
font-weight: 700;
|
|
675
|
+
}
|
|
676
|
+
.kr2-strong-clear-row {
|
|
677
|
+
background: rgba(79, 195, 247, 0.14);
|
|
678
|
+
}
|
|
679
|
+
.kr2-strong-owned {
|
|
680
|
+
color: #f6f7f9;
|
|
681
|
+
font-weight: 700;
|
|
682
|
+
}
|
|
683
|
+
.kr2-strong-owned.kr2-strong-stock-short {
|
|
684
|
+
color: #ff6b6b;
|
|
685
|
+
}
|
|
686
|
+
.kr2-strong-owned.kr2-strong-stock-clear {
|
|
687
|
+
color: #4fc3f7;
|
|
688
|
+
}
|
|
689
|
+
.kr2-strong-clear-row td {
|
|
690
|
+
color: #4fc3f7;
|
|
691
|
+
}
|
|
692
|
+
.kr2-strong-clear-row .kr2-strong-target,
|
|
693
|
+
.kr2-strong-clear-row .kr2-strong-stock-name,
|
|
694
|
+
.kr2-strong-clear-row .kr2-strong-owned {
|
|
695
|
+
color: #4fc3f7;
|
|
696
|
+
}
|
|
446
697
|
.kr2-search {
|
|
447
698
|
width: 240px;
|
|
448
699
|
padding: 6px 10px;
|
|
@@ -509,20 +760,24 @@ const CSS = `
|
|
|
509
760
|
overflow-y: scroll;
|
|
510
761
|
}
|
|
511
762
|
.kr2-plan::-webkit-scrollbar,
|
|
763
|
+
.kr2-strong::-webkit-scrollbar,
|
|
512
764
|
.kr2-list::-webkit-scrollbar {
|
|
513
765
|
width: 10px;
|
|
514
766
|
height: 10px;
|
|
515
767
|
}
|
|
516
768
|
.kr2-plan::-webkit-scrollbar-track,
|
|
769
|
+
.kr2-strong::-webkit-scrollbar-track,
|
|
517
770
|
.kr2-list::-webkit-scrollbar-track {
|
|
518
771
|
background: #1c2127;
|
|
519
772
|
}
|
|
520
773
|
.kr2-plan::-webkit-scrollbar-thumb,
|
|
774
|
+
.kr2-strong::-webkit-scrollbar-thumb,
|
|
521
775
|
.kr2-list::-webkit-scrollbar-thumb {
|
|
522
776
|
background: #5f6b7c;
|
|
523
777
|
border-radius: 5px;
|
|
524
778
|
}
|
|
525
779
|
.kr2-plan::-webkit-scrollbar-thumb:hover,
|
|
780
|
+
.kr2-strong::-webkit-scrollbar-thumb:hover,
|
|
526
781
|
.kr2-list::-webkit-scrollbar-thumb:hover {
|
|
527
782
|
background: #8b95a1;
|
|
528
783
|
}
|
|
@@ -1944,6 +2199,8 @@ function buildRows(staticData, masterEquips, fallbackNames, akashi, recommendati
|
|
|
1944
2199
|
upgradesByEquip[key].push(
|
|
1945
2200
|
Object.assign({}, r, {
|
|
1946
2201
|
targetName: String(targetMaster.api_name || targetFallback.name || ("装备 " + r.upgrade_id)),
|
|
2202
|
+
targetCategory: String(targetMaster.api_type_name || targetFallback.type || ""),
|
|
2203
|
+
targetBase: baseById[targetId] || null,
|
|
1947
2204
|
secretaries: secretaries.slice(),
|
|
1948
2205
|
})
|
|
1949
2206
|
)
|
|
@@ -2168,7 +2425,7 @@ function planInventoryLevels(row, inventoryByEquip) {
|
|
|
2168
2425
|
return out
|
|
2169
2426
|
}
|
|
2170
2427
|
|
|
2171
|
-
function planCopyCosts(row, target, current) {
|
|
2428
|
+
function planCopyCosts(row, target, current, upgradeId) {
|
|
2172
2429
|
const levels = target === "max" ? PLAN_LEVELS_MAX : PLAN_LEVELS_6
|
|
2173
2430
|
const out = { screws: 0, dev: 0, fuel: 0, ammo: 0, steel: 0, bauxite: 0, materials: [] }
|
|
2174
2431
|
for (const lv of levels) {
|
|
@@ -2192,10 +2449,31 @@ function planCopyCosts(row, target, current) {
|
|
|
2192
2449
|
out.materials.push({ item: m, count: m.count || 1 })
|
|
2193
2450
|
}
|
|
2194
2451
|
}
|
|
2452
|
+
if (upgradeId != null && target === "max") {
|
|
2453
|
+
const upg = (row.upgrades || []).find((u) => String(u.upgrade_id) === String(upgradeId))
|
|
2454
|
+
if (upg) {
|
|
2455
|
+
const rec = buildRecommendation(upg.consume_improvement_min, upg.consume_improvement_max, 0.62)
|
|
2456
|
+
const ensure = rec.tone === "ensure"
|
|
2457
|
+
const expected = Number.isFinite(rec.expected) ? rec.expected : upg.consume_improvement_min / 0.62
|
|
2458
|
+
const screws = ensure ? upg.consume_improvement_max : expected
|
|
2459
|
+
const attempts = ensure ? 1 : expected
|
|
2460
|
+
const dev = ensure ? upg.consume_development_max : upg.consume_development_min * attempts
|
|
2461
|
+
out.screws += screws
|
|
2462
|
+
out.dev += dev
|
|
2463
|
+
const base = upg.targetBase || row.base || {}
|
|
2464
|
+
out.fuel += (base.consume_fuel || 0) * attempts
|
|
2465
|
+
out.ammo += (base.consume_ammo || 0) * attempts
|
|
2466
|
+
out.steel += (base.consume_steel || 0) * attempts
|
|
2467
|
+
out.bauxite += (base.consume_bauxite || 0) * attempts
|
|
2468
|
+
for (const m of upg.materials || []) {
|
|
2469
|
+
out.materials.push({ item: m, count: m.count || 1 })
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2195
2473
|
return out
|
|
2196
2474
|
}
|
|
2197
2475
|
|
|
2198
|
-
function planRowCosts(row, target, qty, inventoryByEquip) {
|
|
2476
|
+
function planRowCosts(row, target, qty, inventoryByEquip, upgradeId) {
|
|
2199
2477
|
const count = Math.max(1, Math.min(99, Math.round(Number(qty) || 1)))
|
|
2200
2478
|
let starts = []
|
|
2201
2479
|
if (count === 1) {
|
|
@@ -2206,7 +2484,7 @@ function planRowCosts(row, target, qty, inventoryByEquip) {
|
|
|
2206
2484
|
}
|
|
2207
2485
|
const out = { screws: 0, dev: 0, fuel: 0, ammo: 0, steel: 0, bauxite: 0, materials: [] }
|
|
2208
2486
|
for (const current of starts) {
|
|
2209
|
-
const c = planCopyCosts(row, target, current)
|
|
2487
|
+
const c = planCopyCosts(row, target, current, upgradeId)
|
|
2210
2488
|
out.screws += c.screws
|
|
2211
2489
|
out.dev += c.dev
|
|
2212
2490
|
out.fuel += c.fuel
|
|
@@ -2282,11 +2560,80 @@ function planMaterialDevExpected(costs, kcDevData) {
|
|
|
2282
2560
|
return total
|
|
2283
2561
|
}
|
|
2284
2562
|
|
|
2285
|
-
|
|
2563
|
+
class EvolutionButton extends React.Component {
|
|
2564
|
+
state = { open: false, selected: null }
|
|
2565
|
+
|
|
2566
|
+
open = () => {
|
|
2567
|
+
const branches = this.props.branches || []
|
|
2568
|
+
if (branches.length <= 1) {
|
|
2569
|
+
const id = branches[0] ? String(branches[0].upgrade_id) : null
|
|
2570
|
+
if (id == null || !this.props.onSelect) return
|
|
2571
|
+
this.props.onSelect(this.props.rowId, this.props.value === id ? null : id)
|
|
2572
|
+
return
|
|
2573
|
+
}
|
|
2574
|
+
this.setState({ open: true, selected: this.props.value || null })
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
close = () => {
|
|
2578
|
+
if (this.props.onSelect) this.props.onSelect(this.props.rowId, this.state.selected)
|
|
2579
|
+
this.setState({ open: false })
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
render() {
|
|
2583
|
+
const branches = this.props.branches || []
|
|
2584
|
+
if (branches.length === 0) {
|
|
2585
|
+
return React.createElement("button", { type: "button", className: "kr2-plan-evo-btn", disabled: true }, "无进化")
|
|
2586
|
+
}
|
|
2587
|
+
const active = !!this.props.value
|
|
2588
|
+
const selected = branches.find((b) => String(b.upgrade_id) === String(this.props.value))
|
|
2589
|
+
const label = "进化"
|
|
2590
|
+
return React.createElement(
|
|
2591
|
+
"div",
|
|
2592
|
+
{ className: "kr2-plan-evo-wrap" },
|
|
2593
|
+
React.createElement("button", { type: "button", className: "kr2-plan-evo-btn" + (active ? " kr2-plan-evo-active" : ""), onClick: this.open }, label),
|
|
2594
|
+
this.state.open
|
|
2595
|
+
? React.createElement(
|
|
2596
|
+
"div",
|
|
2597
|
+
{ className: "kr2-modal-backdrop", onClick: this.close },
|
|
2598
|
+
React.createElement(
|
|
2599
|
+
"div",
|
|
2600
|
+
{ className: "kr2-modal kr2-evo-modal", onClick: (e) => e.stopPropagation() },
|
|
2601
|
+
React.createElement(
|
|
2602
|
+
"div",
|
|
2603
|
+
{ className: "kr2-modal-head" },
|
|
2604
|
+
React.createElement("div", { className: "kr2-modal-title" }, "选择进化分支"),
|
|
2605
|
+
React.createElement(
|
|
2606
|
+
"div",
|
|
2607
|
+
{ className: "kr2-modal-actions" },
|
|
2608
|
+
React.createElement("button", { className: "kr2-button", onClick: this.close }, "关闭")
|
|
2609
|
+
)
|
|
2610
|
+
),
|
|
2611
|
+
React.createElement(
|
|
2612
|
+
"div",
|
|
2613
|
+
{ className: "kr2-evo-scroll" },
|
|
2614
|
+
branches.map((b) =>
|
|
2615
|
+
React.createElement(
|
|
2616
|
+
"button",
|
|
2617
|
+
{ key: String(b.upgrade_id), type: "button", className: "kr2-evo-option" + (this.state.selected === String(b.upgrade_id) ? " kr2-evo-option-active" : ""), onClick: () => this.setState({ selected: String(b.upgrade_id) }) },
|
|
2618
|
+
b.targetName
|
|
2619
|
+
)
|
|
2620
|
+
)
|
|
2621
|
+
)
|
|
2622
|
+
)
|
|
2623
|
+
)
|
|
2624
|
+
: null
|
|
2625
|
+
)
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
function PlanningPage({ rows, inventoryByEquip, useItemCounts, selection, onToggle, onTarget, onQty, onSelectAll, onMaterialClick, kcDevData, includeDevExpected, onToggleIncludeDevExpected, onEvo }) {
|
|
2286
2630
|
const planRows = rows.map((row) => {
|
|
2287
2631
|
const sel = (selection || {})[row.id] || { selected: true, target: "max", qty: 1 }
|
|
2288
|
-
const
|
|
2289
|
-
|
|
2632
|
+
const evoUpgradeId = sel.evoUpgradeId || null
|
|
2633
|
+
const evoBranch = evoUpgradeId ? (row.upgrades || []).find((u) => String(u.upgrade_id) === String(evoUpgradeId)) : null
|
|
2634
|
+
const target = evoUpgradeId ? "max" : sel.target
|
|
2635
|
+
const costs = planRowCosts(row, target, sel.qty, inventoryByEquip, evoUpgradeId)
|
|
2636
|
+
return { row, sel, costs, matDev: planMaterialDevExpected(costs, kcDevData), display: planCurrentDisplay(row, sel, inventoryByEquip), target, evoUpgradeId, evoBranch }
|
|
2290
2637
|
})
|
|
2291
2638
|
const selected = planRows.filter((p) => p.sel.selected)
|
|
2292
2639
|
const totals = { screws: 0, dev: 0, fuel: 0, ammo: 0, steel: 0, bauxite: 0 }
|
|
@@ -2351,7 +2698,7 @@ function PlanningPage({ rows, inventoryByEquip, useItemCounts, selection, onTogg
|
|
|
2351
2698
|
),
|
|
2352
2699
|
React.createElement(
|
|
2353
2700
|
"table",
|
|
2354
|
-
{ className: "kr2-table kr2-plan-table" },
|
|
2701
|
+
{ className: "kr2-table kr2-plan-table kr2-plan-main-table" },
|
|
2355
2702
|
React.createElement(
|
|
2356
2703
|
"thead",
|
|
2357
2704
|
null,
|
|
@@ -2377,22 +2724,17 @@ function PlanningPage({ rows, inventoryByEquip, useItemCounts, selection, onTogg
|
|
|
2377
2724
|
"tr",
|
|
2378
2725
|
{ key: p.row.id },
|
|
2379
2726
|
React.createElement("td", null, React.createElement("input", { type: "checkbox", checked: !!p.sel.selected, onChange: () => onToggle(p.row.id) })),
|
|
2380
|
-
React.createElement("td", { className: "kr2-plan-name" }, React.createElement("span", { className: "kr2-plan-name-inner" }, React.createElement(SlotitemIcon, { slotitemId: p.row.icon, className: "kr2-icon" }), " ", p.row.name)),
|
|
2727
|
+
React.createElement("td", { className: "kr2-plan-name" }, React.createElement("span", { className: "kr2-plan-name-inner" }, React.createElement(SlotitemIcon, { slotitemId: p.row.icon, className: "kr2-icon" }), " ", p.row.name, p.evoBranch ? React.createElement("span", { className: "kr2-plan-evo-target-line" }, "→ ", React.createElement("span", { className: "kr2-plan-evo-target-name" }, p.evoBranch.targetName)) : null)),
|
|
2381
2728
|
React.createElement("td", { className: Math.round(Number(p.sel.qty || 1)) === 1 ? "kr2-plan-current" : "kr2-plan-current-stock" }, p.display),
|
|
2382
2729
|
React.createElement(
|
|
2383
2730
|
"td",
|
|
2384
2731
|
null,
|
|
2385
2732
|
React.createElement(
|
|
2386
|
-
"
|
|
2387
|
-
{
|
|
2388
|
-
React.createElement("
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
React.createElement(
|
|
2392
|
-
"label",
|
|
2393
|
-
null,
|
|
2394
|
-
React.createElement("input", { type: "radio", name: "plan-" + p.row.id, checked: p.sel.target === "max", onChange: () => onTarget(p.row.id, "max") }),
|
|
2395
|
-
"MAX"
|
|
2733
|
+
"div",
|
|
2734
|
+
{ className: "kr2-plan-target-group" },
|
|
2735
|
+
React.createElement("button", { type: "button", className: "kr2-plan-target-btn" + (!p.evoUpgradeId && p.target !== "max" ? " kr2-plan-target-active" : ""), onClick: () => onTarget(p.row.id, "6") }, "+6"),
|
|
2736
|
+
React.createElement("button", { type: "button", className: "kr2-plan-target-btn" + (!p.evoUpgradeId && p.target === "max" ? " kr2-plan-target-active" : ""), onClick: () => onTarget(p.row.id, "max") }, "max"),
|
|
2737
|
+
React.createElement(EvolutionButton, { rowId: p.row.id, branches: p.row.upgrades || [], value: p.evoUpgradeId, onSelect: onEvo })
|
|
2396
2738
|
)
|
|
2397
2739
|
),
|
|
2398
2740
|
React.createElement(
|
|
@@ -2447,6 +2789,161 @@ function PlanningPage({ rows, inventoryByEquip, useItemCounts, selection, onTogg
|
|
|
2447
2789
|
)
|
|
2448
2790
|
}
|
|
2449
2791
|
|
|
2792
|
+
class StrongPage extends React.Component {
|
|
2793
|
+
catRef = React.createRef()
|
|
2794
|
+
state = {
|
|
2795
|
+
categoryOpen: false,
|
|
2796
|
+
selectedCategories: readStrongCategories(),
|
|
2797
|
+
catPos: null,
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2800
|
+
toggleCategoryOpen = () => {
|
|
2801
|
+
if (this.state.categoryOpen) {
|
|
2802
|
+
this.setState({ categoryOpen: false, catPos: null })
|
|
2803
|
+
return
|
|
2804
|
+
}
|
|
2805
|
+
const el = this.catRef.current
|
|
2806
|
+
if (!el) return
|
|
2807
|
+
const rect = el.getBoundingClientRect()
|
|
2808
|
+
this.setState({
|
|
2809
|
+
categoryOpen: true,
|
|
2810
|
+
catPos: { top: rect.bottom + 4, left: rect.left, width: rect.width },
|
|
2811
|
+
})
|
|
2812
|
+
}
|
|
2813
|
+
|
|
2814
|
+
toggleCategory = (name) => {
|
|
2815
|
+
const all = Array.from(new Set((this.props.rows || []).map((row) => row.category).filter(Boolean)))
|
|
2816
|
+
this.setState((prev) => {
|
|
2817
|
+
let next
|
|
2818
|
+
if (prev.selectedCategories == null) {
|
|
2819
|
+
next = all.filter((c) => c !== name)
|
|
2820
|
+
} else if (prev.selectedCategories.indexOf(name) >= 0) {
|
|
2821
|
+
next = prev.selectedCategories.filter((c) => c !== name)
|
|
2822
|
+
} else {
|
|
2823
|
+
next = prev.selectedCategories.concat([name])
|
|
2824
|
+
}
|
|
2825
|
+
if (next.length === all.length) next = null
|
|
2826
|
+
saveStrongCategories(next)
|
|
2827
|
+
return { selectedCategories: next }
|
|
2828
|
+
})
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
render() {
|
|
2832
|
+
const { rows, inventoryByEquip, selection } = this.props
|
|
2833
|
+
const inventoryLoaded = inventoryByEquip && Object.keys(inventoryByEquip).length > 0
|
|
2834
|
+
const entries = []
|
|
2835
|
+
const levelText = (level) => {
|
|
2836
|
+
const n = Number(level)
|
|
2837
|
+
if (n >= 10) return "max"
|
|
2838
|
+
return "+" + String(n)
|
|
2839
|
+
}
|
|
2840
|
+
for (const row of rows || []) {
|
|
2841
|
+
const sel = (selection || {})[row.id] || { selected: true, target: "max", qty: 1 }
|
|
2842
|
+
const qty = Math.max(1, Math.min(99, Math.round(Number(sel.qty) || 1)))
|
|
2843
|
+
const evoUpgradeId = sel.evoUpgradeId || null
|
|
2844
|
+
const evoUpgrade = evoUpgradeId ? (row.upgrades || []).find((u) => String(u.upgrade_id) === String(evoUpgradeId)) : null
|
|
2845
|
+
const displayRow = evoUpgrade
|
|
2846
|
+
? Object.assign({}, row, { id: row.id + ":evo:" + evoUpgrade.upgrade_id, name: evoUpgrade.targetName, category: evoUpgrade.targetCategory || row.category })
|
|
2847
|
+
: row
|
|
2848
|
+
const invId = evoUpgrade ? String(evoUpgrade.upgrade_id) : row.id
|
|
2849
|
+
const targetLevelValue = evoUpgrade ? 0 : (sel.target === "max" ? 10 : 6)
|
|
2850
|
+
const targetLevel = levelText(targetLevelValue)
|
|
2851
|
+
const inv = (inventoryByEquip || {})[invId]
|
|
2852
|
+
const levels = []
|
|
2853
|
+
if (inv && inv.levels) {
|
|
2854
|
+
for (const level of Object.keys(inv.levels)) {
|
|
2855
|
+
const count = Math.max(0, Math.round(Number(inv.levels[level]) || 0))
|
|
2856
|
+
if (count > 0) levels.push({ level: Number(level), count })
|
|
2857
|
+
}
|
|
2858
|
+
levels.sort((a, b) => b.level - a.level)
|
|
2859
|
+
}
|
|
2860
|
+
const rowEntries = []
|
|
2861
|
+
if (levels.length === 0) {
|
|
2862
|
+
rowEntries.push({ key: displayRow.id + ":none", row: displayRow, targetLevel, targetLevelValue, inventoryLevel: null, stock: inventoryLoaded ? 0 : null, notFound: true })
|
|
2863
|
+
} else {
|
|
2864
|
+
for (const lv of levels) rowEntries.push({ key: displayRow.id + ":" + String(lv.level), row: displayRow, targetLevel, targetLevelValue, inventoryLevel: lv.level, stock: lv.count })
|
|
2865
|
+
}
|
|
2866
|
+
const base = Math.floor(qty / rowEntries.length)
|
|
2867
|
+
let remainder = qty % rowEntries.length
|
|
2868
|
+
for (const item of rowEntries) {
|
|
2869
|
+
item.qty = base + (remainder > 0 ? 1 : 0)
|
|
2870
|
+
if (remainder > 0) remainder -= 1
|
|
2871
|
+
}
|
|
2872
|
+
for (const item of rowEntries) {
|
|
2873
|
+
if (item.qty > 0) entries.push(item)
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
for (const item of entries) {
|
|
2877
|
+
item.clear = item.qty > 0 && item.stock != null && item.inventoryLevel === item.targetLevelValue && item.stock >= item.qty
|
|
2878
|
+
item.levelShort = item.inventoryLevel != null && item.inventoryLevel < item.targetLevelValue
|
|
2879
|
+
item.countShort = item.stock != null && item.qty > 0 && item.stock < item.qty
|
|
2880
|
+
item.countEnough = item.stock != null && item.stock >= item.qty
|
|
2881
|
+
}
|
|
2882
|
+
entries.sort((a, b) => (b.clear ? 1 : 0) - (a.clear ? 1 : 0))
|
|
2883
|
+
const categories = Array.from(new Set(entries.map((item) => item.row.category).filter(Boolean))).sort((a, b) => a.localeCompare(b, "zh-Hans-CN"))
|
|
2884
|
+
const selectedCategories = this.state.selectedCategories
|
|
2885
|
+
const visibleEntries = selectedCategories == null ? entries : entries.filter((item) => selectedCategories.indexOf(item.row.category) >= 0)
|
|
2886
|
+
const stockText = (item) => {
|
|
2887
|
+
const nameNode = React.createElement("span", { className: "kr2-strong-stock-name" }, item.row.name)
|
|
2888
|
+
if (item.notFound || item.stock == null) return nameNode
|
|
2889
|
+
const levelPart = levelText(item.inventoryLevel)
|
|
2890
|
+
return React.createElement("span", null, nameNode, " ", levelPart)
|
|
2891
|
+
}
|
|
2892
|
+
const stockClass = (item) => item.notFound || item.stock == null ? "kr2-strong-stock-notfound" : item.clear ? "kr2-strong-stock-clear" : item.levelShort ? "kr2-strong-stock-short" : "kr2-strong-stock-ok"
|
|
2893
|
+
const ownedClass = (item) => item.stock == null ? "kr2-strong-stock-missing" : item.clear || item.countEnough ? "kr2-strong-stock-clear" : item.countShort ? "kr2-strong-stock-short" : "kr2-strong-stock-ok"
|
|
2894
|
+
const catStyle = this.state.catPos ? { position: "fixed", top: this.state.catPos.top, left: this.state.catPos.left, minWidth: Math.max(180, this.state.catPos.width) } : null
|
|
2895
|
+
const categoryHead = React.createElement(
|
|
2896
|
+
"th",
|
|
2897
|
+
{ className: "kr2-strong-cat-th", ref: this.catRef, onClick: this.toggleCategoryOpen },
|
|
2898
|
+
React.createElement("span", { className: "kr2-strong-cat-title" }, "装备分类"),
|
|
2899
|
+
React.createElement("span", { className: "kr2-strong-cat-arrow" }, this.state.categoryOpen ? "▲" : "▼"),
|
|
2900
|
+
this.state.categoryOpen
|
|
2901
|
+
? React.createElement(
|
|
2902
|
+
"div",
|
|
2903
|
+
{ className: "kr2-strong-cat-menu", style: catStyle, onClick: (e) => e.stopPropagation() },
|
|
2904
|
+
categories.map((cat) =>
|
|
2905
|
+
React.createElement(
|
|
2906
|
+
"label",
|
|
2907
|
+
{ key: cat, className: "kr2-strong-cat-option" },
|
|
2908
|
+
React.createElement("input", { type: "checkbox", checked: selectedCategories == null || selectedCategories.indexOf(cat) >= 0, onChange: () => this.toggleCategory(cat) }),
|
|
2909
|
+
cat
|
|
2910
|
+
)
|
|
2911
|
+
)
|
|
2912
|
+
)
|
|
2913
|
+
: null
|
|
2914
|
+
)
|
|
2915
|
+
return React.createElement(
|
|
2916
|
+
"div",
|
|
2917
|
+
{ className: "kr2-strong" },
|
|
2918
|
+
React.createElement(
|
|
2919
|
+
"table",
|
|
2920
|
+
{ className: "kr2-table kr2-plan-table kr2-strong-table" },
|
|
2921
|
+
React.createElement(
|
|
2922
|
+
"thead",
|
|
2923
|
+
null,
|
|
2924
|
+
React.createElement("tr", null, categoryHead, React.createElement("th", null, "目标装备"), React.createElement("th", null, "目标数"), React.createElement("th", null, "库存"), React.createElement("th", null, "完成数"))
|
|
2925
|
+
),
|
|
2926
|
+
React.createElement(
|
|
2927
|
+
"tbody",
|
|
2928
|
+
null,
|
|
2929
|
+
visibleEntries.length === 0
|
|
2930
|
+
? React.createElement("tr", null, React.createElement("td", { colSpan: 5 }, "无匹配分类"))
|
|
2931
|
+
: visibleEntries.map((item) =>
|
|
2932
|
+
React.createElement(
|
|
2933
|
+
"tr",
|
|
2934
|
+
{ key: item.key, className: item.clear ? "kr2-strong-clear-row" : null },
|
|
2935
|
+
React.createElement("td", { className: "kr2-strong-cat" }, item.row.category || "-"),
|
|
2936
|
+
React.createElement("td", { className: "kr2-strong-equip" }, item.row.name, " ", React.createElement("span", { className: "kr2-strong-level" }, item.targetLevel)),
|
|
2937
|
+
React.createElement("td", { className: "kr2-strong-target" }, String(item.qty)),
|
|
2938
|
+
React.createElement("td", { className: "kr2-strong-stock " + stockClass(item) }, stockText(item)),
|
|
2939
|
+
React.createElement("td", { className: "kr2-strong-owned " + ownedClass(item) }, item.stock == null ? "--" : item.clear ? "clear!" : String(item.stock))
|
|
2940
|
+
)
|
|
2941
|
+
)
|
|
2942
|
+
)
|
|
2943
|
+
)
|
|
2944
|
+
)
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2450
2947
|
function RateCell({ range, open, onToggle, tone }) {
|
|
2451
2948
|
return React.createElement(
|
|
2452
2949
|
"span",
|
|
@@ -2536,12 +3033,15 @@ class LevelTwoTable extends React.Component {
|
|
|
2536
3033
|
const phase1 = this.props.phase1
|
|
2537
3034
|
const upgrades = this.props.upgrades || null
|
|
2538
3035
|
const rows = []
|
|
2539
|
-
const pushRateRow = (step, range, label, key, p, subText, evolTarget) => {
|
|
3036
|
+
const pushRateRow = (step, range, label, key, p, subText, evolTarget, maxBlue) => {
|
|
2540
3037
|
const normal = step ? step.consume_improvement_min : null
|
|
2541
3038
|
const certain = step ? step.consume_improvement_max : null
|
|
2542
3039
|
const rec = buildRecommendation(normal, certain, p)
|
|
2543
3040
|
const materials = step ? step.materials || [] : []
|
|
2544
3041
|
const hasMaterials = materials.some((item) => item && (item.item_name || item.item_material_key || item.item_equipment_id != null))
|
|
3042
|
+
const rangeNode = maxBlue
|
|
3043
|
+
? React.createElement("span", null, "★9→", React.createElement("span", { className: "kr2-level-max-blue" }, "max"))
|
|
3044
|
+
: range
|
|
2545
3045
|
rows.push(
|
|
2546
3046
|
React.createElement(
|
|
2547
3047
|
"tr",
|
|
@@ -2561,7 +3061,7 @@ class LevelTwoTable extends React.Component {
|
|
|
2561
3061
|
),
|
|
2562
3062
|
React.createElement("div", { className: "kr2-evol-secretaries" }, subText)
|
|
2563
3063
|
)
|
|
2564
|
-
:
|
|
3064
|
+
: rangeNode
|
|
2565
3065
|
),
|
|
2566
3066
|
React.createElement("td", null, label),
|
|
2567
3067
|
React.createElement("td", null, normal == null ? "--" : String(normal)),
|
|
@@ -2597,7 +3097,7 @@ class LevelTwoTable extends React.Component {
|
|
|
2597
3097
|
return
|
|
2598
3098
|
}
|
|
2599
3099
|
const step = rate.source === "phase0" ? phase0 : phase1
|
|
2600
|
-
pushRateRow(step, rate.range, rate.label, rate.range, rate.p)
|
|
3100
|
+
pushRateRow(step, rate.range, rate.label, rate.range, rate.p, "", "", rate.range === "★9→max" && !upgrades)
|
|
2601
3101
|
})
|
|
2602
3102
|
|
|
2603
3103
|
return React.createElement(
|
|
@@ -2713,7 +3213,7 @@ function EquipmentRow({ row, expanded, onToggle, onMaterialClick, inventoryByEqu
|
|
|
2713
3213
|
{ className: "kr2-level" },
|
|
2714
3214
|
React.createElement(
|
|
2715
3215
|
LevelSection,
|
|
2716
|
-
{ title: "6→
|
|
3216
|
+
{ title: "6→max", defaultOpen: true, resourceText: "成功率 95 / 90 / 82 / 77 / 67 / 62 %" },
|
|
2717
3217
|
React.createElement(LevelTwoTable, { phase0: row.phase0, phase1: row.phase1, upgrades: row.upgrades, onMaterialClick, inventoryByEquip, useItemCounts, onInventoryClick })
|
|
2718
3218
|
)
|
|
2719
3219
|
)
|
|
@@ -2805,6 +3305,100 @@ function saveFavorites(favorites) {
|
|
|
2805
3305
|
saveFavoritesToLocalStorage(favorites)
|
|
2806
3306
|
}
|
|
2807
3307
|
|
|
3308
|
+
const UI_STATE_STORAGE_KEY = "poi-plugin-koushu-rate:ui-state";
|
|
3309
|
+
const FAVORITES_ONLY_STORAGE_KEY = "poi-plugin-koushu-rate:favorites-only";
|
|
3310
|
+
const UI_STATE_FILE_NAME = "ui-state.json";
|
|
3311
|
+
|
|
3312
|
+
function getUiStateFilePath() {
|
|
3313
|
+
try {
|
|
3314
|
+
let remote = null
|
|
3315
|
+
try {
|
|
3316
|
+
remote = require("@electron/remote")
|
|
3317
|
+
} catch (_) {}
|
|
3318
|
+
if (!remote) {
|
|
3319
|
+
try {
|
|
3320
|
+
remote = require("electron").remote
|
|
3321
|
+
} catch (_) {}
|
|
3322
|
+
}
|
|
3323
|
+
const app = remote && (remote.app || (remote.default && remote.default.app))
|
|
3324
|
+
if (app && typeof app.getPath === "function") {
|
|
3325
|
+
return path.join(String(app.getPath("userData")), "poi-plugin-koushu-rate", UI_STATE_FILE_NAME)
|
|
3326
|
+
}
|
|
3327
|
+
} catch (_) {}
|
|
3328
|
+
return null
|
|
3329
|
+
}
|
|
3330
|
+
|
|
3331
|
+
function readUiStateFromLocalStorage() {
|
|
3332
|
+
const out = {}
|
|
3333
|
+
try {
|
|
3334
|
+
const storage = typeof localStorage !== "undefined" ? localStorage : (typeof window !== "undefined" ? window.localStorage : null)
|
|
3335
|
+
if (!storage) return out
|
|
3336
|
+
const raw = storage.getItem(UI_STATE_STORAGE_KEY)
|
|
3337
|
+
if (raw) {
|
|
3338
|
+
const parsed = JSON.parse(raw)
|
|
3339
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) Object.assign(out, parsed)
|
|
3340
|
+
}
|
|
3341
|
+
const legacy = storage.getItem(FAVORITES_ONLY_STORAGE_KEY)
|
|
3342
|
+
if (legacy != null && out.favoritesOnly == null) out.favoritesOnly = legacy === "1"
|
|
3343
|
+
} catch (_) {}
|
|
3344
|
+
return out
|
|
3345
|
+
}
|
|
3346
|
+
|
|
3347
|
+
function writeUiStateToLocalStorage(state) {
|
|
3348
|
+
try {
|
|
3349
|
+
const storage = typeof localStorage !== "undefined" ? localStorage : (typeof window !== "undefined" ? window.localStorage : null)
|
|
3350
|
+
if (storage) storage.setItem(UI_STATE_STORAGE_KEY, JSON.stringify(state || {}))
|
|
3351
|
+
} catch (_) {}
|
|
3352
|
+
}
|
|
3353
|
+
|
|
3354
|
+
function readUiState() {
|
|
3355
|
+
const file = getUiStateFilePath()
|
|
3356
|
+
let fileState = {}
|
|
3357
|
+
if (file) {
|
|
3358
|
+
try {
|
|
3359
|
+
if (fs.existsSync(file)) {
|
|
3360
|
+
const parsed = JSON.parse(fs.readFileSync(file, "utf8"))
|
|
3361
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) fileState = parsed
|
|
3362
|
+
}
|
|
3363
|
+
} catch (_) {}
|
|
3364
|
+
}
|
|
3365
|
+
return Object.assign({}, fileState, readUiStateFromLocalStorage())
|
|
3366
|
+
}
|
|
3367
|
+
|
|
3368
|
+
function saveUiState(patch) {
|
|
3369
|
+
const next = Object.assign({}, readUiState(), patch || {})
|
|
3370
|
+
for (const key of ["query", "day", "category", "activeTab"]) delete next[key]
|
|
3371
|
+
const file = getUiStateFilePath()
|
|
3372
|
+
if (file) {
|
|
3373
|
+
try {
|
|
3374
|
+
fs.mkdirSync(path.dirname(file), { recursive: true })
|
|
3375
|
+
fs.writeFileSync(file, JSON.stringify(next, null, 2), "utf8")
|
|
3376
|
+
} catch (_) {}
|
|
3377
|
+
}
|
|
3378
|
+
writeUiStateToLocalStorage(next)
|
|
3379
|
+
try {
|
|
3380
|
+
const storage = typeof localStorage !== "undefined" ? localStorage : (typeof window !== "undefined" ? window.localStorage : null)
|
|
3381
|
+
if (storage) storage.setItem(FAVORITES_ONLY_STORAGE_KEY, next.favoritesOnly ? "1" : "0")
|
|
3382
|
+
} catch (_) {}
|
|
3383
|
+
return next
|
|
3384
|
+
}
|
|
3385
|
+
|
|
3386
|
+
function readFavoritesOnly() {
|
|
3387
|
+
return !!readUiState().favoritesOnly
|
|
3388
|
+
}
|
|
3389
|
+
|
|
3390
|
+
function saveFavoritesOnly(value) {
|
|
3391
|
+
saveUiState({ favoritesOnly: !!value })
|
|
3392
|
+
}
|
|
3393
|
+
|
|
3394
|
+
function readStrongCategories() {
|
|
3395
|
+
const value = readUiState().strongCategories
|
|
3396
|
+
return Array.isArray(value) ? value : null
|
|
3397
|
+
}
|
|
3398
|
+
|
|
3399
|
+
function saveStrongCategories(value) {
|
|
3400
|
+
saveUiState({ strongCategories: Array.isArray(value) ? value : null })
|
|
3401
|
+
}
|
|
2808
3402
|
const PLAN_SELECTION_STORAGE_KEY = "poi-plugin-koushu-rate:plan-selection";
|
|
2809
3403
|
|
|
2810
3404
|
function readPlanSelection() {
|
|
@@ -2866,8 +3460,8 @@ class KoushuRateApp extends React.Component {
|
|
|
2866
3460
|
useItemCounts: {},
|
|
2867
3461
|
kcDevData: null,
|
|
2868
3462
|
favorites: readFavorites(),
|
|
2869
|
-
favoritesOnly:
|
|
2870
|
-
starSort: null,
|
|
3463
|
+
favoritesOnly: readFavoritesOnly(),
|
|
3464
|
+
starSort: readUiState().starSort || null,
|
|
2871
3465
|
activeTab: "list",
|
|
2872
3466
|
planSelection: readPlanSelection(),
|
|
2873
3467
|
includeDevExpected: readPlanIncludeDev(),
|
|
@@ -2957,13 +3551,19 @@ class KoushuRateApp extends React.Component {
|
|
|
2957
3551
|
}
|
|
2958
3552
|
|
|
2959
3553
|
toggleFavoritesOnly = () => {
|
|
2960
|
-
this.setState((prev) =>
|
|
3554
|
+
this.setState((prev) => {
|
|
3555
|
+
const favoritesOnly = !prev.favoritesOnly
|
|
3556
|
+
saveFavoritesOnly(favoritesOnly)
|
|
3557
|
+
return { favoritesOnly }
|
|
3558
|
+
})
|
|
2961
3559
|
}
|
|
2962
3560
|
|
|
2963
3561
|
toggleStarSort = () => {
|
|
2964
|
-
this.setState((prev) =>
|
|
2965
|
-
starSort
|
|
2966
|
-
|
|
3562
|
+
this.setState((prev) => {
|
|
3563
|
+
const starSort = prev.starSort === "desc" ? "asc" : prev.starSort === "asc" ? null : "desc"
|
|
3564
|
+
saveUiState({ starSort })
|
|
3565
|
+
return { starSort }
|
|
3566
|
+
})
|
|
2967
3567
|
}
|
|
2968
3568
|
|
|
2969
3569
|
toggleCategory = () => {
|
|
@@ -3053,7 +3653,18 @@ class KoushuRateApp extends React.Component {
|
|
|
3053
3653
|
setPlanTarget = (id, target) => {
|
|
3054
3654
|
this.setState((prev) => {
|
|
3055
3655
|
const cur = prev.planSelection[id] || this.planDefaultSel(id)
|
|
3056
|
-
const
|
|
3656
|
+
const next = Object.assign({}, cur, { target, evoUpgradeId: null })
|
|
3657
|
+
const planSelection = Object.assign({}, prev.planSelection, { [id]: next })
|
|
3658
|
+
savePlanSelection(planSelection)
|
|
3659
|
+
return { planSelection }
|
|
3660
|
+
})
|
|
3661
|
+
}
|
|
3662
|
+
|
|
3663
|
+
setPlanEvo = (id, upgradeId) => {
|
|
3664
|
+
this.setState((prev) => {
|
|
3665
|
+
const cur = prev.planSelection[id] || this.planDefaultSel(id)
|
|
3666
|
+
const next = Object.assign({}, cur, { target: "max", evoUpgradeId: upgradeId == null ? null : String(upgradeId) })
|
|
3667
|
+
const planSelection = Object.assign({}, prev.planSelection, { [id]: next })
|
|
3057
3668
|
savePlanSelection(planSelection)
|
|
3058
3669
|
return { planSelection }
|
|
3059
3670
|
})
|
|
@@ -3161,6 +3772,7 @@ class KoushuRateApp extends React.Component {
|
|
|
3161
3772
|
React.createElement(
|
|
3162
3773
|
"div",
|
|
3163
3774
|
{ className: "kr2-header" },
|
|
3775
|
+
|
|
3164
3776
|
React.createElement(
|
|
3165
3777
|
"div",
|
|
3166
3778
|
{ className: "kr2-title-row" },
|
|
@@ -3204,7 +3816,14 @@ class KoushuRateApp extends React.Component {
|
|
|
3204
3816
|
),
|
|
3205
3817
|
React.createElement(
|
|
3206
3818
|
"div",
|
|
3207
|
-
{ className: "kr2-
|
|
3819
|
+
{ className: "kr2-nav" },
|
|
3820
|
+
React.createElement("button", { className: "kr2-nav-btn" + (this.state.activeTab === "list" ? " kr2-nav-active" : ""), onClick: () => this.setActiveTab("list") }, "改修列表"),
|
|
3821
|
+
React.createElement("button", { className: "kr2-nav-btn" + (this.state.activeTab === "plan" ? " kr2-nav-active" : ""), onClick: () => this.setActiveTab("plan") }, "素材计算"),
|
|
3822
|
+
React.createElement("button", { className: "kr2-nav-btn" + (this.state.activeTab === "strong" ? " kr2-nav-active" : ""), onClick: () => this.setActiveTab("strong") }, "我变强了!")
|
|
3823
|
+
),
|
|
3824
|
+
React.createElement(
|
|
3825
|
+
"div",
|
|
3826
|
+
{ className: "kr2-toolbar", style: this.state.activeTab === "plan" || this.state.activeTab === "strong" ? { display: "none" } : null },
|
|
3208
3827
|
React.createElement("input", {
|
|
3209
3828
|
className: "kr2-search",
|
|
3210
3829
|
value: this.state.query,
|
|
@@ -3246,15 +3865,10 @@ class KoushuRateApp extends React.Component {
|
|
|
3246
3865
|
: null
|
|
3247
3866
|
)
|
|
3248
3867
|
),
|
|
3868
|
+
|
|
3249
3869
|
React.createElement(
|
|
3250
3870
|
"div",
|
|
3251
|
-
{ className: "kr2-
|
|
3252
|
-
React.createElement("button", { className: "kr2-nav-btn" + (this.state.activeTab === "list" ? " kr2-nav-active" : ""), onClick: () => this.setActiveTab("list") }, "改修列表"),
|
|
3253
|
-
React.createElement("button", { className: "kr2-nav-btn" + (this.state.activeTab === "plan" ? " kr2-nav-active" : ""), onClick: () => this.setActiveTab("plan") }, "素材计算")
|
|
3254
|
-
),
|
|
3255
|
-
React.createElement(
|
|
3256
|
-
"div",
|
|
3257
|
-
{ className: "kr2-days", style: this.state.activeTab === "plan" ? { display: "none" } : null },
|
|
3871
|
+
{ className: "kr2-days", style: this.state.activeTab === "plan" || this.state.activeTab === "strong" ? { display: "none" } : null },
|
|
3258
3872
|
React.createElement(
|
|
3259
3873
|
"button",
|
|
3260
3874
|
{ className: "kr2-day" + (day === ALL_DAYS_KEY ? " kr2-day-active" : ""), onClick: () => this.setState({ day: ALL_DAYS_KEY }) },
|
|
@@ -3279,7 +3893,7 @@ class KoushuRateApp extends React.Component {
|
|
|
3279
3893
|
: null,
|
|
3280
3894
|
React.createElement(
|
|
3281
3895
|
"div",
|
|
3282
|
-
{ className: "kr2-list-head", style: this.state.activeTab === "plan" ? { display: "none" } : null },
|
|
3896
|
+
{ className: "kr2-list-head", style: this.state.activeTab === "plan" || this.state.activeTab === "strong" ? { display: "none" } : null },
|
|
3283
3897
|
React.createElement("span", { className: "kr2-head-name" }, "装备"),
|
|
3284
3898
|
React.createElement("span", { className: "kr2-head-secretary" }, "秘书舰"),
|
|
3285
3899
|
React.createElement("span", { className: "kr2-head-meta" }, "可改修日期"),
|
|
@@ -3296,7 +3910,7 @@ class KoushuRateApp extends React.Component {
|
|
|
3296
3910
|
),
|
|
3297
3911
|
React.createElement(
|
|
3298
3912
|
"div",
|
|
3299
|
-
{ className: "kr2-list", style: this.state.activeTab === "plan" ? { display: "none" } : null },
|
|
3913
|
+
{ className: "kr2-list", style: this.state.activeTab === "plan" || this.state.activeTab === "strong" ? { display: "none" } : null },
|
|
3300
3914
|
rows.length === 0
|
|
3301
3915
|
? React.createElement("div", { className: "kr2-empty" }, favoritesOnly ? "还没有收藏装备" : "没有匹配的装备")
|
|
3302
3916
|
: rows.map((row) =>
|
|
@@ -3323,6 +3937,7 @@ class KoushuRateApp extends React.Component {
|
|
|
3323
3937
|
selection: this.state.planSelection || {},
|
|
3324
3938
|
onToggle: this.togglePlanRow,
|
|
3325
3939
|
onTarget: this.setPlanTarget,
|
|
3940
|
+
onEvo: this.setPlanEvo,
|
|
3326
3941
|
onQty: this.setPlanQty,
|
|
3327
3942
|
onSelectAll: this.selectAllPlan,
|
|
3328
3943
|
onMaterialClick: this.openKcDevPopup,
|
|
@@ -3331,6 +3946,13 @@ class KoushuRateApp extends React.Component {
|
|
|
3331
3946
|
onToggleIncludeDevExpected: this.toggleIncludeDevExpected,
|
|
3332
3947
|
})
|
|
3333
3948
|
: null,
|
|
3949
|
+
this.state.activeTab === "strong"
|
|
3950
|
+
? React.createElement(StrongPage, {
|
|
3951
|
+
rows: this.state.rows.filter((row) => !!this.state.favorites[row.id]),
|
|
3952
|
+
inventoryByEquip,
|
|
3953
|
+
selection: this.state.planSelection || {},
|
|
3954
|
+
})
|
|
3955
|
+
: null,
|
|
3334
3956
|
kcDevPopup
|
|
3335
3957
|
? React.createElement(
|
|
3336
3958
|
"div",
|