mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-06-13 18:31:16 +08:00
Add global task regex migration and UI
This commit is contained in:
6
index.js
6
index.js
@@ -146,6 +146,7 @@ import {
|
|||||||
} from "./ui/panel-bridge.js";
|
} from "./ui/panel-bridge.js";
|
||||||
import {
|
import {
|
||||||
migrateLegacyTaskProfiles,
|
migrateLegacyTaskProfiles,
|
||||||
|
migratePerTaskRegexToGlobal,
|
||||||
} from "./prompting/prompt-profiles.js";
|
} from "./prompting/prompt-profiles.js";
|
||||||
import { inspectTaskRegexReuse } from "./prompting/task-regex.js";
|
import { inspectTaskRegexReuse } from "./prompting/task-regex.js";
|
||||||
import {
|
import {
|
||||||
@@ -2885,6 +2886,11 @@ function getSettings() {
|
|||||||
const migrated = migrateLegacyTaskProfiles(mergedSettings);
|
const migrated = migrateLegacyTaskProfiles(mergedSettings);
|
||||||
mergedSettings.taskProfilesVersion = migrated.taskProfilesVersion;
|
mergedSettings.taskProfilesVersion = migrated.taskProfilesVersion;
|
||||||
mergedSettings.taskProfiles = migrated.taskProfiles;
|
mergedSettings.taskProfiles = migrated.taskProfiles;
|
||||||
|
const regexMigration = migratePerTaskRegexToGlobal(mergedSettings);
|
||||||
|
if (regexMigration.changed) {
|
||||||
|
mergedSettings.globalTaskRegex = regexMigration.settings.globalTaskRegex;
|
||||||
|
mergedSettings.taskProfiles = regexMigration.settings.taskProfiles;
|
||||||
|
}
|
||||||
extension_settings[MODULE_NAME] = mergedSettings;
|
extension_settings[MODULE_NAME] = mergedSettings;
|
||||||
globalThis.__stBmeDebugLoggingEnabled = Boolean(
|
globalThis.__stBmeDebugLoggingEnabled = Boolean(
|
||||||
mergedSettings.debugLoggingEnabled,
|
mergedSettings.debugLoggingEnabled,
|
||||||
|
|||||||
@@ -806,6 +806,71 @@ export function normalizeTaskRegexStages(stages = {}) {
|
|||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createDefaultGlobalTaskRegex() {
|
||||||
|
return {
|
||||||
|
enabled: true,
|
||||||
|
inheritStRegex: true,
|
||||||
|
sources: {
|
||||||
|
global: true,
|
||||||
|
preset: true,
|
||||||
|
character: true,
|
||||||
|
},
|
||||||
|
stages: normalizeTaskRegexStages(DEFAULT_TASK_REGEX_STAGES),
|
||||||
|
localRules: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dedupeRegexRules(rules = [], taskType = "task") {
|
||||||
|
const sourceRules = Array.isArray(rules) ? rules : [];
|
||||||
|
const deduped = [];
|
||||||
|
const seen = new Set();
|
||||||
|
|
||||||
|
for (let index = 0; index < sourceRules.length; index++) {
|
||||||
|
const normalized = normalizeRegexLocalRule(sourceRules[index], taskType, index);
|
||||||
|
const key = JSON.stringify({
|
||||||
|
enabled: normalized.enabled !== false,
|
||||||
|
find_regex: normalized.find_regex,
|
||||||
|
replace_string: normalized.replace_string,
|
||||||
|
trim_strings: normalized.trim_strings,
|
||||||
|
source: {
|
||||||
|
user_input: normalized.source?.user_input !== false,
|
||||||
|
ai_output: normalized.source?.ai_output !== false,
|
||||||
|
},
|
||||||
|
destination: {
|
||||||
|
prompt: normalized.destination?.prompt !== false,
|
||||||
|
display: Boolean(normalized.destination?.display),
|
||||||
|
},
|
||||||
|
min_depth: normalized.min_depth,
|
||||||
|
max_depth: normalized.max_depth,
|
||||||
|
});
|
||||||
|
if (seen.has(key)) continue;
|
||||||
|
seen.add(key);
|
||||||
|
deduped.push(normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deduped;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeGlobalTaskRegex(config = {}, taskType = "global") {
|
||||||
|
const defaults = createDefaultGlobalTaskRegex();
|
||||||
|
const source =
|
||||||
|
config && typeof config === "object" && !Array.isArray(config) ? config : {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
enabled: source.enabled !== false,
|
||||||
|
inheritStRegex: source.inheritStRegex !== false,
|
||||||
|
sources: {
|
||||||
|
...defaults.sources,
|
||||||
|
...(source.sources && typeof source.sources === "object" ? source.sources : {}),
|
||||||
|
},
|
||||||
|
stages: {
|
||||||
|
...normalizeTaskRegexStages(defaults.stages),
|
||||||
|
...normalizeTaskRegexStages(source.stages || {}),
|
||||||
|
},
|
||||||
|
localRules: dedupeRegexRules(source.localRules, taskType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function isTaskRegexStageEnabled(stages = {}, stageKey = "") {
|
export function isTaskRegexStageEnabled(stages = {}, stageKey = "") {
|
||||||
const normalizedStages = normalizeTaskRegexStages(stages);
|
const normalizedStages = normalizeTaskRegexStages(stages);
|
||||||
const normalizedStageKey = normalizeRegexStageKey(stageKey);
|
const normalizedStageKey = normalizeRegexStageKey(stageKey);
|
||||||
@@ -829,6 +894,20 @@ export function isTaskRegexStageEnabled(stages = {}, stageKey = "") {
|
|||||||
return normalizedStages[normalizedStageKey] !== false;
|
return normalizedStages[normalizedStageKey] !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildRegexConfigSignature(config = {}, taskType = "global") {
|
||||||
|
const normalized = normalizeGlobalTaskRegex(config, taskType);
|
||||||
|
return JSON.stringify({
|
||||||
|
enabled: normalized.enabled !== false,
|
||||||
|
inheritStRegex: normalized.inheritStRegex !== false,
|
||||||
|
sources: {
|
||||||
|
global: normalized.sources?.global !== false,
|
||||||
|
preset: normalized.sources?.preset !== false,
|
||||||
|
character: normalized.sources?.character !== false,
|
||||||
|
},
|
||||||
|
stages: normalizeTaskRegexStages(normalized.stages || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeTaskProfilesState(taskProfiles = {}) {
|
function normalizeTaskProfilesState(taskProfiles = {}) {
|
||||||
return ensureTaskProfiles({ taskProfiles });
|
return ensureTaskProfiles({ taskProfiles });
|
||||||
}
|
}
|
||||||
@@ -1358,6 +1437,141 @@ export function migrateLegacyTaskProfiles(settings = {}) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function migratePerTaskRegexToGlobal(settings = {}) {
|
||||||
|
const taskProfiles = ensureTaskProfiles(settings);
|
||||||
|
const defaultGlobalRegex = normalizeGlobalTaskRegex(
|
||||||
|
createDefaultGlobalTaskRegex(),
|
||||||
|
"global",
|
||||||
|
);
|
||||||
|
const existingGlobalRegex = normalizeGlobalTaskRegex(
|
||||||
|
settings.globalTaskRegex || {},
|
||||||
|
"global",
|
||||||
|
);
|
||||||
|
const existingGlobalConfigSignature = buildRegexConfigSignature(
|
||||||
|
existingGlobalRegex,
|
||||||
|
"global",
|
||||||
|
);
|
||||||
|
const defaultGlobalConfigSignature = buildRegexConfigSignature(
|
||||||
|
defaultGlobalRegex,
|
||||||
|
"global",
|
||||||
|
);
|
||||||
|
const profilesWithLegacyRegex = [];
|
||||||
|
|
||||||
|
for (const taskType of TASK_TYPES) {
|
||||||
|
const bucket = taskProfiles[taskType];
|
||||||
|
const defaultProfileRegex = normalizeGlobalTaskRegex(
|
||||||
|
createDefaultTaskProfile(taskType).regex || {},
|
||||||
|
taskType,
|
||||||
|
);
|
||||||
|
const defaultProfileConfigSignature = buildRegexConfigSignature(
|
||||||
|
defaultProfileRegex,
|
||||||
|
taskType,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const profile of Array.isArray(bucket?.profiles) ? bucket.profiles : []) {
|
||||||
|
const normalizedProfileRegex = normalizeGlobalTaskRegex(
|
||||||
|
profile?.regex || {},
|
||||||
|
taskType,
|
||||||
|
);
|
||||||
|
const profileConfigSignature = buildRegexConfigSignature(
|
||||||
|
normalizedProfileRegex,
|
||||||
|
taskType,
|
||||||
|
);
|
||||||
|
const hasRules = normalizedProfileRegex.localRules.length > 0;
|
||||||
|
const hasConfigDiff = profileConfigSignature !== defaultProfileConfigSignature;
|
||||||
|
if (!hasRules && !hasConfigDiff) continue;
|
||||||
|
profilesWithLegacyRegex.push({
|
||||||
|
taskType,
|
||||||
|
profileId: String(profile?.id || ""),
|
||||||
|
regex: normalizedProfileRegex,
|
||||||
|
configSignature: profileConfigSignature,
|
||||||
|
hasConfigDiff,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profilesWithLegacyRegex.length === 0) {
|
||||||
|
return {
|
||||||
|
changed: false,
|
||||||
|
settings: {
|
||||||
|
...settings,
|
||||||
|
taskProfiles,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const configCandidates = profilesWithLegacyRegex.filter(
|
||||||
|
(item) => item.hasConfigDiff,
|
||||||
|
);
|
||||||
|
const uniqueCandidateSignatures = [
|
||||||
|
...new Set(configCandidates.map((item) => item.configSignature)),
|
||||||
|
];
|
||||||
|
if (uniqueCandidateSignatures.length > 1) {
|
||||||
|
console.warn(
|
||||||
|
"[ST-BME] 检测到多个任务预设存在冲突的旧正则配置,已按顺序采用第一份并统一迁移。",
|
||||||
|
configCandidates.map((item) => ({
|
||||||
|
taskType: item.taskType,
|
||||||
|
profileId: item.profileId,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedConfig =
|
||||||
|
existingGlobalConfigSignature !== defaultGlobalConfigSignature
|
||||||
|
? existingGlobalRegex
|
||||||
|
: configCandidates[0]?.regex || defaultGlobalRegex;
|
||||||
|
|
||||||
|
const mergedLocalRules = dedupeRegexRules(
|
||||||
|
[
|
||||||
|
...(Array.isArray(existingGlobalRegex.localRules)
|
||||||
|
? existingGlobalRegex.localRules
|
||||||
|
: []),
|
||||||
|
...profilesWithLegacyRegex.flatMap((item) =>
|
||||||
|
Array.isArray(item.regex?.localRules) ? item.regex.localRules : [],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
"global",
|
||||||
|
);
|
||||||
|
|
||||||
|
const nextGlobalRegex = {
|
||||||
|
...normalizeGlobalTaskRegex(selectedConfig, "global"),
|
||||||
|
localRules: mergedLocalRules,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nextTaskProfiles = {};
|
||||||
|
for (const taskType of TASK_TYPES) {
|
||||||
|
const bucket = taskProfiles[taskType] || {
|
||||||
|
activeProfileId: DEFAULT_PROFILE_ID,
|
||||||
|
profiles: [createDefaultTaskProfile(taskType)],
|
||||||
|
};
|
||||||
|
const legacyProfileIds = new Set(
|
||||||
|
profilesWithLegacyRegex
|
||||||
|
.filter((item) => item.taskType === taskType)
|
||||||
|
.map((item) => item.profileId),
|
||||||
|
);
|
||||||
|
nextTaskProfiles[taskType] = {
|
||||||
|
...bucket,
|
||||||
|
profiles: (Array.isArray(bucket.profiles) ? bucket.profiles : []).map((profile) =>
|
||||||
|
legacyProfileIds.has(String(profile?.id || ""))
|
||||||
|
? normalizeTaskProfile(taskType, {
|
||||||
|
...profile,
|
||||||
|
regex: {},
|
||||||
|
})
|
||||||
|
: normalizeTaskProfile(taskType, profile),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
changed: true,
|
||||||
|
settings: {
|
||||||
|
...settings,
|
||||||
|
globalTaskRegex: nextGlobalRegex,
|
||||||
|
taskProfiles: nextTaskProfiles,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function getActiveTaskProfile(settings = {}, taskType) {
|
export function getActiveTaskProfile(settings = {}, taskType) {
|
||||||
const taskProfiles = ensureTaskProfiles(settings);
|
const taskProfiles = ensureTaskProfiles(settings);
|
||||||
const bucket = taskProfiles?.[taskType];
|
const bucket = taskProfiles?.[taskType];
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { getHostAdapter } from "../host/adapter/index.js";
|
|||||||
import {
|
import {
|
||||||
getActiveTaskProfile,
|
getActiveTaskProfile,
|
||||||
isTaskRegexStageEnabled,
|
isTaskRegexStageEnabled,
|
||||||
|
normalizeGlobalTaskRegex,
|
||||||
normalizeTaskRegexStages,
|
normalizeTaskRegexStages,
|
||||||
} from "./prompt-profiles.js";
|
} from "./prompt-profiles.js";
|
||||||
|
|
||||||
@@ -1026,6 +1027,29 @@ function applyHostRegexReuseFallback(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveTaskRegexConfig(settings = {}, taskType = "") {
|
||||||
|
const hasGlobalRegex =
|
||||||
|
settings?.globalTaskRegex &&
|
||||||
|
typeof settings.globalTaskRegex === "object" &&
|
||||||
|
!Array.isArray(settings.globalTaskRegex);
|
||||||
|
|
||||||
|
if (hasGlobalRegex) {
|
||||||
|
return {
|
||||||
|
profile: null,
|
||||||
|
regexConfig: normalizeGlobalTaskRegex(
|
||||||
|
settings.globalTaskRegex || {},
|
||||||
|
"global",
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const profile = getActiveTaskProfile(settings, taskType);
|
||||||
|
return {
|
||||||
|
profile,
|
||||||
|
regexConfig: normalizeGlobalTaskRegex(profile?.regex || {}, taskType || "task"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function applyHostRegexReuse(
|
export function applyHostRegexReuse(
|
||||||
settings = {},
|
settings = {},
|
||||||
taskType,
|
taskType,
|
||||||
@@ -1041,8 +1065,7 @@ export function applyHostRegexReuse(
|
|||||||
const normalizedTaskType = String(taskType || "").trim();
|
const normalizedTaskType = String(taskType || "").trim();
|
||||||
const normalizedSourceType = normalizeHostRegexSourceType(sourceType);
|
const normalizedSourceType = normalizeHostRegexSourceType(sourceType);
|
||||||
const normalizedFormatterOptions = normalizeHostFormatterOptions(formatterOptions);
|
const normalizedFormatterOptions = normalizeHostFormatterOptions(formatterOptions);
|
||||||
const profile = getActiveTaskProfile(settings, normalizedTaskType);
|
const { regexConfig } = resolveTaskRegexConfig(settings, taskType);
|
||||||
const regexConfig = profile?.regex || {};
|
|
||||||
const regexHost = getRegexHost();
|
const regexHost = getRegexHost();
|
||||||
const executionState = buildHostRegexExecutionState(regexHost);
|
const executionState = buildHostRegexExecutionState(regexHost);
|
||||||
|
|
||||||
@@ -1193,8 +1216,7 @@ export function applyTaskRegex(
|
|||||||
debugCollector = null,
|
debugCollector = null,
|
||||||
role = "system",
|
role = "system",
|
||||||
) {
|
) {
|
||||||
const profile = getActiveTaskProfile(settings, taskType);
|
const { regexConfig } = resolveTaskRegexConfig(settings, taskType);
|
||||||
const regexConfig = profile?.regex || {};
|
|
||||||
const input = typeof text === "string" ? text : "";
|
const input = typeof text === "string" ? text : "";
|
||||||
|
|
||||||
if (!regexConfig.enabled) {
|
if (!regexConfig.enabled) {
|
||||||
@@ -1252,8 +1274,7 @@ export function applyTaskRegex(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function inspectTaskRegexReuse(settings = {}, taskType = "") {
|
export function inspectTaskRegexReuse(settings = {}, taskType = "") {
|
||||||
const profile = getActiveTaskProfile(settings, taskType);
|
const { profile, regexConfig } = resolveTaskRegexConfig(settings, taskType);
|
||||||
const regexConfig = profile?.regex || {};
|
|
||||||
const detailed = collectTavernRulesDetailed(regexConfig);
|
const detailed = collectTavernRulesDetailed(regexConfig);
|
||||||
const stageConfig = normalizeTaskRegexStages(regexConfig.stages || {});
|
const stageConfig = normalizeTaskRegexStages(regexConfig.stages || {});
|
||||||
const localRules = collectLocalRules(regexConfig);
|
const localRules = collectLocalRules(regexConfig);
|
||||||
@@ -1292,3 +1313,6 @@ export function inspectTaskRegexReuse(settings = {}, taskType = "") {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { createDefaultTaskProfiles } from "../prompting/prompt-profiles.js";
|
import {
|
||||||
|
createDefaultGlobalTaskRegex,
|
||||||
|
createDefaultTaskProfiles,
|
||||||
|
} from "../prompting/prompt-profiles.js";
|
||||||
|
|
||||||
function clampIntValue(value, fallback = 0, min = 0, max = 9999) {
|
function clampIntValue(value, fallback = 0, min = 0, max = 9999) {
|
||||||
const numeric = Number(value);
|
const numeric = Number(value);
|
||||||
@@ -110,6 +113,7 @@ export const defaultSettings = {
|
|||||||
reflectionPrompt: "",
|
reflectionPrompt: "",
|
||||||
taskProfilesVersion: 3,
|
taskProfilesVersion: 3,
|
||||||
taskProfiles: createDefaultTaskProfiles(),
|
taskProfiles: createDefaultTaskProfiles(),
|
||||||
|
globalTaskRegex: createDefaultGlobalTaskRegex(),
|
||||||
|
|
||||||
// ====== v2 增强设置 ======
|
// ====== v2 增强设置 ======
|
||||||
enableConsolidation: true,
|
enableConsolidation: true,
|
||||||
|
|||||||
@@ -112,6 +112,10 @@ export function createGenerationRecallHarness(options = {}) {
|
|||||||
taskProfilesVersion: settings?.taskProfilesVersion || 0,
|
taskProfilesVersion: settings?.taskProfilesVersion || 0,
|
||||||
taskProfiles: settings?.taskProfiles || {},
|
taskProfiles: settings?.taskProfiles || {},
|
||||||
}),
|
}),
|
||||||
|
migratePerTaskRegexToGlobal: (settings = {}) => ({
|
||||||
|
changed: false,
|
||||||
|
settings,
|
||||||
|
}),
|
||||||
refreshPanelLiveStateController: () => {
|
refreshPanelLiveStateController: () => {
|
||||||
context.refreshPanelCalls += 1;
|
context.refreshPanelCalls += 1;
|
||||||
},
|
},
|
||||||
|
|||||||
552
ui/panel.js
552
ui/panel.js
@@ -20,10 +20,12 @@ import {
|
|||||||
} from "../llm/llm-preset-utils.js";
|
} from "../llm/llm-preset-utils.js";
|
||||||
import {
|
import {
|
||||||
cloneTaskProfile,
|
cloneTaskProfile,
|
||||||
|
createDefaultGlobalTaskRegex,
|
||||||
createBuiltinPromptBlock,
|
createBuiltinPromptBlock,
|
||||||
createCustomPromptBlock,
|
createCustomPromptBlock,
|
||||||
createLocalRegexRule,
|
createLocalRegexRule,
|
||||||
DEFAULT_TASK_BLOCKS,
|
DEFAULT_TASK_BLOCKS,
|
||||||
|
dedupeRegexRules,
|
||||||
ensureTaskProfiles,
|
ensureTaskProfiles,
|
||||||
exportTaskProfile as serializeTaskProfile,
|
exportTaskProfile as serializeTaskProfile,
|
||||||
getBuiltinBlockDefinitions,
|
getBuiltinBlockDefinitions,
|
||||||
@@ -31,6 +33,7 @@ import {
|
|||||||
getTaskTypeOptions,
|
getTaskTypeOptions,
|
||||||
importTaskProfile as parseImportedTaskProfile,
|
importTaskProfile as parseImportedTaskProfile,
|
||||||
isTaskRegexStageEnabled,
|
isTaskRegexStageEnabled,
|
||||||
|
normalizeGlobalTaskRegex,
|
||||||
normalizeTaskRegexStages,
|
normalizeTaskRegexStages,
|
||||||
restoreDefaultTaskProfile,
|
restoreDefaultTaskProfile,
|
||||||
setActiveTaskProfileId,
|
setActiveTaskProfileId,
|
||||||
@@ -67,7 +70,6 @@ function getDefaultPromptText(taskType = "") {
|
|||||||
const TASK_PROFILE_TABS = [
|
const TASK_PROFILE_TABS = [
|
||||||
{ id: "generation", label: "生成参数" },
|
{ id: "generation", label: "生成参数" },
|
||||||
{ id: "prompt", label: "Prompt 编排" },
|
{ id: "prompt", label: "Prompt 编排" },
|
||||||
{ id: "regex", label: "正则" },
|
|
||||||
{ id: "debug", label: "调试预览" },
|
{ id: "debug", label: "调试预览" },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -226,6 +228,8 @@ let currentTaskProfileTaskType = "extract";
|
|||||||
let currentTaskProfileTabId = "generation";
|
let currentTaskProfileTabId = "generation";
|
||||||
let currentTaskProfileBlockId = "";
|
let currentTaskProfileBlockId = "";
|
||||||
let currentTaskProfileRuleId = "";
|
let currentTaskProfileRuleId = "";
|
||||||
|
let showGlobalRegexPanel = false;
|
||||||
|
let currentGlobalRegexRuleId = "";
|
||||||
let currentCognitionOwnerKey = "";
|
let currentCognitionOwnerKey = "";
|
||||||
let currentGraphView = "graph";
|
let currentGraphView = "graph";
|
||||||
let fetchedMemoryLLMModels = [];
|
let fetchedMemoryLLMModels = [];
|
||||||
@@ -4784,16 +4788,58 @@ function _bindTaskProfileWorkspace() {
|
|||||||
try {
|
try {
|
||||||
const text = await file.text();
|
const text = await file.text();
|
||||||
const settings = _getSettings?.() || {};
|
const settings = _getSettings?.() || {};
|
||||||
const imported = parseImportedTaskProfile(
|
const parsed = JSON.parse(text);
|
||||||
settings.taskProfiles || {},
|
let nextGlobalTaskRegex = _normalizeGlobalRegexDraft(
|
||||||
text,
|
settings.globalTaskRegex || {},
|
||||||
);
|
);
|
||||||
|
const importedGlobalMerge = _mergeImportedGlobalRegex(
|
||||||
|
nextGlobalTaskRegex,
|
||||||
|
parsed?.globalTaskRegex,
|
||||||
|
);
|
||||||
|
nextGlobalTaskRegex = importedGlobalMerge.globalTaskRegex;
|
||||||
|
let imported = parseImportedTaskProfile(
|
||||||
|
settings.taskProfiles || {},
|
||||||
|
parsed,
|
||||||
|
);
|
||||||
|
const legacyRuleMerge = _mergeProfileRegexRulesIntoGlobal(
|
||||||
|
nextGlobalTaskRegex,
|
||||||
|
imported.profile,
|
||||||
|
);
|
||||||
|
nextGlobalTaskRegex = legacyRuleMerge.globalTaskRegex;
|
||||||
|
if (legacyRuleMerge.clearedLegacyRules) {
|
||||||
|
imported = {
|
||||||
|
...imported,
|
||||||
|
profile: legacyRuleMerge.profile,
|
||||||
|
taskProfiles: upsertTaskProfile(
|
||||||
|
imported.taskProfiles,
|
||||||
|
imported.taskType,
|
||||||
|
legacyRuleMerge.profile,
|
||||||
|
{ setActive: true },
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
currentTaskProfileTaskType = imported.taskType || currentTaskProfileTaskType;
|
currentTaskProfileTaskType = imported.taskType || currentTaskProfileTaskType;
|
||||||
currentTaskProfileBlockId = imported.profile?.blocks?.[0]?.id || "";
|
currentTaskProfileBlockId = imported.profile?.blocks?.[0]?.id || "";
|
||||||
currentTaskProfileRuleId =
|
currentTaskProfileRuleId =
|
||||||
imported.profile?.regex?.localRules?.[0]?.id || "";
|
imported.profile?.regex?.localRules?.[0]?.id || "";
|
||||||
_patchTaskProfiles(imported.taskProfiles);
|
_patchSettings(
|
||||||
toastr.success("预设导入成功", "ST-BME");
|
{
|
||||||
|
taskProfilesVersion: 3,
|
||||||
|
taskProfiles: imported.taskProfiles,
|
||||||
|
globalTaskRegex: nextGlobalTaskRegex,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
refreshTaskWorkspace: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const mergedRuleCount =
|
||||||
|
importedGlobalMerge.mergedRuleCount + legacyRuleMerge.mergedRuleCount;
|
||||||
|
toastr.success(
|
||||||
|
mergedRuleCount > 0
|
||||||
|
? `预设导入成功,${mergedRuleCount} 条正则规则已合并到通用正则规则`
|
||||||
|
: "预设导入成功",
|
||||||
|
"ST-BME",
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[ST-BME] 导入任务预设失败:", error);
|
console.error("[ST-BME] 导入任务预设失败:", error);
|
||||||
toastr.error(`预设导入失败: ${error?.message || error}`, "ST-BME");
|
toastr.error(`预设导入失败: ${error?.message || error}`, "ST-BME");
|
||||||
@@ -4817,14 +4863,41 @@ function _bindTaskProfileWorkspace() {
|
|||||||
}
|
}
|
||||||
const settings = _getSettings?.() || {};
|
const settings = _getSettings?.() || {};
|
||||||
let mergedProfiles = settings.taskProfiles || {};
|
let mergedProfiles = settings.taskProfiles || {};
|
||||||
|
let nextGlobalTaskRegex = _normalizeGlobalRegexDraft(
|
||||||
|
settings.globalTaskRegex || {},
|
||||||
|
);
|
||||||
|
const importedGlobalMerge = _mergeImportedGlobalRegex(
|
||||||
|
nextGlobalTaskRegex,
|
||||||
|
parsed?.globalTaskRegex,
|
||||||
|
);
|
||||||
|
nextGlobalTaskRegex = importedGlobalMerge.globalTaskRegex;
|
||||||
let importedCount = 0;
|
let importedCount = 0;
|
||||||
|
let mergedLegacyRuleCount = 0;
|
||||||
for (const [taskType, entry] of Object.entries(parsed.profiles)) {
|
for (const [taskType, entry] of Object.entries(parsed.profiles)) {
|
||||||
try {
|
try {
|
||||||
const imported = parseImportedTaskProfile(
|
let imported = parseImportedTaskProfile(
|
||||||
mergedProfiles,
|
mergedProfiles,
|
||||||
entry,
|
entry,
|
||||||
taskType,
|
taskType,
|
||||||
);
|
);
|
||||||
|
const legacyRuleMerge = _mergeProfileRegexRulesIntoGlobal(
|
||||||
|
nextGlobalTaskRegex,
|
||||||
|
imported.profile,
|
||||||
|
);
|
||||||
|
nextGlobalTaskRegex = legacyRuleMerge.globalTaskRegex;
|
||||||
|
mergedLegacyRuleCount += legacyRuleMerge.mergedRuleCount;
|
||||||
|
if (legacyRuleMerge.clearedLegacyRules) {
|
||||||
|
imported = {
|
||||||
|
...imported,
|
||||||
|
profile: legacyRuleMerge.profile,
|
||||||
|
taskProfiles: upsertTaskProfile(
|
||||||
|
imported.taskProfiles,
|
||||||
|
imported.taskType,
|
||||||
|
legacyRuleMerge.profile,
|
||||||
|
{ setActive: true },
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
mergedProfiles = imported.taskProfiles;
|
mergedProfiles = imported.taskProfiles;
|
||||||
importedCount++;
|
importedCount++;
|
||||||
} catch (innerError) {
|
} catch (innerError) {
|
||||||
@@ -4835,8 +4908,24 @@ function _bindTaskProfileWorkspace() {
|
|||||||
toastr.warning("没有成功导入任何预设", "ST-BME");
|
toastr.warning("没有成功导入任何预设", "ST-BME");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_patchTaskProfiles(mergedProfiles);
|
_patchSettings(
|
||||||
toastr.success(`已导入 ${importedCount} 个任务预设`, "ST-BME");
|
{
|
||||||
|
taskProfilesVersion: 3,
|
||||||
|
taskProfiles: mergedProfiles,
|
||||||
|
globalTaskRegex: nextGlobalTaskRegex,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
refreshTaskWorkspace: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const mergedRuleCount =
|
||||||
|
importedGlobalMerge.mergedRuleCount + mergedLegacyRuleCount;
|
||||||
|
toastr.success(
|
||||||
|
mergedRuleCount > 0
|
||||||
|
? `已导入 ${importedCount} 个任务预设,并合并 ${mergedRuleCount} 条通用正则规则`
|
||||||
|
: `已导入 ${importedCount} 个任务预设`,
|
||||||
|
"ST-BME",
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[ST-BME] 导入全部预设失败:", error);
|
console.error("[ST-BME] 导入全部预设失败:", error);
|
||||||
toastr.error(`导入全部预设失败: ${error?.message || error}`, "ST-BME");
|
toastr.error(`导入全部预设失败: ${error?.message || error}`, "ST-BME");
|
||||||
@@ -4851,6 +4940,7 @@ function _bindTaskProfileWorkspace() {
|
|||||||
function _handleTaskProfileWorkspaceInput(event) {
|
function _handleTaskProfileWorkspaceInput(event) {
|
||||||
const target = event.target;
|
const target = event.target;
|
||||||
if (!(target instanceof HTMLElement)) return;
|
if (!(target instanceof HTMLElement)) return;
|
||||||
|
const isGlobalRegexPanel = _isGlobalRegexPanelTarget(target);
|
||||||
|
|
||||||
if (target.matches("[data-block-field]")) {
|
if (target.matches("[data-block-field]")) {
|
||||||
_persistSelectedBlockField(target, false);
|
_persistSelectedBlockField(target, false);
|
||||||
@@ -4880,13 +4970,18 @@ function _handleTaskProfileWorkspaceInput(event) {
|
|||||||
target.matches("[data-regex-rule-source]") ||
|
target.matches("[data-regex-rule-source]") ||
|
||||||
target.matches("[data-regex-rule-destination]")
|
target.matches("[data-regex-rule-destination]")
|
||||||
) {
|
) {
|
||||||
|
if (isGlobalRegexPanel) {
|
||||||
|
_persistSelectedGlobalRegexRuleField(target, false);
|
||||||
|
} else {
|
||||||
_persistSelectedRegexRuleField(target, false);
|
_persistSelectedRegexRuleField(target, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _handleTaskProfileWorkspaceChange(event) {
|
function _handleTaskProfileWorkspaceChange(event) {
|
||||||
const target = event.target;
|
const target = event.target;
|
||||||
if (!(target instanceof HTMLElement)) return;
|
if (!(target instanceof HTMLElement)) return;
|
||||||
|
const isGlobalRegexPanel = _isGlobalRegexPanelTarget(target);
|
||||||
|
|
||||||
if (target.id === "bme-task-profile-select") {
|
if (target.id === "bme-task-profile-select") {
|
||||||
const settings = _getSettings?.() || {};
|
const settings = _getSettings?.() || {};
|
||||||
@@ -4912,17 +5007,29 @@ function _handleTaskProfileWorkspaceChange(event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (target.matches("[data-regex-field]")) {
|
if (target.matches("[data-regex-field]")) {
|
||||||
|
if (isGlobalRegexPanel) {
|
||||||
|
_persistGlobalRegexField(target, false);
|
||||||
|
} else {
|
||||||
_persistRegexConfigField(target, false);
|
_persistRegexConfigField(target, false);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.matches("[data-regex-source]")) {
|
if (target.matches("[data-regex-source]")) {
|
||||||
|
if (isGlobalRegexPanel) {
|
||||||
|
_persistGlobalRegexSourceField(target, false);
|
||||||
|
} else {
|
||||||
_persistRegexSourceField(target, false);
|
_persistRegexSourceField(target, false);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.matches("[data-regex-stage]")) {
|
if (target.matches("[data-regex-stage]")) {
|
||||||
|
if (isGlobalRegexPanel) {
|
||||||
|
_persistGlobalRegexStageField(target, false);
|
||||||
|
} else {
|
||||||
_persistRegexStageField(target, false);
|
_persistRegexStageField(target, false);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4931,12 +5038,20 @@ function _handleTaskProfileWorkspaceChange(event) {
|
|||||||
target.matches("[data-regex-rule-source]") ||
|
target.matches("[data-regex-rule-source]") ||
|
||||||
target.matches("[data-regex-rule-destination]")
|
target.matches("[data-regex-rule-destination]")
|
||||||
) {
|
) {
|
||||||
|
if (isGlobalRegexPanel) {
|
||||||
|
_persistSelectedGlobalRegexRuleField(target, true);
|
||||||
|
} else {
|
||||||
_persistSelectedRegexRuleField(target, true);
|
_persistSelectedRegexRuleField(target, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _getTaskProfileWorkspaceState(settings = _getSettings?.() || {}) {
|
function _getTaskProfileWorkspaceState(settings = _getSettings?.() || {}) {
|
||||||
const taskProfiles = ensureTaskProfiles(settings);
|
const taskProfiles = ensureTaskProfiles(settings);
|
||||||
|
const globalTaskRegex = _normalizeGlobalRegexDraft(settings.globalTaskRegex || {});
|
||||||
|
const globalRegexRules = Array.isArray(globalTaskRegex.localRules)
|
||||||
|
? globalTaskRegex.localRules
|
||||||
|
: [];
|
||||||
const taskTypeOptions = getTaskTypeOptions();
|
const taskTypeOptions = getTaskTypeOptions();
|
||||||
const runtimeDebug = _getRuntimeDebugSnapshot?.() || {
|
const runtimeDebug = _getRuntimeDebugSnapshot?.() || {
|
||||||
hostCapabilities: null,
|
hostCapabilities: null,
|
||||||
@@ -4970,10 +5085,16 @@ function _getTaskProfileWorkspaceState(settings = _getSettings?.() || {}) {
|
|||||||
if (!regexRules.some((rule) => rule.id === currentTaskProfileRuleId)) {
|
if (!regexRules.some((rule) => rule.id === currentTaskProfileRuleId)) {
|
||||||
currentTaskProfileRuleId = regexRules[0]?.id || "";
|
currentTaskProfileRuleId = regexRules[0]?.id || "";
|
||||||
}
|
}
|
||||||
|
if (!globalRegexRules.some((rule) => rule.id === currentGlobalRegexRuleId)) {
|
||||||
|
currentGlobalRegexRuleId = globalRegexRules[0]?.id || "";
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
settings,
|
settings,
|
||||||
taskProfiles,
|
taskProfiles,
|
||||||
|
globalTaskRegex,
|
||||||
|
globalRegexRules,
|
||||||
|
showGlobalRegex: showGlobalRegexPanel,
|
||||||
taskTypeOptions,
|
taskTypeOptions,
|
||||||
taskType: currentTaskProfileTaskType,
|
taskType: currentTaskProfileTaskType,
|
||||||
taskTabId: currentTaskProfileTabId,
|
taskTabId: currentTaskProfileTabId,
|
||||||
@@ -4985,6 +5106,8 @@ function _getTaskProfileWorkspaceState(settings = _getSettings?.() || {}) {
|
|||||||
regexRules,
|
regexRules,
|
||||||
selectedRule:
|
selectedRule:
|
||||||
regexRules.find((rule) => rule.id === currentTaskProfileRuleId) || null,
|
regexRules.find((rule) => rule.id === currentTaskProfileRuleId) || null,
|
||||||
|
selectedGlobalRegexRule:
|
||||||
|
globalRegexRules.find((rule) => rule.id === currentGlobalRegexRuleId) || null,
|
||||||
builtinBlockDefinitions: getBuiltinBlockDefinitions(),
|
builtinBlockDefinitions: getBuiltinBlockDefinitions(),
|
||||||
runtimeDebug,
|
runtimeDebug,
|
||||||
};
|
};
|
||||||
@@ -5636,6 +5759,10 @@ async function _handleTaskProfileWorkspaceClick(event) {
|
|||||||
currentTaskProfileRuleId = "";
|
currentTaskProfileRuleId = "";
|
||||||
_refreshTaskProfileWorkspace();
|
_refreshTaskProfileWorkspace();
|
||||||
return;
|
return;
|
||||||
|
case "toggle-global-regex":
|
||||||
|
showGlobalRegexPanel = !showGlobalRegexPanel;
|
||||||
|
_refreshTaskProfileWorkspace();
|
||||||
|
return;
|
||||||
case "switch-task-tab":
|
case "switch-task-tab":
|
||||||
currentTaskProfileTabId =
|
currentTaskProfileTabId =
|
||||||
actionEl.dataset.taskTab || currentTaskProfileTabId;
|
actionEl.dataset.taskTab || currentTaskProfileTabId;
|
||||||
@@ -5655,7 +5782,11 @@ async function _handleTaskProfileWorkspaceClick(event) {
|
|||||||
_refreshTaskProfileWorkspace();
|
_refreshTaskProfileWorkspace();
|
||||||
return;
|
return;
|
||||||
case "select-regex-rule":
|
case "select-regex-rule":
|
||||||
|
if (_isGlobalRegexPanelTarget(actionEl)) {
|
||||||
|
currentGlobalRegexRuleId = actionEl.dataset.ruleId || "";
|
||||||
|
} else {
|
||||||
currentTaskProfileRuleId = actionEl.dataset.ruleId || "";
|
currentTaskProfileRuleId = actionEl.dataset.ruleId || "";
|
||||||
|
}
|
||||||
_refreshTaskProfileWorkspace();
|
_refreshTaskProfileWorkspace();
|
||||||
return;
|
return;
|
||||||
case "add-custom-block":
|
case "add-custom-block":
|
||||||
@@ -5748,20 +5879,25 @@ async function _handleTaskProfileWorkspaceClick(event) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case "export-profile":
|
case "export-profile":
|
||||||
_downloadTaskProfile(state.taskProfiles, currentTaskProfileTaskType, selectedProfile);
|
_downloadTaskProfile(
|
||||||
|
state.taskProfiles,
|
||||||
|
currentTaskProfileTaskType,
|
||||||
|
selectedProfile,
|
||||||
|
state.globalTaskRegex,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
case "import-profile":
|
case "import-profile":
|
||||||
document.getElementById("bme-task-profile-import")?.click();
|
document.getElementById("bme-task-profile-import")?.click();
|
||||||
return;
|
return;
|
||||||
case "export-all-profiles":
|
case "export-all-profiles":
|
||||||
_downloadAllTaskProfiles(state.taskProfiles);
|
_downloadAllTaskProfiles(state.taskProfiles, state.globalTaskRegex);
|
||||||
return;
|
return;
|
||||||
case "import-all-profiles":
|
case "import-all-profiles":
|
||||||
document.getElementById("bme-task-profile-import-all")?.click();
|
document.getElementById("bme-task-profile-import-all")?.click();
|
||||||
return;
|
return;
|
||||||
case "restore-all-profiles": {
|
case "restore-all-profiles": {
|
||||||
const confirmed = window.confirm(
|
const confirmed = window.confirm(
|
||||||
"这会将全部 6 个任务的默认预设恢复为出厂状态。已保存的自定义预设不受影响。是否继续?",
|
"这会将全部 6 个任务的默认预设恢复为出厂状态。已保存的自定义预设不受影响,通用正则规则也不受影响。是否继续?",
|
||||||
);
|
);
|
||||||
if (!confirmed) return;
|
if (!confirmed) return;
|
||||||
const taskTypes = getTaskTypeOptions().map((t) => t.id);
|
const taskTypes = getTaskTypeOptions().map((t) => t.id);
|
||||||
@@ -5815,6 +5951,33 @@ async function _handleTaskProfileWorkspaceClick(event) {
|
|||||||
case "delete-regex-rule":
|
case "delete-regex-rule":
|
||||||
_deleteRegexRule(actionEl.dataset.ruleId);
|
_deleteRegexRule(actionEl.dataset.ruleId);
|
||||||
return;
|
return;
|
||||||
|
case "add-global-regex-rule":
|
||||||
|
_updateGlobalTaskRegex((draft) => {
|
||||||
|
const localRules = Array.isArray(draft.localRules) ? draft.localRules : [];
|
||||||
|
const nextRule = createLocalRegexRule("global", {
|
||||||
|
script_name: `通用规则 ${localRules.length + 1}`,
|
||||||
|
});
|
||||||
|
draft.localRules = [...localRules, nextRule];
|
||||||
|
return { selectRuleId: nextRule.id };
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
case "delete-global-regex-rule":
|
||||||
|
_deleteGlobalRegexRule(actionEl.dataset.ruleId);
|
||||||
|
return;
|
||||||
|
case "select-global-regex-rule":
|
||||||
|
currentGlobalRegexRuleId = actionEl.dataset.ruleId || "";
|
||||||
|
_refreshTaskProfileWorkspace();
|
||||||
|
return;
|
||||||
|
case "restore-global-regex-defaults": {
|
||||||
|
const confirmed = window.confirm(
|
||||||
|
"这会将通用正则规则恢复为默认配置。是否继续?",
|
||||||
|
);
|
||||||
|
if (!confirmed) return;
|
||||||
|
currentGlobalRegexRuleId = "";
|
||||||
|
_patchGlobalTaskRegex(createDefaultGlobalTaskRegex(), { refresh: true });
|
||||||
|
toastr.success("通用正则规则已恢复默认", "ST-BME");
|
||||||
|
return;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -5853,6 +6016,14 @@ function _renderTaskProfileWorkspace(state) {
|
|||||||
.join("")}
|
.join("")}
|
||||||
</div>
|
</div>
|
||||||
<div class="bme-task-action-bar-right">
|
<div class="bme-task-action-bar-right">
|
||||||
|
<button
|
||||||
|
class="bme-config-secondary-btn bme-bulk-profile-btn ${state.showGlobalRegex ? "active" : ""}"
|
||||||
|
data-task-action="toggle-global-regex"
|
||||||
|
type="button"
|
||||||
|
title="打开或收起通用正则规则面板"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-filter"></i><span>通用正则</span>
|
||||||
|
</button>
|
||||||
<button class="bme-config-secondary-btn bme-bulk-profile-btn bme-task-btn-danger" data-task-action="restore-all-profiles" type="button" title="恢复全部 6 个任务的默认预设">
|
<button class="bme-config-secondary-btn bme-bulk-profile-btn bme-task-btn-danger" data-task-action="restore-all-profiles" type="button" title="恢复全部 6 个任务的默认预设">
|
||||||
<i class="fa-solid fa-arrows-rotate"></i><span>恢复全部</span>
|
<i class="fa-solid fa-arrows-rotate"></i><span>恢复全部</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -5865,6 +6036,8 @@ function _renderTaskProfileWorkspace(state) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
${state.showGlobalRegex ? _renderGlobalRegexPanel(state) : ""}
|
||||||
|
|
||||||
<div class="bme-task-master-detail">
|
<div class="bme-task-master-detail">
|
||||||
<div class="bme-task-profile-editor">
|
<div class="bme-task-profile-editor">
|
||||||
<div class="bme-task-editor-header">
|
<div class="bme-task-editor-header">
|
||||||
@@ -5921,8 +6094,6 @@ function _renderTaskProfileWorkspace(state) {
|
|||||||
${
|
${
|
||||||
state.taskTabId === "generation"
|
state.taskTabId === "generation"
|
||||||
? _renderTaskGenerationTab(state)
|
? _renderTaskGenerationTab(state)
|
||||||
: state.taskTabId === "regex"
|
|
||||||
? _renderTaskRegexTab(state)
|
|
||||||
: state.taskTabId === "debug"
|
: state.taskTabId === "debug"
|
||||||
? _renderTaskDebugTab(state)
|
? _renderTaskDebugTab(state)
|
||||||
: _renderTaskPromptTab(state)
|
: _renderTaskPromptTab(state)
|
||||||
@@ -5933,7 +6104,6 @@ function _renderTaskProfileWorkspace(state) {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _renderTaskPromptTab(state) {
|
function _renderTaskPromptTab(state) {
|
||||||
return `
|
return `
|
||||||
<div class="bme-task-editor-grid">
|
<div class="bme-task-editor-grid">
|
||||||
@@ -6026,30 +6196,61 @@ function _renderTaskGenerationTab(state) {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _renderTaskRegexTab(state) {
|
function _renderTaskRegexTab(state, options = {}) {
|
||||||
const regex = state.profile.regex || {};
|
const regex = options.regex || state.profile?.regex || {};
|
||||||
|
const regexRules = Array.isArray(options.regexRules)
|
||||||
|
? options.regexRules
|
||||||
|
: state.regexRules;
|
||||||
|
const selectedRule =
|
||||||
|
options.selectedRule === undefined ? state.selectedRule : options.selectedRule;
|
||||||
const normalizedStages = normalizeTaskRegexStages(regex.stages || {});
|
const normalizedStages = normalizeTaskRegexStages(regex.stages || {});
|
||||||
|
const selectAction = options.selectAction || "select-regex-rule";
|
||||||
|
const deleteAction = options.deleteAction || "delete-regex-rule";
|
||||||
|
const addAction = options.addAction || "add-regex-rule";
|
||||||
|
const addButtonLabel = options.addButtonLabel || "+ 新增规则";
|
||||||
|
const wrapperClassName = options.wrapperClassName
|
||||||
|
? ` ${options.wrapperClassName}`
|
||||||
|
: "";
|
||||||
|
const sectionTitle = options.sectionTitle || "复用与阶段";
|
||||||
|
const sectionSubtitle =
|
||||||
|
options.sectionSubtitle ||
|
||||||
|
"任务预设可复用酒馆正则,并叠加当前任务自己的附加规则。";
|
||||||
|
const rulesTitle = options.rulesTitle || "本地附加规则";
|
||||||
|
const rulesSubtitle =
|
||||||
|
options.rulesSubtitle ||
|
||||||
|
"本地规则只作用于当前任务预设,不会污染宿主酒馆配置。";
|
||||||
|
const emptyText = options.emptyText || "当前预设还没有本地正则规则。";
|
||||||
|
const defaultNamePrefix = options.defaultNamePrefix || "本地规则";
|
||||||
|
const headerExtraActions = options.extraHeaderActions || "";
|
||||||
|
const editorState = {
|
||||||
|
...state,
|
||||||
|
selectedRule,
|
||||||
|
};
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="bme-task-tab-body">
|
<div class="bme-task-tab-body${wrapperClassName}">
|
||||||
<div class="bme-task-regex-top">
|
<div class="bme-task-regex-top">
|
||||||
<div class="bme-config-card">
|
<div class="bme-config-card">
|
||||||
<div class="bme-config-card-head">
|
<div class="bme-config-card-head">
|
||||||
<div>
|
<div>
|
||||||
<div class="bme-config-card-title">复用与阶段</div>
|
<div class="bme-config-card-title">${_escHtml(sectionTitle)}</div>
|
||||||
<div class="bme-config-card-subtitle">
|
<div class="bme-config-card-subtitle">
|
||||||
任务预设可复用酒馆正则,并叠加当前任务自己的附加规则。
|
${_escHtml(sectionSubtitle)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="bme-task-inline-actions">
|
||||||
<button class="bme-config-secondary-btn" data-task-action="inspect-tavern-regex" type="button">
|
<button class="bme-config-secondary-btn" data-task-action="inspect-tavern-regex" type="button">
|
||||||
查看当前复用规则
|
查看当前复用规则
|
||||||
</button>
|
</button>
|
||||||
|
${headerExtraActions}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bme-task-toggle-list">
|
<div class="bme-task-toggle-list">
|
||||||
<label class="bme-toggle-item">
|
<label class="bme-toggle-item">
|
||||||
<span class="bme-toggle-copy">
|
<span class="bme-toggle-copy">
|
||||||
<span class="bme-toggle-title">启用任务正则</span>
|
<span class="bme-toggle-title">启用任务正则</span>
|
||||||
<span class="bme-toggle-desc">关闭后当前预设不执行任何任务级正则。</span>
|
<span class="bme-toggle-desc">关闭后当前配置不执行任何任务级正则。</span>
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -6119,24 +6320,30 @@ function _renderTaskRegexTab(state) {
|
|||||||
<div class="bme-config-card">
|
<div class="bme-config-card">
|
||||||
<div class="bme-config-card-head">
|
<div class="bme-config-card-head">
|
||||||
<div>
|
<div>
|
||||||
<div class="bme-config-card-title">本地附加规则</div>
|
<div class="bme-config-card-title">${_escHtml(rulesTitle)}</div>
|
||||||
<div class="bme-config-card-subtitle">
|
<div class="bme-config-card-subtitle">
|
||||||
本地规则只作用于当前任务预设,不会污染宿主酒馆配置。
|
${_escHtml(rulesSubtitle)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="bme-config-secondary-btn" data-task-action="add-regex-rule" type="button">
|
<button class="bme-config-secondary-btn" data-task-action="${_escAttr(addAction)}" type="button">
|
||||||
+ 新增规则
|
${_escHtml(addButtonLabel)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bme-task-list">
|
<div class="bme-task-list">
|
||||||
${state.regexRules.length
|
${regexRules.length
|
||||||
? state.regexRules
|
? regexRules
|
||||||
.map((rule, index) => _renderRegexRuleListItem(rule, index, state))
|
.map((rule, index) =>
|
||||||
|
_renderRegexRuleListItem(rule, index, editorState, {
|
||||||
|
selectAction,
|
||||||
|
deleteAction,
|
||||||
|
defaultNamePrefix,
|
||||||
|
})
|
||||||
|
)
|
||||||
.join("")
|
.join("")
|
||||||
: `
|
: `
|
||||||
<div class="bme-task-empty">
|
<div class="bme-task-empty">
|
||||||
当前预设还没有本地正则规则。
|
${_escHtml(emptyText)}
|
||||||
</div>
|
</div>
|
||||||
`}
|
`}
|
||||||
</div>
|
</div>
|
||||||
@@ -6144,12 +6351,41 @@ function _renderTaskRegexTab(state) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bme-config-card">
|
<div class="bme-config-card">
|
||||||
${_renderRegexRuleEditor(state)}
|
${_renderRegexRuleEditor(editorState)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _renderGlobalRegexPanel(state) {
|
||||||
|
return _renderTaskRegexTab(
|
||||||
|
{
|
||||||
|
...state,
|
||||||
|
selectedRule: state.selectedGlobalRegexRule,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regex: state.globalTaskRegex,
|
||||||
|
regexRules: state.globalRegexRules,
|
||||||
|
selectedRule: state.selectedGlobalRegexRule,
|
||||||
|
addAction: "add-global-regex-rule",
|
||||||
|
selectAction: "select-global-regex-rule",
|
||||||
|
deleteAction: "delete-global-regex-rule",
|
||||||
|
addButtonLabel: "+ 新增通用规则",
|
||||||
|
wrapperClassName: "bme-global-regex-panel",
|
||||||
|
sectionTitle: "通用正则设置",
|
||||||
|
sectionSubtitle: "所有任务共享同一套任务正则开关、复用来源、执行阶段与附加规则。",
|
||||||
|
rulesTitle: "通用附加规则",
|
||||||
|
rulesSubtitle: "这里维护所有任务共享的附加规则。",
|
||||||
|
emptyText: "当前还没有通用正则规则。",
|
||||||
|
defaultNamePrefix: "通用规则",
|
||||||
|
extraHeaderActions: `
|
||||||
|
<button class="bme-config-secondary-btn bme-task-btn-danger" data-task-action="restore-global-regex-defaults" type="button">
|
||||||
|
恢复默认
|
||||||
|
</button>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
function _formatRegexReuseSourceState(source = {}) {
|
function _formatRegexReuseSourceState(source = {}) {
|
||||||
const states = [];
|
const states = [];
|
||||||
states.push(source.enabled ? "已启用" : "已关闭");
|
states.push(source.enabled ? "已启用" : "已关闭");
|
||||||
@@ -7238,19 +7474,23 @@ function _renderGenerationField(field, value, state = {}) {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _renderRegexRuleListItem(rule, index, state) {
|
function _renderRegexRuleListItem(rule, index, state, options = {}) {
|
||||||
const isSelected = rule.id === state.selectedRule?.id;
|
const isSelected = rule.id === state.selectedRule?.id;
|
||||||
|
const selectAction = options.selectAction || "select-regex-rule";
|
||||||
|
const deleteAction = options.deleteAction || "delete-regex-rule";
|
||||||
|
const defaultNamePrefix = options.defaultNamePrefix || "本地规则";
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="bme-task-list-entry">
|
<div class="bme-task-list-entry">
|
||||||
<button
|
<button
|
||||||
class="bme-task-list-item ${isSelected ? "active" : ""}"
|
class="bme-task-list-item ${isSelected ? "active" : ""}"
|
||||||
data-task-action="select-regex-rule"
|
data-task-action="${_escAttr(selectAction)}"
|
||||||
data-rule-id="${_escAttr(rule.id)}"
|
data-rule-id="${_escAttr(rule.id)}"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<span class="bme-task-list-index">#${index + 1}</span>
|
<span class="bme-task-list-index">#${index + 1}</span>
|
||||||
<span class="bme-task-list-copy">
|
<span class="bme-task-list-copy">
|
||||||
<span class="bme-task-list-title">${_escHtml(rule.script_name || `本地规则 ${index + 1}`)}</span>
|
<span class="bme-task-list-title">${_escHtml(rule.script_name || `${defaultNamePrefix} ${index + 1}`)}</span>
|
||||||
<span class="bme-task-list-meta">
|
<span class="bme-task-list-meta">
|
||||||
${rule.enabled ? "启用" : "停用"} · ${_escHtml(rule.find_regex || "(未填写 find_regex)")}
|
${rule.enabled ? "启用" : "停用"} · ${_escHtml(rule.find_regex || "(未填写 find_regex)")}
|
||||||
</span>
|
</span>
|
||||||
@@ -7259,7 +7499,7 @@ function _renderRegexRuleListItem(rule, index, state) {
|
|||||||
<div class="bme-task-inline-actions">
|
<div class="bme-task-inline-actions">
|
||||||
<button
|
<button
|
||||||
class="bme-config-secondary-btn bme-task-mini-btn"
|
class="bme-config-secondary-btn bme-task-mini-btn"
|
||||||
data-task-action="delete-regex-rule"
|
data-task-action="${_escAttr(deleteAction)}"
|
||||||
data-rule-id="${_escAttr(rule.id)}"
|
data-rule-id="${_escAttr(rule.id)}"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
@@ -7269,7 +7509,6 @@ function _renderRegexRuleListItem(rule, index, state) {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _renderRegexRuleEditor(state) {
|
function _renderRegexRuleEditor(state) {
|
||||||
const rule = state.selectedRule;
|
const rule = state.selectedRule;
|
||||||
if (!rule) {
|
if (!rule) {
|
||||||
@@ -7627,6 +7866,110 @@ function _persistSelectedRegexRuleField(target, refresh) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _deleteGlobalRegexRule(ruleId) {
|
||||||
|
if (!ruleId) return;
|
||||||
|
_updateGlobalTaskRegex((draft) => {
|
||||||
|
const localRules = Array.isArray(draft.localRules) ? [...draft.localRules] : [];
|
||||||
|
const index = localRules.findIndex((item) => item.id === ruleId);
|
||||||
|
if (index < 0) return null;
|
||||||
|
localRules.splice(index, 1);
|
||||||
|
draft.localRules = localRules;
|
||||||
|
return {
|
||||||
|
selectRuleId:
|
||||||
|
localRules[Math.max(0, index - 1)]?.id || localRules[0]?.id || "",
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function _persistGlobalRegexField(target, refresh) {
|
||||||
|
const key = target.dataset.regexField;
|
||||||
|
if (!key) return;
|
||||||
|
|
||||||
|
_updateGlobalTaskRegex(
|
||||||
|
(draft) => {
|
||||||
|
draft[key] =
|
||||||
|
target instanceof HTMLInputElement && target.type === "checkbox"
|
||||||
|
? Boolean(target.checked)
|
||||||
|
: target.value;
|
||||||
|
},
|
||||||
|
{ refresh },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _persistGlobalRegexSourceField(target, refresh) {
|
||||||
|
const sourceKey = target.dataset.regexSource;
|
||||||
|
if (!sourceKey) return;
|
||||||
|
|
||||||
|
_updateGlobalTaskRegex(
|
||||||
|
(draft) => {
|
||||||
|
draft.sources = {
|
||||||
|
...(draft.sources || {}),
|
||||||
|
[sourceKey]: Boolean(target.checked),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{ refresh },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _persistGlobalRegexStageField(target, refresh) {
|
||||||
|
const stageKey = target.dataset.regexStage;
|
||||||
|
if (!stageKey) return;
|
||||||
|
|
||||||
|
_updateGlobalTaskRegex(
|
||||||
|
(draft) => {
|
||||||
|
draft.stages = {
|
||||||
|
...(draft.stages || {}),
|
||||||
|
[stageKey]: Boolean(target.checked),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{ refresh },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _persistSelectedGlobalRegexRuleField(target, refresh) {
|
||||||
|
_updateGlobalTaskRegex(
|
||||||
|
(draft) => {
|
||||||
|
const localRules = Array.isArray(draft.localRules) ? [...draft.localRules] : [];
|
||||||
|
const rule = localRules.find((item) => item.id === currentGlobalRegexRuleId);
|
||||||
|
if (!rule) return null;
|
||||||
|
|
||||||
|
if (target.dataset.regexRuleField) {
|
||||||
|
const field = target.dataset.regexRuleField;
|
||||||
|
if (target instanceof HTMLInputElement && target.type === "checkbox") {
|
||||||
|
rule[field] = Boolean(target.checked);
|
||||||
|
} else if (["min_depth", "max_depth"].includes(field)) {
|
||||||
|
const parsed = Number.parseInt(String(target.value || "").trim(), 10);
|
||||||
|
rule[field] = Number.isFinite(parsed) ? parsed : 0;
|
||||||
|
} else if (field === "trim_strings") {
|
||||||
|
rule[field] = String(target.value || "");
|
||||||
|
} else {
|
||||||
|
rule[field] = String(target.value || "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.dataset.regexRuleSource) {
|
||||||
|
const sourceKey = target.dataset.regexRuleSource;
|
||||||
|
rule.source = {
|
||||||
|
...(rule.source || {}),
|
||||||
|
[sourceKey]: Boolean(target.checked),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.dataset.regexRuleDestination) {
|
||||||
|
const destinationKey = target.dataset.regexRuleDestination;
|
||||||
|
rule.destination = {
|
||||||
|
...(rule.destination || {}),
|
||||||
|
[destinationKey]: Boolean(target.checked),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
draft.localRules = localRules;
|
||||||
|
return { selectRuleId: rule.id };
|
||||||
|
},
|
||||||
|
{ refresh },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function _updateCurrentTaskProfile(mutator, options = {}) {
|
function _updateCurrentTaskProfile(mutator, options = {}) {
|
||||||
const settings = _getSettings?.() || {};
|
const settings = _getSettings?.() || {};
|
||||||
const taskProfiles = ensureTaskProfiles(settings);
|
const taskProfiles = ensureTaskProfiles(settings);
|
||||||
@@ -7751,9 +8094,139 @@ function _parseTaskWorkspaceValue(target, valueType = "text") {
|
|||||||
return String(target.value || "").trim();
|
return String(target.value || "").trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _downloadTaskProfile(taskProfiles, taskType, profile) {
|
function _isGlobalRegexPanelTarget(target) {
|
||||||
|
return target instanceof HTMLElement && Boolean(target.closest(".bme-global-regex-panel"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function _normalizeGlobalRegexDraft(regex = {}) {
|
||||||
|
const normalized = normalizeGlobalTaskRegex(regex || {}, "global");
|
||||||
|
return {
|
||||||
|
...normalized,
|
||||||
|
sources: {
|
||||||
|
...(normalized.sources || {}),
|
||||||
|
},
|
||||||
|
stages: {
|
||||||
|
...normalizeTaskRegexStages(normalized.stages || {}),
|
||||||
|
},
|
||||||
|
localRules: Array.isArray(normalized.localRules)
|
||||||
|
? normalized.localRules.map((rule, index) =>
|
||||||
|
createLocalRegexRule("global", {
|
||||||
|
...rule,
|
||||||
|
id: String(rule?.id || `global-rule-${index + 1}`),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function _mergeImportedGlobalRegex(currentGlobalRegex = {}, importedGlobalRegex = null) {
|
||||||
|
const current = _normalizeGlobalRegexDraft(currentGlobalRegex);
|
||||||
|
if (
|
||||||
|
!importedGlobalRegex ||
|
||||||
|
typeof importedGlobalRegex !== "object" ||
|
||||||
|
Array.isArray(importedGlobalRegex)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
globalTaskRegex: current,
|
||||||
|
mergedRuleCount: 0,
|
||||||
|
replacedConfig: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const imported = _normalizeGlobalRegexDraft(importedGlobalRegex);
|
||||||
|
const mergedRules = dedupeRegexRules(
|
||||||
|
[
|
||||||
|
...(Array.isArray(current.localRules) ? current.localRules : []),
|
||||||
|
...(Array.isArray(imported.localRules) ? imported.localRules : []),
|
||||||
|
],
|
||||||
|
"global",
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
globalTaskRegex: {
|
||||||
|
...imported,
|
||||||
|
localRules: mergedRules,
|
||||||
|
},
|
||||||
|
mergedRuleCount: Math.max(
|
||||||
|
0,
|
||||||
|
mergedRules.length -
|
||||||
|
(Array.isArray(current.localRules) ? current.localRules.length : 0),
|
||||||
|
),
|
||||||
|
replacedConfig: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function _mergeProfileRegexRulesIntoGlobal(currentGlobalRegex = {}, profile = null) {
|
||||||
|
const current = _normalizeGlobalRegexDraft(currentGlobalRegex);
|
||||||
|
const legacyRules = Array.isArray(profile?.regex?.localRules)
|
||||||
|
? profile.regex.localRules
|
||||||
|
: [];
|
||||||
|
if (legacyRules.length === 0) {
|
||||||
|
return {
|
||||||
|
globalTaskRegex: current,
|
||||||
|
mergedRuleCount: 0,
|
||||||
|
profile,
|
||||||
|
clearedLegacyRules: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mergedRules = dedupeRegexRules(
|
||||||
|
[...(current.localRules || []), ...legacyRules],
|
||||||
|
"global",
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
globalTaskRegex: {
|
||||||
|
...current,
|
||||||
|
localRules: mergedRules,
|
||||||
|
},
|
||||||
|
mergedRuleCount: Math.max(0, mergedRules.length - current.localRules.length),
|
||||||
|
profile: {
|
||||||
|
...(profile || {}),
|
||||||
|
regex: {},
|
||||||
|
},
|
||||||
|
clearedLegacyRules: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function _patchGlobalTaskRegex(globalTaskRegex, options = {}) {
|
||||||
|
return _patchSettings(
|
||||||
|
{
|
||||||
|
globalTaskRegex: _normalizeGlobalRegexDraft(globalTaskRegex),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
refreshTaskWorkspace: options.refresh !== false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _updateGlobalTaskRegex(mutator, options = {}) {
|
||||||
|
const settings = _getSettings?.() || {};
|
||||||
|
const draft = _normalizeGlobalRegexDraft(_cloneJson(settings.globalTaskRegex || {}));
|
||||||
|
const mutationResult = mutator?.(draft, { settings });
|
||||||
|
if (mutationResult === null) return null;
|
||||||
|
|
||||||
|
const result = mutationResult || {};
|
||||||
|
const nextRegex = _normalizeGlobalRegexDraft(result.globalTaskRegex || draft);
|
||||||
|
if (Object.prototype.hasOwnProperty.call(result, "selectRuleId")) {
|
||||||
|
currentGlobalRegexRuleId = result.selectRuleId || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return _patchSettings(
|
||||||
|
{
|
||||||
|
globalTaskRegex: nextRegex,
|
||||||
|
...(result.extraSettingsPatch || {}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
refreshTaskWorkspace:
|
||||||
|
result.refresh === undefined ? options.refresh !== false : result.refresh,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _downloadTaskProfile(taskProfiles, taskType, profile, globalTaskRegex = {}) {
|
||||||
try {
|
try {
|
||||||
const payload = serializeTaskProfile(taskProfiles, taskType, profile?.id || "");
|
const payload = serializeTaskProfile(taskProfiles, taskType, profile?.id || "");
|
||||||
|
payload.globalTaskRegex = _normalizeGlobalRegexDraft(globalTaskRegex || {});
|
||||||
const fileName = _sanitizeFileName(
|
const fileName = _sanitizeFileName(
|
||||||
`st-bme-${taskType}-${profile?.name || "profile"}.json`,
|
`st-bme-${taskType}-${profile?.name || "profile"}.json`,
|
||||||
);
|
);
|
||||||
@@ -7774,12 +8247,11 @@ function _downloadTaskProfile(taskProfiles, taskType, profile) {
|
|||||||
toastr.error(`预设导出失败: ${error?.message || error}`, "ST-BME");
|
toastr.error(`预设导出失败: ${error?.message || error}`, "ST-BME");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _sanitizeFileName(fileName = "profile.json") {
|
function _sanitizeFileName(fileName = "profile.json") {
|
||||||
return String(fileName || "profile.json").replace(/[<>:"/\\|?*\x00-\x1f]/g, "-");
|
return String(fileName || "profile.json").replace(/[<>:"/\\|?*\x00-\x1f]/g, "-");
|
||||||
}
|
}
|
||||||
|
|
||||||
function _downloadAllTaskProfiles(taskProfiles) {
|
function _downloadAllTaskProfiles(taskProfiles, globalTaskRegex = {}) {
|
||||||
try {
|
try {
|
||||||
const taskTypes = getTaskTypeOptions().map((t) => t.id);
|
const taskTypes = getTaskTypeOptions().map((t) => t.id);
|
||||||
const profiles = {};
|
const profiles = {};
|
||||||
@@ -7799,6 +8271,7 @@ function _downloadAllTaskProfiles(taskProfiles) {
|
|||||||
format: "st-bme-all-task-profiles",
|
format: "st-bme-all-task-profiles",
|
||||||
version: 1,
|
version: 1,
|
||||||
exportedAt: new Date().toISOString(),
|
exportedAt: new Date().toISOString(),
|
||||||
|
globalTaskRegex: _normalizeGlobalRegexDraft(globalTaskRegex || {}),
|
||||||
profiles,
|
profiles,
|
||||||
};
|
};
|
||||||
const blob = new Blob([JSON.stringify(payload, null, 2)], {
|
const blob = new Blob([JSON.stringify(payload, null, 2)], {
|
||||||
@@ -7818,7 +8291,6 @@ function _downloadAllTaskProfiles(taskProfiles) {
|
|||||||
toastr.error(`导出全部预设失败: ${error?.message || error}`, "ST-BME");
|
toastr.error(`导出全部预设失败: ${error?.message || error}`, "ST-BME");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _cloneJson(value) {
|
function _cloneJson(value) {
|
||||||
return JSON.parse(JSON.stringify(value ?? null));
|
return JSON.parse(JSON.stringify(value ?? null));
|
||||||
}
|
}
|
||||||
@@ -8356,3 +8828,5 @@ function _getNodeSnippet(node) {
|
|||||||
function _isMobile() {
|
function _isMobile() {
|
||||||
return window.innerWidth <= 768;
|
return window.innerWidth <= 768;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user