poi-plugin-leveling-plan 0.0.1 → 0.0.2

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.
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.getTotalShortageCount = exports.calcAllShortages = exports.calcShortage = exports.getShipRemodelCost = exports.countRemodelNodesInRange = exports.getRemodelLevelsForShip = exports.getRemodelChainForShip = exports.parseShipMaterials = exports.getShipMaterials = exports.multiplyCost = exports.addCost = exports.emptyCost = exports.RESOURCE_INDEX = void 0;
5
+
6
+ var _lodash = _interopRequireDefault(require("lodash"));
7
+
8
+ var _constants = require("./constants");
9
+
10
+ var _kaisou_materials = _interopRequireDefault(require("../assets/kaisou_materials.json"));
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+
14
+ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
15
+
16
+ const KAISOU_ITEM_ID = {
17
+ drawing: 58,
18
+ catapult: 65,
19
+ report: 78,
20
+ devkit: 3,
21
+ buildkit: 2,
22
+ aviation: 77,
23
+ hokoheso: 75,
24
+ arms: 94
25
+ };
26
+ const RESOURCE_INDEX = {
27
+ fuel: 0,
28
+ ammo: 1,
29
+ steel: 2,
30
+ bauxite: 3,
31
+ buildkit: 4,
32
+ bucket: 5,
33
+ devmat: 6,
34
+ screw: 7
35
+ };
36
+ exports.RESOURCE_INDEX = RESOURCE_INDEX;
37
+
38
+ const emptyCost = () => ({
39
+ ammo: 0,
40
+ steel: 0,
41
+ consumable: {},
42
+ equipment: {}
43
+ });
44
+
45
+ exports.emptyCost = emptyCost;
46
+
47
+ const addCost = (a, b) => {
48
+ const addMap = (mapA, mapB) => {
49
+ const result = _extends({}, mapA);
50
+
51
+ Object.keys(mapB).forEach(key => {
52
+ result[key] = (result[key] || 0) + mapB[key];
53
+ });
54
+ return result;
55
+ };
56
+
57
+ return {
58
+ ammo: (a.ammo || 0) + (b.ammo || 0),
59
+ steel: (a.steel || 0) + (b.steel || 0),
60
+ consumable: addMap(a.consumable || {}, b.consumable || {}),
61
+ equipment: addMap(a.equipment || {}, b.equipment || {})
62
+ };
63
+ };
64
+
65
+ exports.addCost = addCost;
66
+
67
+ const multiplyCost = (cost, multiplier) => {
68
+ const m = Number(multiplier || 0);
69
+ if (m <= 0) return emptyCost();
70
+
71
+ const multiplyMap = map => {
72
+ const result = {};
73
+ Object.keys(map).forEach(key => {
74
+ result[key] = map[key] * m;
75
+ });
76
+ return result;
77
+ };
78
+
79
+ return {
80
+ ammo: (cost.ammo || 0) * m,
81
+ steel: (cost.steel || 0) * m,
82
+ consumable: multiplyMap(cost.consumable || {}),
83
+ equipment: multiplyMap(cost.equipment || {})
84
+ };
85
+ };
86
+
87
+ exports.multiplyCost = multiplyCost;
88
+
89
+ const getShipMaterials = shipMasterId => {
90
+ return _kaisou_materials.default[String(shipMasterId)] || null;
91
+ };
92
+
93
+ exports.getShipMaterials = getShipMaterials;
94
+
95
+ const parseShipMaterials = materialsData => {
96
+ if (!materialsData) return emptyCost();
97
+ const result = emptyCost();
98
+ result.ammo = Number(materialsData.ammo || 0);
99
+ result.steel = Number(materialsData.steel || 0);
100
+
101
+ if (Array.isArray(materialsData.consumable)) {
102
+ materialsData.consumable.forEach(([itemId, count]) => {
103
+ result.consumable[String(itemId)] = (result.consumable[String(itemId)] || 0) + count;
104
+ });
105
+ }
106
+
107
+ if (Array.isArray(materialsData.equipment)) {
108
+ materialsData.equipment.forEach(([equipId, count]) => {
109
+ result.equipment[String(equipId)] = (result.equipment[String(equipId)] || 0) + count;
110
+ });
111
+ }
112
+
113
+ return result;
114
+ }; // 直接从当前舰船往后遍历,不需要往前找起点
115
+
116
+
117
+ exports.parseShipMaterials = parseShipMaterials;
118
+
119
+ const getRemodelChainForShip = (shipMasterId, $ships) => {
120
+ if (!$ships || !$ships[shipMasterId]) return [shipMasterId];
121
+ const chain = [shipMasterId];
122
+ const visited = new Set([shipMasterId]);
123
+ let current = shipMasterId;
124
+ let iterations = 0;
125
+ const MAX_ITERATIONS = 20; // 防止无限循环
126
+
127
+ while (iterations < MAX_ITERATIONS) {
128
+ var _$ships$current;
129
+
130
+ iterations++;
131
+ const next = +(((_$ships$current = $ships[current]) === null || _$ships$current === void 0 ? void 0 : _$ships$current.api_aftershipid) || 0);
132
+ if (next <= 0 || visited.has(next)) break;
133
+ visited.add(next);
134
+ chain.push(next);
135
+ current = next;
136
+ }
137
+
138
+ return chain;
139
+ }; // 直接往后遍历获取改造等级
140
+
141
+
142
+ exports.getRemodelChainForShip = getRemodelChainForShip;
143
+
144
+ const getRemodelLevelsForShip = (shipMasterId, $ships) => {
145
+ if (!$ships || !$ships[shipMasterId]) return [];
146
+ const levels = [];
147
+ const visited = new Set();
148
+ let current = shipMasterId;
149
+ let iterations = 0;
150
+ const MAX_ITERATIONS = 20; // 防止无限循环
151
+
152
+ while (iterations < MAX_ITERATIONS) {
153
+ var _$ships$current2, _$ships$nextId;
154
+
155
+ iterations++;
156
+ const nextId = +(((_$ships$current2 = $ships[current]) === null || _$ships$current2 === void 0 ? void 0 : _$ships$current2.api_aftershipid) || 0);
157
+ if (nextId <= 0 || visited.has(nextId)) break;
158
+ visited.add(nextId);
159
+ const nextLv = +(((_$ships$nextId = $ships[nextId]) === null || _$ships$nextId === void 0 ? void 0 : _$ships$nextId.api_afterlv) || 0);
160
+
161
+ if (nextLv > 0 && nextLv < 200) {
162
+ // 过滤异常值
163
+ levels.push(nextLv);
164
+ }
165
+
166
+ current = nextId;
167
+ }
168
+
169
+ if (levels.length === 0) return [];
170
+ levels.sort((a, b) => a - b);
171
+ const lastLv = levels[levels.length - 1]; // 确保 MAX_LEVEL 是有效值
172
+
173
+ const maxLvl = typeof _constants.MAX_LEVEL === 'number' && _constants.MAX_LEVEL > 0 ? _constants.MAX_LEVEL : 100;
174
+
175
+ if (lastLv < 100) {
176
+ return [...levels, 99, maxLvl];
177
+ }
178
+
179
+ return [...levels, maxLvl];
180
+ };
181
+
182
+ exports.getRemodelLevelsForShip = getRemodelLevelsForShip;
183
+
184
+ const countRemodelNodesInRange = (shipMasterId, fromLevel, toLevel, $ships) => {
185
+ if (fromLevel >= toLevel) return 0;
186
+ const levels = getRemodelLevelsForShip(shipMasterId, $ships);
187
+ if (levels.length === 0) return 0;
188
+ return levels.filter(lv => lv > fromLevel && lv <= toLevel).length;
189
+ };
190
+
191
+ exports.countRemodelNodesInRange = countRemodelNodesInRange;
192
+
193
+ const getShipRemodelCost = (shipMasterId, fromLevel, toLevel, $ships) => {
194
+ if (!shipMasterId || fromLevel >= toLevel) return emptyCost();
195
+ const chain = getRemodelChainForShip(shipMasterId, $ships);
196
+ const levels = getRemodelLevelsForShip(shipMasterId, $ships);
197
+ if (levels.length === 0) return emptyCost();
198
+ let totalCost = emptyCost(); // 遍历改造等级,找出需要改造的节点
199
+
200
+ for (let i = 0; i < levels.length; i++) {
201
+ const targetLv = levels[i];
202
+ if (targetLv <= fromLevel || targetLv > toLevel) continue; // 改造前的舰船是 chain[i]
203
+
204
+ const shipIdBeforeRemodel = chain[i];
205
+ const materials = getShipMaterials(shipIdBeforeRemodel);
206
+
207
+ if (materials) {
208
+ const parsed = parseShipMaterials(materials);
209
+ totalCost = addCost(totalCost, parsed);
210
+ }
211
+ }
212
+
213
+ return totalCost;
214
+ };
215
+
216
+ exports.getShipRemodelCost = getShipRemodelCost;
217
+
218
+ const calcShortage = (required, available) => {
219
+ const req = Number(required || 0);
220
+ const avail = Number(available || 0);
221
+ return {
222
+ required: req,
223
+ available: avail,
224
+ gap: Math.max(0, req - avail)
225
+ };
226
+ };
227
+
228
+ exports.calcShortage = calcShortage;
229
+
230
+ const calcAllShortages = (totalCost, resources, useitems, equips) => {
231
+ const resourcesArr = Array.isArray(resources) ? resources : [];
232
+ const shortages = {
233
+ ammo: calcShortage(totalCost.ammo, resourcesArr[RESOURCE_INDEX.ammo]),
234
+ steel: calcShortage(totalCost.steel, resourcesArr[RESOURCE_INDEX.steel]),
235
+ devmat: calcShortage(totalCost.consumable[KAISOU_ITEM_ID.devkit] || 0, resourcesArr[RESOURCE_INDEX.devmat]),
236
+ buildkit: calcShortage(totalCost.consumable[KAISOU_ITEM_ID.buildkit] || 0, resourcesArr[RESOURCE_INDEX.buildkit]),
237
+ consumable: {},
238
+ equipment: {}
239
+ };
240
+ Object.entries(totalCost.consumable || {}).forEach(([itemId, required]) => {
241
+ const available = _lodash.default.get(useitems, [itemId, 'api_count'], 0);
242
+
243
+ shortages.consumable[itemId] = calcShortage(required, available);
244
+ });
245
+ Object.entries(totalCost.equipment || {}).forEach(([equipId, required]) => {
246
+ const available = _lodash.default.get(equips, [equipId, 'length'], 0);
247
+
248
+ shortages.equipment[equipId] = calcShortage(required, available);
249
+ });
250
+ return shortages;
251
+ };
252
+
253
+ exports.calcAllShortages = calcAllShortages;
254
+
255
+ const getTotalShortageCount = shortages => {
256
+ var _shortages$ammo, _shortages$steel, _shortages$devmat, _shortages$buildkit;
257
+
258
+ let count = 0;
259
+ if (((_shortages$ammo = shortages.ammo) === null || _shortages$ammo === void 0 ? void 0 : _shortages$ammo.gap) > 0) count++;
260
+ if (((_shortages$steel = shortages.steel) === null || _shortages$steel === void 0 ? void 0 : _shortages$steel.gap) > 0) count++;
261
+ if (((_shortages$devmat = shortages.devmat) === null || _shortages$devmat === void 0 ? void 0 : _shortages$devmat.gap) > 0) count++;
262
+ if (((_shortages$buildkit = shortages.buildkit) === null || _shortages$buildkit === void 0 ? void 0 : _shortages$buildkit.gap) > 0) count++;
263
+ Object.values(shortages.consumable || {}).forEach(s => {
264
+ if (s.gap > 0) count++;
265
+ });
266
+ return count;
267
+ };
268
+
269
+ exports.getTotalShortageCount = getTotalShortageCount;
@@ -5,8 +5,6 @@ exports.default = void 0;
5
5
 
6
6
  var _react = _interopRequireWildcard(require("react"));
7
7
 
8
- var _reactBootstrap = require("react-bootstrap");
9
-
10
8
  var _core = require("@blueprintjs/core");
11
9
 
12
10
  var _select = require("@blueprintjs/select");
@@ -33,92 +31,38 @@ const {
33
31
  __
34
32
  } = window.i18n['poi-plugin-leveling-plan'];
35
33
 
36
- const MapMultiSelect = _select.MultiSelect.ofType(); // 海图选择器组件
34
+ const MapMultiSelect = _select.MultiSelect.ofType(); // 按世界分组
35
+
37
36
 
37
+ const getWorldGroups = () => {
38
+ const groups = {};
39
+ Object.keys(_constants.EXP_BY_POI_DB).sort((a, b) => Number(a) - Number(b)).forEach(id => {
40
+ const world = Math.floor(Number(id) / 10);
41
+ if (!groups[world]) groups[world] = [];
42
+ groups[world].push(id);
43
+ });
44
+ return groups;
45
+ };
38
46
 
39
47
  class MapSelector extends _react.Component {
40
48
  constructor(props) {
41
49
  super(props);
42
- Object.defineProperty(this, "toggleMap", {
43
- configurable: true,
44
- enumerable: true,
45
- writable: true,
46
- value: mapId => {
47
- const {
48
- value = [],
49
- onChange
50
- } = this.props;
51
-
52
- if (value.includes(mapId)) {
53
- // 取消选择
54
- onChange(value.filter(id => id !== mapId));
55
- } else {
56
- // 添加选择
57
- onChange([...value, mapId]);
58
- }
59
- }
60
- });
61
- Object.defineProperty(this, "handleItemSelect", {
62
- configurable: true,
63
- enumerable: true,
64
- writable: true,
65
- value: mapId => {
66
- this.toggleMap(mapId);
67
- }
68
- });
69
- Object.defineProperty(this, "handleTagRemove", {
70
- configurable: true,
71
- enumerable: true,
72
- writable: true,
73
- value: mapId => {
74
- const {
75
- value = [],
76
- onChange
77
- } = this.props;
78
- onChange(value.filter(id => id !== mapId));
79
- }
80
- });
81
- Object.defineProperty(this, "renderMap", {
82
- configurable: true,
83
- enumerable: true,
84
- writable: true,
85
- value: (mapId, {
86
- handleClick,
87
- modifiers
88
- }) => {
89
- const {
90
- value = []
91
- } = this.props;
92
- const isSelected = value.includes(mapId);
93
- return _react.default.createElement(_core.MenuItem, {
94
- key: mapId,
95
- text: (0, _planHelpers.formatMapName)(mapId),
96
- onClick: handleClick,
97
- active: modifiers.active,
98
- shouldDismissPopover: false,
99
- icon: isSelected ? 'tick' : 'blank'
100
- });
101
- }
102
- });
103
- Object.defineProperty(this, "renderTag", {
104
- configurable: true,
105
- enumerable: true,
106
- writable: true,
107
- value: mapId => {
108
- return (0, _planHelpers.formatMapName)(mapId);
109
- }
110
- });
50
+
51
+ _initialiseProps.call(this);
52
+
111
53
  this.state = {
112
- isOpen: false
54
+ isOpen: false,
55
+ activeWorld: null
113
56
  };
57
+ this.worldGroups = getWorldGroups();
58
+ const worlds = Object.keys(this.worldGroups).sort((a, b) => Number(a) - Number(b));
59
+ this.state.activeWorld = worlds[0] || null;
114
60
  }
115
61
 
116
62
  render() {
117
63
  const {
118
- value = [],
119
- mapExpData
120
- } = this.props; // 所有海图
121
-
64
+ value = []
65
+ } = this.props;
122
66
  const allMapIds = Object.keys(_constants.EXP_BY_POI_DB);
123
67
  return _react.default.createElement("div", {
124
68
  className: "map-selector"
@@ -128,10 +72,8 @@ class MapSelector extends _react.Component {
128
72
  items: allMapIds,
129
73
  selectedItems: value.filter(id => allMapIds.includes(id)),
130
74
  onItemSelect: this.handleItemSelect,
131
- itemRenderer: this.renderMap,
132
- onClick: () => this.setState({
133
- isOpen: !this.state.isOpen
134
- }),
75
+ itemRenderer: () => null,
76
+ itemListRenderer: () => this.renderPopoverContent(),
135
77
  tagRenderer: this.renderTag,
136
78
  tagInputProps: {
137
79
  onRemove: this.handleTagRemove,
@@ -147,20 +89,112 @@ class MapSelector extends _react.Component {
147
89
  popoverProps: {
148
90
  minimal: true,
149
91
  usePortal: false,
150
- isOpen: this.state.isOpen
92
+ isOpen: this.state.isOpen,
93
+ onClose: () => this.setState({
94
+ isOpen: false
95
+ }),
96
+ popoverClassName: 'map-selector-popover'
151
97
  }
152
98
  })));
153
99
  }
154
100
 
155
- } // Redux 连接
101
+ }
102
+
103
+ var _initialiseProps = function () {
104
+ Object.defineProperty(this, "toggleMap", {
105
+ configurable: true,
106
+ enumerable: true,
107
+ writable: true,
108
+ value: mapId => {
109
+ const {
110
+ value = [],
111
+ onChange
112
+ } = this.props;
156
113
 
114
+ if (value.includes(mapId)) {
115
+ onChange(value.filter(id => id !== mapId));
116
+ } else {
117
+ onChange([...value, mapId]);
118
+ }
119
+ }
120
+ });
121
+ Object.defineProperty(this, "handleItemSelect", {
122
+ configurable: true,
123
+ enumerable: true,
124
+ writable: true,
125
+ value: mapId => {
126
+ this.toggleMap(mapId);
127
+ }
128
+ });
129
+ Object.defineProperty(this, "handleTagRemove", {
130
+ configurable: true,
131
+ enumerable: true,
132
+ writable: true,
133
+ value: mapId => {
134
+ const {
135
+ value = [],
136
+ onChange
137
+ } = this.props;
138
+ onChange(value.filter(id => id !== mapId));
139
+ }
140
+ });
141
+ Object.defineProperty(this, "renderTag", {
142
+ configurable: true,
143
+ enumerable: true,
144
+ writable: true,
145
+ value: mapId => {
146
+ return (0, _planHelpers.formatMapName)(mapId);
147
+ }
148
+ });
149
+ Object.defineProperty(this, "renderPopoverContent", {
150
+ configurable: true,
151
+ enumerable: true,
152
+ writable: true,
153
+ value: () => {
154
+ const {
155
+ value = []
156
+ } = this.props;
157
+ const {
158
+ activeWorld
159
+ } = this.state;
160
+ const worlds = Object.keys(this.worldGroups).sort((a, b) => Number(a) - Number(b));
161
+ return _react.default.createElement("div", {
162
+ className: "map-selector-tabs"
163
+ }, _react.default.createElement(_core.Tabs, {
164
+ id: "map-world-tabs",
165
+ selectedTabId: activeWorld,
166
+ onChange: id => this.setState({
167
+ activeWorld: id
168
+ }),
169
+ renderActiveTabPanelOnly: true,
170
+ vertical: true
171
+ }, worlds.map(world => _react.default.createElement(_core.Tab, {
172
+ key: world,
173
+ id: world,
174
+ title: `${world}`,
175
+ panel: _react.default.createElement("div", {
176
+ className: "map-selector-tab-panel"
177
+ }, this.worldGroups[world].map(mapId => {
178
+ const isSelected = value.includes(mapId);
179
+ return _react.default.createElement(_core.MenuItem, {
180
+ key: mapId,
181
+ text: (0, _planHelpers.formatMapName)(mapId),
182
+ icon: isSelected ? 'tick' : 'blank',
183
+ onClick: () => this.toggleMap(mapId),
184
+ shouldDismissPopover: false
185
+ });
186
+ }))
187
+ }))));
188
+ }
189
+ });
190
+ };
157
191
 
158
192
  const mapStateToProps = (0, _reselect.createSelector)([_selectors.personalStatsSelector], personalStats => {
159
- // 获取所有海图的经验数据
160
193
  const allMapIds = Object.keys(_constants.EXP_BY_POI_DB);
161
194
  const mapExpData = {};
162
195
  allMapIds.forEach(mapId => {
163
- mapExpData[mapId] = (0, _expCalculator.getMapExp)(mapId, personalStats, 30);
196
+ const result = (0, _expCalculator.getMapExp)(mapId, personalStats, 30);
197
+ mapExpData[mapId] = result.exp || 0;
164
198
  });
165
199
  return {
166
200
  mapExpData
@@ -21,6 +21,8 @@ var _selectors = require("../../utils/selectors");
21
21
 
22
22
  var _planHelpers = require("../../utils/plan-helpers");
23
23
 
24
+ var _kaisouCost = require("../../utils/kaisou-cost");
25
+
24
26
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
27
 
26
28
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
@@ -96,7 +98,35 @@ class PlanForm extends _react.Component {
96
98
  min: currentLevel + 1,
97
99
  max: 185,
98
100
  placeholder: __('Enter target level')
99
- }), selectedShip && _react.default.createElement("p", {
101
+ }), selectedShip && $ships && (() => {
102
+ const shipMasterId = selectedShip.api_ship_id;
103
+ const remodelLevels = (0, _kaisouCost.getRemodelLevelsForShip)(shipMasterId, $ships);
104
+ const startLv = parseInt(startLevel) || 0;
105
+ const filteredLevels = remodelLevels.filter(lv => lv > startLv);
106
+ if (filteredLevels.length === 0) return null;
107
+ return _react.default.createElement("div", {
108
+ className: "remodel-level-tags",
109
+ style: {
110
+ marginBottom: 8,
111
+ display: 'flex',
112
+ flexWrap: 'wrap',
113
+ gap: 5
114
+ }
115
+ }, filteredLevels.map(lv => _react.default.createElement("span", {
116
+ key: lv,
117
+ onClick: () => this.setState({
118
+ targetLevel: String(lv)
119
+ }),
120
+ style: {
121
+ cursor: 'pointer',
122
+ padding: '2px 8px',
123
+ backgroundColor: parseInt(targetLevel) === lv ? '#337ab7' : '#f0f0f0',
124
+ color: parseInt(targetLevel) === lv ? 'white' : '#333',
125
+ borderRadius: 3,
126
+ fontSize: 12
127
+ }
128
+ }, "lv", lv)));
129
+ })(), selectedShip && _react.default.createElement("p", {
100
130
  className: "help-block"
101
131
  }, __('Current level'), ": ", currentLevel)), _react.default.createElement(_reactBootstrap.FormGroup, null, _react.default.createElement(_reactBootstrap.ControlLabel, null, __('Maps')), _react.default.createElement(_mapSelector.default, {
102
132
  value: maps,
@@ -7,24 +7,109 @@ var _react = _interopRequireDefault(require("react"));
7
7
 
8
8
  var _reactBootstrap = require("react-bootstrap");
9
9
 
10
- var _reactRedux = require("react-redux");
10
+ var _icon = require("views/components/etc/icon");
11
11
 
12
- var _reselect = require("reselect");
12
+ var _useitemIcon = require("./useitem-icon");
13
+
14
+ var _kaisouCost = require("../../utils/kaisou-cost");
15
+
16
+ var _lodash = _interopRequireDefault(require("lodash"));
13
17
 
14
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
19
 
16
20
  const {
17
21
  __
18
- } = window.i18n['poi-plugin-leveling-plan']; // 单个计划卡片组件
22
+ } = window.i18n['poi-plugin-leveling-plan'];
23
+ const {
24
+ __: __r
25
+ } = window.i18n.resources;
26
+
27
+ const RemodelCostDisplay = ({
28
+ cost,
29
+ resources,
30
+ useitems,
31
+ $useitems
32
+ }) => {
33
+ var _shortages$ammo, _shortages$steel;
34
+
35
+ if (!cost || cost.ammo === 0 && cost.steel === 0 && Object.keys(cost.consumable).length === 0) {
36
+ return _react.default.createElement("span", {
37
+ style: {
38
+ opacity: 0.5
39
+ }
40
+ }, __('No remodel required'));
41
+ }
42
+
43
+ const shortages = (0, _kaisouCost.calcAllShortages)(cost, resources, useitems || {}, {});
44
+ return _react.default.createElement("span", {
45
+ style: {
46
+ textAlign: 'right',
47
+ fontSize: '0.9em'
48
+ }
49
+ }, _react.default.createElement("span", {
50
+ style: {
51
+ display: 'inline-flex',
52
+ alignItems: 'center',
53
+ gap: '4px',
54
+ flexWrap: 'wrap'
55
+ }
56
+ }, cost.ammo > 0 && _react.default.createElement("span", null, _react.default.createElement(_icon.MaterialIcon, {
57
+ materialId: 2,
58
+ className: "material-icon-sm"
59
+ }), cost.ammo.toLocaleString(), ((_shortages$ammo = shortages.ammo) === null || _shortages$ammo === void 0 ? void 0 : _shortages$ammo.gap) > 0 && _react.default.createElement("span", {
60
+ style: {
61
+ color: '#d9534f'
62
+ }
63
+ }, "(-", shortages.ammo.gap.toLocaleString(), ")")), cost.steel > 0 && _react.default.createElement("span", null, _react.default.createElement(_icon.MaterialIcon, {
64
+ materialId: 3,
65
+ className: "material-icon-sm"
66
+ }), cost.steel.toLocaleString(), ((_shortages$steel = shortages.steel) === null || _shortages$steel === void 0 ? void 0 : _shortages$steel.gap) > 0 && _react.default.createElement("span", {
67
+ style: {
68
+ color: '#d9534f'
69
+ }
70
+ }, "(-", shortages.steel.gap.toLocaleString(), ")")), Object.keys(cost.consumable || {}).length > 0 && Object.entries(cost.consumable).map(([itemId, count]) => {
71
+ const shortage = _lodash.default.get(shortages, ['consumable', itemId, 'gap'], 0);
72
+
73
+ const numId = Number(itemId); // 建造资材(2) materialId=4,开发资材(3) materialId=6
74
+
75
+ const isMaterial = numId === 2 || numId === 3;
76
+ const materialId = numId === 2 ? 4 : 6;
77
+ return _react.default.createElement("span", {
78
+ key: itemId,
79
+ style: {
80
+ fontSize: '0.85em',
81
+ display: 'inline-flex',
82
+ alignItems: 'center',
83
+ gap: 2
84
+ }
85
+ }, isMaterial ? _react.default.createElement(_icon.MaterialIcon, {
86
+ materialId: materialId,
87
+ className: "material-icon-sm"
88
+ }) : _react.default.createElement(_useitemIcon.UseitemIcon, {
89
+ useitemId: numId,
90
+ className: "useitem-icon-sm"
91
+ }), count, shortage > 0 && _react.default.createElement("span", {
92
+ style: {
93
+ color: '#d9534f'
94
+ }
95
+ }, "(-", shortage, ")"));
96
+ })));
97
+ }; // 单个计划卡片组件
98
+
19
99
 
20
100
  const PlanItem = ({
21
101
  planDetail,
22
102
  onEdit,
23
103
  onDelete,
24
- onComplete
104
+ onComplete,
105
+ $ships,
106
+ resources,
107
+ useitems,
108
+ $useitems
25
109
  }) => {
26
110
  if (!planDetail) return null;
27
111
  const {
112
+ shipMasterId,
28
113
  shipName,
29
114
  startLv,
30
115
  currentLv,
@@ -37,7 +122,8 @@ const PlanItem = ({
37
122
  notes,
38
123
  completed
39
124
  } = planDetail;
40
- console.log(planDetail);
125
+ const fromLevel = startLv === undefined ? currentLv : startLv;
126
+ const remodelCost = $ships && shipMasterId && fromLevel && targetLv ? (0, _kaisouCost.getShipRemodelCost)(shipMasterId, fromLevel, targetLv, $ships) : null;
41
127
  return _react.default.createElement(_reactBootstrap.Panel, {
42
128
  className: "plan-item"
43
129
  }, _react.default.createElement(_reactBootstrap.Panel.Heading, null, _react.default.createElement("div", {
@@ -74,7 +160,16 @@ const PlanItem = ({
74
160
  className: "exp-info"
75
161
  }, __('Current EXP'), ": ", currentExp.toLocaleString(), " / ", targetTotalExp.toLocaleString()), _react.default.createElement("div", {
76
162
  className: "exp-info"
77
- }, __('Required EXP'), ": ", requiredExp.toLocaleString())), _react.default.createElement("div", {
163
+ }, __('Required EXP'), ": ", requiredExp.toLocaleString(), remodelCost && _react.default.createElement("span", {
164
+ style: {
165
+ marginLeft: 15
166
+ }
167
+ }, _react.default.createElement(RemodelCostDisplay, {
168
+ cost: remodelCost,
169
+ resources: resources,
170
+ useitems: useitems,
171
+ $useitems: $useitems
172
+ })))), _react.default.createElement("div", {
78
173
  className: "maps-section"
79
174
  }, _react.default.createElement("div", {
80
175
  className: "maps-label"