feat(sidepanel): implement multi-select and delete functionality for account records

- Added a new feature to allow users to select multiple account records and delete them.
- Introduced a filter system to categorize account records based on their status (success, failed, stopped, retry).
- Enhanced the UI with a toolbar for selection and deletion actions, including a confirmation modal for deletions.
- Updated the CSS for better styling of the new toolbar and selection states.
- Implemented backend support for deleting selected records and syncing the remaining records.
- Added unit tests to ensure the new functionality works as expected.
This commit is contained in:
QLHazyCoder
2026-04-19 01:12:17 +08:00
parent 49707ffa74
commit 774ead30f7
9 changed files with 916 additions and 112 deletions
@@ -203,3 +203,103 @@ test('account run history helper clears persisted records and syncs full snapsho
});
assert.equal(logs[0].message, '账号记录快照已同步到本地:C:/tmp/account-run-history.json');
});
test('account run history helper deletes selected records and syncs remaining snapshot payload', async () => {
const source = fs.readFileSync('background/account-run-history.js', 'utf8');
const globalScope = {};
const api = new Function('self', `${source}; return self.MultiPageBackgroundAccountRunHistory;`)(globalScope);
let storedHistory = [
{
recordId: 'keep@example.com',
email: 'keep@example.com',
password: 'secret',
finalStatus: 'success',
finishedAt: '2026-04-17T01:10:00.000Z',
retryCount: 0,
failureLabel: '流程完成',
failureDetail: '',
failedStep: null,
source: 'manual',
autoRunContext: null,
},
{
recordId: 'remove@example.com',
email: 'remove@example.com',
password: 'secret',
finalStatus: 'failed',
finishedAt: '2026-04-17T01:00:00.000Z',
retryCount: 2,
failureLabel: '步骤 8 失败',
failureDetail: '步骤 8:认证页异常',
failedStep: 8,
source: 'auto',
autoRunContext: {
currentRun: 1,
totalRuns: 5,
attemptRun: 3,
},
},
];
const fetchCalls = [];
global.fetch = async (url, options = {}) => {
fetchCalls.push({
url,
options,
});
return {
ok: true,
json: async () => ({
ok: true,
filePath: 'C:/tmp/account-run-history.json',
}),
};
};
const logs = [];
const helpers = api.createAccountRunHistoryHelpers({
ACCOUNT_RUN_HISTORY_STORAGE_KEY: 'accountRunHistory',
addLog: async (message, level) => {
logs.push({ message, level });
},
buildLocalHelperEndpoint: (baseUrl, path) => `${baseUrl}${path}`,
chrome: {
storage: {
local: {
get: async () => ({ accountRunHistory: storedHistory }),
set: async (payload) => {
storedHistory = payload.accountRunHistory;
},
},
},
},
getErrorMessage: (error) => error?.message || String(error || ''),
getState: async () => ({
accountRunHistoryTextEnabled: true,
accountRunHistoryHelperBaseUrl: 'http://127.0.0.1:17373',
}),
normalizeAccountRunHistoryHelperBaseUrl: (value) => String(value || '').trim(),
});
const result = await helpers.deleteAccountRunHistoryRecords(['remove@example.com']);
assert.deepStrictEqual(result, {
deletedCount: 1,
remainingCount: 1,
});
assert.equal(storedHistory.length, 1);
assert.equal(storedHistory[0].email, 'keep@example.com');
assert.equal(fetchCalls.length, 1);
assert.equal(fetchCalls[0].url, 'http://127.0.0.1:17373/sync-account-run-records');
assert.deepStrictEqual(JSON.parse(fetchCalls[0].options.body), {
generatedAt: JSON.parse(fetchCalls[0].options.body).generatedAt,
summary: {
total: 1,
success: 1,
failed: 0,
stopped: 0,
retryTotal: 0,
},
records: storedHistory,
});
assert.equal(logs[0].message, '账号记录快照已同步到本地:C:/tmp/account-run-history.json');
});