修改备注没有带入的问题
This commit is contained in:
1 parent
c2c71d35af
commit
2f0e6582d5
25 files changed
+5104
-30
No files matched your search
@@ -11,9 +11,14 @@ Chrome Manifest V3 扩展,在用户已登录的 LTJT ERP 页面内执行经过
|
||||
|
||||
## 当前版本
|
||||
|
||||
当前源码版本为 `0.5.190`。版本化 ZIP、文件哈希和 Skill/DOCX 基线见 [`../../dist/release-manifest.json`](../../dist/release-manifest.json)。旧版本实现流水已冻结在 [`../../archive/project-history/2026-08-16/chrome-extension-README.pre-governance.md`](../../archive/project-history/2026-08-16/chrome-extension-README.pre-governance.md)。
|
||||
当前源码版本为 `0.5.191`。版本化 ZIP、文件哈希和 Skill/DOCX 基线见 [`../../dist/release-manifest.json`](../../dist/release-manifest.json)。旧版本实现流水已冻结在 [`../../archive/project-history/2026-08-16/chrome-extension-README.pre-governance.md`](../../archive/project-history/2026-08-16/chrome-extension-README.pre-governance.md)。
|
||||
|
||||
0.5.190 当前重点:
|
||||
0.5.191 当前重点:
|
||||
|
||||
- 酒店新增未填备注时保留选中酒店原生联动备注,明确填写时使用用户备注;在资源选择后、日期/数量回调前冻结,保存前校验及写后回查均验证。默认备注回查使用 v2 证据,旧 v1 回查保持兼容。单条与批量逐条适用;变更未填备注仍保留原记录。仅本地合成验证,真实 ERP 验收待部署方完成。
|
||||
- 需更新插件和平台最低版本至 0.5.191 并刷新平台/ERP 页面;无新增数据库迁移。
|
||||
|
||||
继续保留 0.5.190 的同团批量酒店新增:
|
||||
|
||||
- 同团 2—10 条酒店新增由程序解析为批量信封,插件按输入顺序复用单条原生保存/回查;首次失败或不确定即停止,逐条保存成功前缀、失败/待核验项与未执行项。每条确认成功才进入账号隔离的安排账本和团队进度;整批成功回执包含逐条结果及当前安排。只读回查只核验不确定项,不自动继续剩余安排。禁止跨团、混合动作、批量变更、整批自动重试。
|
||||
- 需同步更新控制面、平台和插件 0.5.190,无新增数据库迁移。单条输入及原生资源匹配规则保持;本地合成验证通过,真实 ERP 验收待部署方完成。
|
||||
|
||||
@@ -6677,7 +6677,7 @@
|
||||
}
|
||||
|
||||
window.LTJTOrderAssistant = {
|
||||
version: '0.5.190',
|
||||
version: '0.5.191',
|
||||
resolveNativeListSearchValues,
|
||||
lookupKeywordMatchesText,
|
||||
inspectLifecycleSearchCriteria: lifecycleSearchCriteria,
|
||||
|
||||
@@ -651,6 +651,13 @@
|
||||
return sha256(JSON.stringify([operation.action, operation.data.existing_refs, arrangement]));
|
||||
}
|
||||
|
||||
function usesNativeHotelRemark(operation) {
|
||||
// Public input only permits a nonempty explicit remark. Resolution also
|
||||
// normalizes an omitted remark to '', so both forms mean inherit here.
|
||||
return operation.action === 'arrangement_hotel' && operation.data?.arrangement?.mode === 'create'
|
||||
&& !normalize(operation.data.arrangement.remark);
|
||||
}
|
||||
|
||||
async function arrangementCreateEvidence(form, operation) {
|
||||
const rows = [];
|
||||
for (const index of arrangementRowIndexes(form)) {
|
||||
@@ -660,7 +667,7 @@
|
||||
const preserved = createPreservedFields(form, operation);
|
||||
const preservedProof = await Promise.all(preserved.map(async (field) => ({ name: field.name, date: Boolean(field.date),
|
||||
sha256: await sha256(field.date ? dateYyyyMD(field.expected) : normalize(field.expected)) })));
|
||||
return { version: 1, slot_index: operation.data.arrangement.target.slot_index,
|
||||
return { version: usesNativeHotelRemark(operation) ? 2 : 1, slot_index: operation.data.arrangement.target.slot_index,
|
||||
operation_key: await arrangementCreateOperationKey(operation), existing_rows: rows,
|
||||
...(operation.action === 'arrangement_other' ? { preserved_fields: preservedProof } : {}), value_redacted: true };
|
||||
}
|
||||
@@ -2318,11 +2325,13 @@
|
||||
}
|
||||
const linkedFields = ['danwei0', 'danweiid0', 'fangxing0', 'diqu0', 'dianhua0', 'bizhong0', 'danjia0', 'fangshi0'].map((name) => arrangementFieldName(operation, name));
|
||||
const before = Object.fromEntries(linkedFields.map((name) => [name, controlValue(getControl(form, name))]));
|
||||
let nativeRemark;
|
||||
try {
|
||||
// SetValToObj is the same ERP-native mapping used by a real hotel-row
|
||||
// click. It fills the read-only room type and all linked fields.
|
||||
selectBox.SetVal = setVal;
|
||||
selectBox.SetValToObj(selected.candidate.raw || selected.candidate.row.join('◆'));
|
||||
nativeRemark = controlValue(getArrangementControl(form, operation, 'beizhu0'));
|
||||
dispatchNativeFieldEvents(control);
|
||||
} catch (error) {
|
||||
blockers.push(`arrangement_hotel_native_selectbox_failed:${error?.message || String(error)}`);
|
||||
@@ -2340,7 +2349,7 @@
|
||||
linked_fields_changed: linkedFields.filter((name) => before[name] !== after[name]),
|
||||
value_redacted: true
|
||||
});
|
||||
return selected;
|
||||
return { ...selected, nativeRemark };
|
||||
}
|
||||
|
||||
function applyNativeSettlementSelection(form, supplier, changes, blockers, action = 'arrangement_transport', operation = {}) {
|
||||
@@ -2793,9 +2802,18 @@
|
||||
const preserved = createPreservedFields(form, operation);
|
||||
const field = (name) => arrangementFieldName(operation, name);
|
||||
const action = operation.action;
|
||||
if (action === 'arrangement_hotel') applyNativeHotelSelection(form, value.resource, changes, blockers, operation);
|
||||
let hotelSelection;
|
||||
if (action === 'arrangement_hotel') hotelSelection = applyNativeHotelSelection(form, value.resource, changes, blockers, operation);
|
||||
else applyNativeSettlementSelection(form, value.supplier, changes, blockers, action, operation);
|
||||
if (blockers.length) return { changes, blockers, arrangementSlot: slot };
|
||||
// Freeze the selected resource's note before date/quantity callbacks can
|
||||
// clear it. Never inherit another existing row or read it back after save.
|
||||
const nativeRemark = usesNativeHotelRemark(operation)
|
||||
? hotelSelection.nativeRemark : undefined;
|
||||
const effectiveRemark = nativeRemark ?? value.remark;
|
||||
const projectionOperation = nativeRemark === undefined ? operation : {
|
||||
...operation, data: { ...operation.data, arrangement: { ...value, remark: effectiveRemark } }
|
||||
};
|
||||
if (action === 'arrangement_hotel' || action === 'arrangement_vehicle') {
|
||||
applyExact(form, field('riqi0'), 'set', value.start_date, changes, blockers);
|
||||
applyExact(form, field('riqis0'), 'set', value.end_date, changes, blockers);
|
||||
@@ -2820,15 +2838,16 @@
|
||||
// Native date/room callbacks may reset status and remark. Set and assert
|
||||
// the requested final values only after those callbacks have settled.
|
||||
applyExact(form, field('zt0'), 'set', value.status, changes, blockers, { optional: action === 'arrangement_other' });
|
||||
applyExact(form, field('beizhu0'), 'set', value.remark, changes, blockers);
|
||||
applyExact(form, field('beizhu0'), 'set', effectiveRemark, changes, blockers);
|
||||
if (action === 'arrangement_other') {
|
||||
for (const [key, name] of Object.entries({ number: 'beianhao', date: 'beianri', entry_port: 'rujingkou', exit_port: 'chujingkou' })) {
|
||||
if (value.filing?.[key] !== undefined) applyExact(form, name, 'set', value.filing[key], changes, blockers);
|
||||
}
|
||||
}
|
||||
const writeGuard = () => arrangementCreateWriteGuard(form, operation, signature, controls, preserved);
|
||||
const writeGuard = () => arrangementCreateWriteGuard(form, projectionOperation, signature, controls, preserved);
|
||||
blockers.push(...writeGuard());
|
||||
return { changes, blockers, arrangementSlot: slot, writeGuard, linkageWait };
|
||||
return { changes, blockers, arrangementSlot: slot, writeGuard, linkageWait,
|
||||
...(nativeRemark !== undefined ? { nativeRemarkSha256: await sha256(normalize(nativeRemark)) } : {}) };
|
||||
}
|
||||
|
||||
async function applyArrangement(form, operation) {
|
||||
@@ -4077,7 +4096,7 @@
|
||||
|
||||
async function indexedCreateRequeryProjection(form, operation, proof) {
|
||||
const blockers = [];
|
||||
if (!proof || proof.version !== 1 || !Array.isArray(proof.existing_rows)
|
||||
if (!proof || ![1, 2].includes(proof.version) || !Array.isArray(proof.existing_rows)
|
||||
|| !Number.isInteger(proof.slot_index) || proof.slot_index < 0
|
||||
|| proof.operation_key !== await arrangementCreateOperationKey(operation)) {
|
||||
return { fields: [], blockers: ['arrangement_create_before_evidence_missing_or_mismatched'], operation };
|
||||
@@ -4097,6 +4116,16 @@
|
||||
if (newRows.length !== 1) blockers.push(`arrangement_create_new_row_count:${newRows.length}`);
|
||||
if (blockers.length) return { fields: [], blockers: [...new Set(blockers)], operation };
|
||||
const projectedOperation = arrangementCreateAtSlot(operation, newRows[0]);
|
||||
if (proof.version === 2) {
|
||||
if (!usesNativeHotelRemark(operation) || !/^(?:[a-f0-9]{64}|fallback-[a-f0-9]{1,8})$/.test(proof.native_remark_sha256 || '')) {
|
||||
return { fields: [], blockers: ['arrangement_create_native_remark_evidence_missing'], operation };
|
||||
}
|
||||
const nativeRemark = controlValue(getArrangementControl(form, projectedOperation, 'beizhu0'));
|
||||
if (await sha256(normalize(nativeRemark)) !== proof.native_remark_sha256) {
|
||||
return { fields: [], blockers: ['arrangement_create_native_remark_changed_after_save'], operation };
|
||||
}
|
||||
projectedOperation.data.arrangement.remark = nativeRemark;
|
||||
}
|
||||
const projection = arrangementExpectedFields(form, projectedOperation);
|
||||
if (operation.action === 'arrangement_other') {
|
||||
const expectedNames = createPreservedFields(form, projectedOperation).map((field) => field.name);
|
||||
@@ -4526,6 +4555,9 @@
|
||||
applyBlockers = applied.blockers;
|
||||
writeGuard = applied.writeGuard || null;
|
||||
if (applied.linkageWait) preflight.preflight.arrangement_linkage = applied.linkageWait;
|
||||
if (applied.nativeRemarkSha256 && preflight.preflight.hotel_create?.version === 2) {
|
||||
preflight.preflight.hotel_create.native_remark_sha256 = applied.nativeRemarkSha256;
|
||||
}
|
||||
} else if (operation.action.startsWith('order_update_')) {
|
||||
const applied = applyUpdates(form, operation);
|
||||
const receivable = applyReceivableFixture(form, operation);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "联泰下单助手",
|
||||
"version": "0.5.190",
|
||||
"version": "0.5.191",
|
||||
"description": "在已登录 LTJT ERP 页面内规划并受控执行联泰 ERP 业务操作。",
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
|
||||
@@ -944,7 +944,7 @@
|
||||
|
||||
window.LTJTOrderAssistant = {
|
||||
...(window.LTJTOrderAssistant || {}),
|
||||
version: '0.5.190',
|
||||
version: '0.5.191',
|
||||
openTeamBatchForm,
|
||||
pingTeamBatchFrame,
|
||||
preflightTeamBatchNative,
|
||||
|
||||
Reference in new issue
Block a user