Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
### 已变更

- 修复领域数据自动更新中“天气过期”判定读取错误字段,天气有效期结束后会在每分钟检查时触发刷新。
- 合同高价规则入口改名为“二次确认设置”;入库页面没有合同时也显示设置按钮。
- 二次确认设置默认全局规则为 `-0`,未自定义时合同价格高于 MP 即触发二次确认。

## [1.33.2] - 2026-08-11

Expand Down
219 changes: 134 additions & 85 deletions src/features/incomingContractsHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,8 @@ const { SCXXCS, PROFIT_PER_BUILDING_LEVEL, RETAIL_ADJUSTMENT } = state;
insertWarningNotice();
processAllCards([...contractCards]);
startMutationObserver();
} else {
insertWarningNotice();
}
}, 500);
}
Expand Down Expand Up @@ -1212,10 +1214,138 @@ const { SCXXCS, PROFIT_PER_BUILDING_LEVEL, RETAIL_ADJUSTMENT } = state;
injectHourlyProfitLegacy(card, profitValue, mpPercent, mpValue, mpNotes);
}

function getReactFiberFromElement(el) {
const key = Object.keys(el).find(k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$'));
return key ? el[key] : null;
}

function getHostNodeFromFiber(fiber) {
const queue = [fiber];
while (queue.length) {
const node = queue.pop();
if (!node) continue;
if (node.stateNode instanceof Element) return node.stateNode;
if (node.sibling) queue.push(node.sibling);
if (node.child) queue.push(node.child);
}
return null;
}

function getIncomingContractsRoot() {
const page = document.getElementById('page');
if (!page) return null;

for (const el of page.querySelectorAll('div')) {
const fiber = getReactFiberFromElement(el);
if (!fiber) continue;

let node = fiber;
while (node) {
const props = node.memoizedProps;
if (props && props.incoming === true && Object.prototype.hasOwnProperty.call(props, 'currentContracts')) {
return getHostNodeFromFiber(node);
}
node = node.return;
}
}
return null;
}

function createWarningNotice() {
const isNarrow8 = window.innerWidth <= 576;
const d8 = DM();
const tip = document.createElement('div');
tip.style.cssText = `
display: flex;
flex-wrap: wrap;
align-items: center;
gap: ${isNarrow8 ? '6px 8px' : '8px'};
color: ${d8 ? '#aaa' : '#777'};
font-size: ${isNarrow8 ? '11px' : '13px'};
width: 100%;
`;
tip.dataset.warningText = 'true';

// 1. 插入文本提示
const textSpan = document.createElement('span');
textSpan.textContent = '自动更新数据有延迟,左下可手动更新';
textSpan.style.cssText = `
white-space: ${isNarrow8 ? 'normal' : 'nowrap'};
flex: ${isNarrow8 ? '1 1 100%' : '0 0 auto'};
`;
tip.appendChild(textSpan);

// 2. 按钮组容器
const btnGroup = document.createElement('div');
btnGroup.style.cssText = `
display: flex;
flex-wrap: wrap;
align-items: center;
gap: ${isNarrow8 ? '4px 6px' : '6px'};
flex: 1 1 auto;
`;

// 2a. 开关按钮
const toggle = createGlobalCustomToggle(
'executiveCustomToggle',
'自定义',
{ buttonClass: 'btn btn-primary' },
(isEnabled) => {
refreshAllContractProfits();
}
);
toggle.wrapper.style.marginLeft = "0";
btnGroup.appendChild(toggle.wrapper);

// 2b. 自定义数据功能按钮
const customBtn = document.createElement('button');
customBtn.type = 'button';
customBtn.textContent = '自定义高管数据';
customBtn.style.cssText = `
padding: 4px 10px; background: #2196f3;
color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;
font-weight: bold; white-space: nowrap; flex-shrink: 0;
`;
customBtn.onclick = () => executiveCustomButton.show();
btnGroup.appendChild(customBtn);

// 2c. 显示更多信息开关按钮
const marketToggle = createGlobalCustomToggle(
'marketMaxProfitToggle',
'显示更多',
{},
() => {
refreshAllContractProfits();
}
);
marketToggle.wrapper.style.marginLeft = "0";
btnGroup.appendChild(marketToggle.wrapper);

// 2d. 二次确认设置按钮
const priceSetBtn = document.createElement('button');
priceSetBtn.type = 'button';
priceSetBtn.textContent = '二次确认设置';
priceSetBtn.style.cssText = `
padding: 4px 10px; background: #9c27b0;
color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;
font-weight: bold; white-space: nowrap; flex-shrink: 0;
`;
priceSetBtn.onclick = () => showContractPriceModal();
btnGroup.appendChild(priceSetBtn);

tip.appendChild(btnGroup);
return tip;
}

function insertWarningNotice() {
if (document.querySelector('[data-warning-text]')) return;

const cards = document.querySelectorAll('div[tabindex="0"]');
if (cards.length === 0) {
const root = getIncomingContractsRoot();
if (root) root.insertBefore(createWarningNotice(), root.firstChild);
return;
}

cards.forEach(card => {
let parent = card.parentElement;
Expand All @@ -1227,88 +1357,7 @@ const { SCXXCS, PROFIT_PER_BUILDING_LEVEL, RETAIL_ADJUSTMENT } = state;
const insertTarget = grandParent.firstElementChild;
if (!insertTarget || insertTarget === parent) return;

const isNarrow8 = window.innerWidth <= 576;
const d8 = DM();
const tip = document.createElement('div');
tip.style.cssText = `
display: flex;
flex-wrap: wrap;
align-items: center;
gap: ${isNarrow8 ? '6px 8px' : '8px'};
color: ${d8 ? '#aaa' : '#777'};
font-size: ${isNarrow8 ? '11px' : '13px'};
width: 100%;
`;
tip.dataset.warningText = 'true';

// 1. 插入文本提示
const textSpan = document.createElement('span');
textSpan.textContent = '自动更新数据有延迟,左下可手动更新';
textSpan.style.cssText = `
white-space: ${isNarrow8 ? 'normal' : 'nowrap'};
flex: ${isNarrow8 ? '1 1 100%' : '0 0 auto'};
`;
tip.appendChild(textSpan);

// 2. 按钮组容器
const btnGroup = document.createElement('div');
btnGroup.style.cssText = `
display: flex;
flex-wrap: wrap;
align-items: center;
gap: ${isNarrow8 ? '4px 6px' : '6px'};
flex: 1 1 auto;
`;

// 2a. 开关按钮
const toggle = createGlobalCustomToggle(
'executiveCustomToggle',
'自定义',
{ buttonClass: 'btn btn-primary' },
(isEnabled) => {
refreshAllContractProfits();
}
);
toggle.wrapper.style.marginLeft = "0";
btnGroup.appendChild(toggle.wrapper);

// 2b. 自定义数据功能按钮
const customBtn = document.createElement('button');
customBtn.type = 'button';
customBtn.textContent = '自定义高管数据';
customBtn.style.cssText = `
padding: 4px 10px; background: #2196f3;
color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;
font-weight: bold; white-space: nowrap; flex-shrink: 0;
`;
customBtn.onclick = () => executiveCustomButton.show();
btnGroup.appendChild(customBtn);

// 2c. 显示更多信息开关按钮
const marketToggle = createGlobalCustomToggle(
'marketMaxProfitToggle',
'显示更多',
{},
() => {
refreshAllContractProfits();
}
);
marketToggle.wrapper.style.marginLeft = "0";
btnGroup.appendChild(marketToggle.wrapper);

// 2d. 预期价格设置按钮
const priceSetBtn = document.createElement('button');
priceSetBtn.type = 'button';
priceSetBtn.textContent = '预期价格';
priceSetBtn.style.cssText = `
padding: 4px 10px; background: #9c27b0;
color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;
font-weight: bold; white-space: nowrap; flex-shrink: 0;
`;
priceSetBtn.onclick = () => showContractPriceModal();
btnGroup.appendChild(priceSetBtn);

tip.appendChild(btnGroup);
const tip = createWarningNotice();

insertTarget.appendChild(tip);
});
Expand All @@ -1325,7 +1374,7 @@ const { SCXXCS, PROFIT_PER_BUILDING_LEVEL, RETAIL_ADJUSTMENT } = state;
const EXCLUDED_IDS = [91, 94, 95, 96, 97, 99];

function getParsedRules() {
const settings = JSON.parse(localStorage.getItem('SC_Contract_HighPrice_Settings') || '{"global":"","individual":""}');
const settings = JSON.parse(localStorage.getItem('SC_Contract_HighPrice_Settings') || '{"global":"-0","individual":""}');
const parsed = {
global: null,
individual: new Map()
Expand Down Expand Up @@ -1541,7 +1590,7 @@ const { SCXXCS, PROFIT_PER_BUILDING_LEVEL, RETAIL_ADJUSTMENT } = state;

wrapper.innerHTML = `
<div style="padding: 12px 20px; background: #9c27b0; color: white; display: flex; justify-content: space-between; align-items: center; user-select: none; font-weight: bold; font-size: 15px;">
<span>合同预期价格设置</span>
<span>合同二次确认设置</span>
<span id="sc-contract-price-close" style="cursor: pointer; font-size: 20px; font-weight: normal; line-height: 1;">&times;</span>
</div>
<div style="padding: 20px; overflow-y: auto; display: flex; flex-direction: column; gap: 15px;">
Expand Down Expand Up @@ -1641,7 +1690,7 @@ const { SCXXCS, PROFIT_PER_BUILDING_LEVEL, RETAIL_ADJUSTMENT } = state;
}

// 初始化规则列表
const settings = JSON.parse(localStorage.getItem('SC_Contract_HighPrice_Settings') || '{"global":"","individual":""}');
const settings = JSON.parse(localStorage.getItem('SC_Contract_HighPrice_Settings') || '{"global":"-0","individual":""}');
document.getElementById('sc-contract-global-val').value = settings.global || '';

const lines = (settings.individual || '').split('\n');
Expand Down
Loading