2026-07-31 16:22:09 +08:00
|
|
|
const AUTOMATION_TYPES = {
|
|
|
|
|
ACCEPT: "AUTO_ACCEPT",
|
|
|
|
|
OPEN_RX: "AUTO_OPEN_RX",
|
|
|
|
|
PASS_RX: "AUTO_PASS_RX",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const DEFAULT_AUTOMATION_CONFIG = {
|
|
|
|
|
autoAcceptOrder: false,
|
|
|
|
|
autoOpenRx: false,
|
|
|
|
|
autoPassRx: false,
|
2026-09-09 11:24:01 +08:00
|
|
|
// Preserve the existing behaviour for institutions with no saved value.
|
|
|
|
|
enableRationalDrug: true,
|
2026-07-31 16:22:09 +08:00
|
|
|
autoAcceptDelayMinSeconds: 2,
|
|
|
|
|
autoAcceptDelayMaxSeconds: 5,
|
|
|
|
|
autoOpenRxDelayMinSeconds: 20,
|
|
|
|
|
autoOpenRxDelayMaxSeconds: 40,
|
|
|
|
|
autoPassRxDelayMinSeconds: 10,
|
|
|
|
|
autoPassRxDelayMaxSeconds: 30,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const TYPE_CONFIG = {
|
|
|
|
|
[AUTOMATION_TYPES.ACCEPT]: {
|
|
|
|
|
enabledKey: "autoAcceptOrder",
|
|
|
|
|
minKey: "autoAcceptDelayMinSeconds",
|
|
|
|
|
maxKey: "autoAcceptDelayMaxSeconds",
|
|
|
|
|
},
|
|
|
|
|
[AUTOMATION_TYPES.OPEN_RX]: {
|
|
|
|
|
enabledKey: "autoOpenRx",
|
|
|
|
|
minKey: "autoOpenRxDelayMinSeconds",
|
|
|
|
|
maxKey: "autoOpenRxDelayMaxSeconds",
|
|
|
|
|
},
|
|
|
|
|
[AUTOMATION_TYPES.PASS_RX]: {
|
|
|
|
|
enabledKey: "autoPassRx",
|
|
|
|
|
minKey: "autoPassRxDelayMinSeconds",
|
|
|
|
|
maxKey: "autoPassRxDelayMaxSeconds",
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const AUTOMATION_DELAY_KEYS = [
|
|
|
|
|
"autoAcceptDelayMinSeconds",
|
|
|
|
|
"autoAcceptDelayMaxSeconds",
|
|
|
|
|
"autoOpenRxDelayMinSeconds",
|
|
|
|
|
"autoOpenRxDelayMaxSeconds",
|
|
|
|
|
"autoPassRxDelayMinSeconds",
|
|
|
|
|
"autoPassRxDelayMaxSeconds",
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const AUTOMATION_DELAY_PAIRS = [
|
|
|
|
|
["autoAcceptDelayMinSeconds", "autoAcceptDelayMaxSeconds"],
|
|
|
|
|
["autoOpenRxDelayMinSeconds", "autoOpenRxDelayMaxSeconds"],
|
|
|
|
|
["autoPassRxDelayMinSeconds", "autoPassRxDelayMaxSeconds"],
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
function normalizeNonNegativeInteger(value, fallback) {
|
|
|
|
|
return Number.isInteger(value) && value >= 0 ? value : fallback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function normalizeAutomationConfig(config = {}) {
|
|
|
|
|
const result = {
|
|
|
|
|
...DEFAULT_AUTOMATION_CONFIG,
|
|
|
|
|
...config,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Object.values(TYPE_CONFIG).forEach(({ minKey, maxKey }) => {
|
|
|
|
|
const defaultMin = DEFAULT_AUTOMATION_CONFIG[minKey];
|
|
|
|
|
const defaultMax = DEFAULT_AUTOMATION_CONFIG[maxKey];
|
|
|
|
|
result[minKey] = normalizeNonNegativeInteger(config[minKey], defaultMin);
|
|
|
|
|
result[maxKey] = normalizeNonNegativeInteger(config[maxKey], defaultMax);
|
|
|
|
|
if (result[minKey] > result[maxKey]) {
|
|
|
|
|
result[minKey] = defaultMin;
|
|
|
|
|
result[maxKey] = defaultMax;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
result.autoAcceptOrder = config.autoAcceptOrder === true;
|
|
|
|
|
result.autoOpenRx = config.autoOpenRx === true;
|
|
|
|
|
result.autoPassRx = config.autoPassRx === true;
|
2026-09-09 11:24:01 +08:00
|
|
|
result.enableRationalDrug = config.enableRationalDrug !== false;
|
2026-07-31 16:22:09 +08:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getTypeConfig(config, type) {
|
|
|
|
|
const normalized = normalizeAutomationConfig(config);
|
|
|
|
|
const mapping = TYPE_CONFIG[type];
|
|
|
|
|
if (!mapping) {
|
|
|
|
|
throw new Error(`未知自动化任务类型: ${type}`);
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
enabled: normalized[mapping.enabledKey] === true,
|
|
|
|
|
minSeconds: normalized[mapping.minKey],
|
|
|
|
|
maxSeconds: normalized[mapping.maxKey],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function randomInteger(min, max, random = Math.random) {
|
|
|
|
|
if (min === max) return min;
|
|
|
|
|
return Math.floor(random() * (max - min + 1)) + min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function validateAutomationDelayConfig(input = {}, current = {}) {
|
|
|
|
|
const data = {};
|
|
|
|
|
for (const key of AUTOMATION_DELAY_KEYS) {
|
|
|
|
|
if (key in input) {
|
|
|
|
|
if (!Number.isInteger(input[key]) || input[key] < 0 || input[key] > 3600) {
|
|
|
|
|
return {
|
|
|
|
|
success: false,
|
|
|
|
|
message: `${key}必须是0到3600之间的整数`,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
data[key] = input[key];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const merged = {
|
|
|
|
|
...normalizeAutomationConfig(current),
|
|
|
|
|
...data,
|
|
|
|
|
};
|
|
|
|
|
for (const [minKey, maxKey] of AUTOMATION_DELAY_PAIRS) {
|
|
|
|
|
if (merged[minKey] > merged[maxKey]) {
|
|
|
|
|
return {
|
|
|
|
|
success: false,
|
|
|
|
|
message: `${minKey}不能大于${maxKey}`,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return { success: true, data };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
AUTOMATION_TYPES,
|
|
|
|
|
DEFAULT_AUTOMATION_CONFIG,
|
|
|
|
|
TYPE_CONFIG,
|
|
|
|
|
AUTOMATION_DELAY_KEYS,
|
|
|
|
|
AUTOMATION_DELAY_PAIRS,
|
|
|
|
|
normalizeAutomationConfig,
|
|
|
|
|
getTypeConfig,
|
|
|
|
|
randomInteger,
|
|
|
|
|
validateAutomationDelayConfig,
|
|
|
|
|
};
|