217 lines
6.8 KiB
JavaScript
217 lines
6.8 KiB
JavaScript
(() => {
|
|
'use strict';
|
|
|
|
try {
|
|
if (window.__LTJT_ORDER_ASSISTANT_BRIDGE_HANDLER__) {
|
|
window.removeEventListener('message', window.__LTJT_ORDER_ASSISTANT_BRIDGE_HANDLER__);
|
|
}
|
|
} catch (error) {
|
|
// Old handlers can belong to an invalidated extension context after reload.
|
|
}
|
|
try {
|
|
if (window.__LTJT_ORDER_ASSISTANT_STORAGE_HANDLER__) {
|
|
chrome.storage.onChanged.removeListener(window.__LTJT_ORDER_ASSISTANT_STORAGE_HANDLER__);
|
|
}
|
|
} catch (error) {
|
|
// Re-injection must keep going even when Chrome has invalidated the old context.
|
|
}
|
|
window.__LTJT_ORDER_ASSISTANT_BRIDGE_INSTALLED_AT__ = new Date().toISOString();
|
|
|
|
const BUSINESS_SOURCE = 'LTJT_MOCK_BUSINESS';
|
|
const EXTENSION_SOURCE = 'LTJT_ORDER_ASSISTANT_EXTENSION';
|
|
|
|
function nowIso() {
|
|
return new Date().toISOString();
|
|
}
|
|
|
|
function postReply(requestId, type, payload = {}) {
|
|
window.postMessage({
|
|
source: EXTENSION_SOURCE,
|
|
requestId,
|
|
type,
|
|
payload
|
|
}, window.location.origin);
|
|
}
|
|
|
|
async function getAutomationState() {
|
|
const saved = await chrome.storage.local.get('erpAutomationEnabled');
|
|
const enabled = saved.erpAutomationEnabled !== false;
|
|
return {
|
|
erp_automation_enabled: enabled,
|
|
erp_automation_status: enabled ? 'enabled' : 'disabled'
|
|
};
|
|
}
|
|
|
|
async function bridgePayload(extra = {}) {
|
|
return {
|
|
ok: true,
|
|
extension: 'ltjt-order-assistant',
|
|
version: chrome.runtime.getManifest().version,
|
|
bridge_installed_at: window.__LTJT_ORDER_ASSISTANT_BRIDGE_INSTALLED_AT__ || '',
|
|
...(await getAutomationState()),
|
|
...extra
|
|
};
|
|
}
|
|
|
|
async function postBridgeReady() {
|
|
window.postMessage({
|
|
source: EXTENSION_SOURCE,
|
|
type: 'BRIDGE_READY',
|
|
payload: await bridgePayload()
|
|
}, window.location.origin);
|
|
}
|
|
|
|
async function getResultMap() {
|
|
const saved = await chrome.storage.local.get('businessTaskResults');
|
|
return saved.businessTaskResults || {};
|
|
}
|
|
|
|
async function removeStoredBusinessTask(taskId) {
|
|
const saved = await chrome.storage.local.get([
|
|
'businessTasks',
|
|
'businessTaskResults',
|
|
'currentBusinessTask',
|
|
'currentBusinessTaskId'
|
|
]);
|
|
const belongsToTask = (candidateId) => candidateId === taskId || candidateId.startsWith(`${taskId}#`);
|
|
const businessTasks = saved.businessTasks || {};
|
|
const businessTaskResults = saved.businessTaskResults || {};
|
|
Object.keys(businessTasks).filter(belongsToTask).forEach((candidateId) => delete businessTasks[candidateId]);
|
|
Object.keys(businessTaskResults).filter(belongsToTask).forEach((candidateId) => delete businessTaskResults[candidateId]);
|
|
await chrome.storage.local.set({ businessTasks, businessTaskResults });
|
|
|
|
if (saved.currentBusinessTaskId === taskId || saved.currentBusinessTask?.task_id === taskId) {
|
|
await chrome.storage.local.remove([
|
|
'currentBusinessTask',
|
|
'currentBusinessTaskId',
|
|
'lastOperation',
|
|
'lastRawText'
|
|
]);
|
|
}
|
|
}
|
|
|
|
async function cancelAndRemoveTask(taskId) {
|
|
const cancellation = await chrome.runtime.sendMessage({
|
|
type: 'LTJT_CANCEL_TASK',
|
|
task_id: taskId
|
|
});
|
|
if (cancellation?.ok === false) {
|
|
throw new Error(cancellation.message || '插件未确认任务已取消。');
|
|
}
|
|
await removeStoredBusinessTask(taskId);
|
|
return {
|
|
ok: true,
|
|
task_id: taskId,
|
|
status: 'cancelled',
|
|
cancelled: cancellation?.cancelled !== false
|
|
};
|
|
}
|
|
|
|
async function createTask(payload) {
|
|
const task = payload?.task || {};
|
|
const operation = task.operation || payload?.operation;
|
|
const taskId = task.task_id || operation?.source?.task_id || `MOCK-${Date.now()}`;
|
|
const executionId = String(payload?.execution_id || '').trim();
|
|
if (!operation) throw new Error('Missing task.operation');
|
|
if (!executionId) throw new Error('Missing execution_id');
|
|
operation.source = {
|
|
...(operation.source || {}),
|
|
task_id: taskId,
|
|
execution_id: executionId,
|
|
origin: 'mock-business-system',
|
|
handed_to_extension_at: nowIso()
|
|
};
|
|
const currentBusinessTask = {
|
|
task_id: taskId,
|
|
operation,
|
|
raw_text: task.raw_text || '',
|
|
created_at: task.created_at || nowIso(),
|
|
received_at: nowIso(),
|
|
execution_id: executionId,
|
|
status: 'queued'
|
|
};
|
|
const acceptance = await chrome.runtime.sendMessage({
|
|
type: 'LTJT_AUTO_EXECUTE_TASK',
|
|
task_id: taskId,
|
|
execution_id: executionId,
|
|
task: currentBusinessTask
|
|
});
|
|
return { ...currentBusinessTask, acceptance };
|
|
}
|
|
|
|
const bridgeHandler = async (event) => {
|
|
if (event.source !== window) return;
|
|
const message = event.data || {};
|
|
if (message.source !== BUSINESS_SOURCE) return;
|
|
const requestId = message.requestId || '';
|
|
try {
|
|
if (message.type === 'PING') {
|
|
postReply(requestId, 'PONG', await bridgePayload());
|
|
return;
|
|
}
|
|
if (message.type === 'CREATE_TASK') {
|
|
const task = await createTask(message.payload || {});
|
|
postReply(requestId, 'TASK_CREATED', {
|
|
ok: true,
|
|
task_id: task.task_id,
|
|
execution_id: task.execution_id,
|
|
accepted: task.acceptance?.accepted === true,
|
|
status: task.acceptance?.status || 'not_accepted',
|
|
message: task.acceptance?.message || ''
|
|
});
|
|
return;
|
|
}
|
|
if (message.type === 'GET_TASK_RESULT') {
|
|
const taskId = message.payload?.task_id || '';
|
|
const resultMap = await getResultMap();
|
|
postReply(requestId, 'TASK_RESULT', {
|
|
ok: true,
|
|
task_id: taskId,
|
|
result: resultMap[taskId] || null
|
|
});
|
|
return;
|
|
}
|
|
if (message.type === 'GET_CURRENT_TASK') {
|
|
const saved = await chrome.storage.local.get('currentBusinessTask');
|
|
postReply(requestId, 'CURRENT_TASK', {
|
|
ok: true,
|
|
task: saved.currentBusinessTask || null
|
|
});
|
|
return;
|
|
}
|
|
if (message.type === 'DELETE_TASK') {
|
|
const taskId = message.payload?.task_id || '';
|
|
if (!taskId) throw new Error('Missing task_id');
|
|
const result = await cancelAndRemoveTask(taskId);
|
|
postReply(requestId, 'TASK_DELETED', result);
|
|
return;
|
|
}
|
|
if (message.type === 'CLEAR_TASKS') {
|
|
await chrome.storage.local.remove(['currentBusinessTask', 'currentBusinessTaskId', 'businessTasks', 'businessTaskResults']);
|
|
postReply(requestId, 'TASKS_CLEARED', { ok: true });
|
|
return;
|
|
}
|
|
postReply(requestId, 'ERROR', {
|
|
ok: false,
|
|
message: `Unknown bridge message type: ${message.type || '<missing>'}`
|
|
});
|
|
} catch (error) {
|
|
postReply(requestId, 'ERROR', {
|
|
ok: false,
|
|
message: error.message || String(error)
|
|
});
|
|
}
|
|
};
|
|
|
|
window.__LTJT_ORDER_ASSISTANT_BRIDGE_HANDLER__ = bridgeHandler;
|
|
window.addEventListener('message', bridgeHandler);
|
|
|
|
window.__LTJT_ORDER_ASSISTANT_STORAGE_HANDLER__ = (changes, areaName) => {
|
|
if (areaName !== 'local' || !changes.erpAutomationEnabled) return;
|
|
postBridgeReady().catch(() => {});
|
|
};
|
|
chrome.storage.onChanged.addListener(window.__LTJT_ORDER_ASSISTANT_STORAGE_HANDLER__);
|
|
|
|
postBridgeReady().catch(() => {});
|
|
})();
|