优化定时器
This commit is contained in:
@@ -212,7 +212,9 @@ const syncAutotkPermissionLimit = async () => {
|
|||||||
if (!isElectron()) return
|
if (!isElectron()) return
|
||||||
try {
|
try {
|
||||||
const permissions = getPermissions()
|
const permissions = getPermissions()
|
||||||
if (permissions?.autotk === 1) return
|
const hasAutotkPermission = permissions?.autotk === 1
|
||||||
|
const hasWebAiPermission = permissions?.webAi === 1
|
||||||
|
if (hasAutotkPermission || hasWebAiPermission) return
|
||||||
await window.electronAPI.updateAutomationConfig({
|
await window.electronAPI.updateAutomationConfig({
|
||||||
filters: {
|
filters: {
|
||||||
maxAnchorCount: 1
|
maxAnchorCount: 1
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
|
|||||||
import { isElectron } from '../utils/electronBridge'
|
import { isElectron } from '../utils/electronBridge'
|
||||||
import { getPermissions } from '@/utils/storage'
|
import { getPermissions } from '@/utils/storage'
|
||||||
import { usePythonBridge } from '@/utils/pythonBridge'
|
import { usePythonBridge } from '@/utils/pythonBridge'
|
||||||
|
import { ensureHostListGateMonitorRunning, stopHostListGateMonitor, syncHostListGateDecision } from '@/utils/hostListGateMonitor'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: { type: Boolean, required: true }
|
visible: { type: Boolean, required: true }
|
||||||
@@ -339,11 +340,12 @@ const maxCount = ref()
|
|||||||
const checkTaskGateState = ref(null)
|
const checkTaskGateState = ref(null)
|
||||||
const selectedLevels = ref(new Set())
|
const selectedLevels = ref(new Set())
|
||||||
const showLevelDropdown = ref(false)
|
const showLevelDropdown = ref(false)
|
||||||
const hostListDialogInstanceId = `host-list-dialog-${Math.random().toString(36).slice(2)}`
|
|
||||||
|
|
||||||
const resolveRestrictedMaxAnchorCount = (fallbackValue = 9999999) => {
|
const resolveRestrictedMaxAnchorCount = (fallbackValue = 9999999) => {
|
||||||
const permissions = getPermissions()
|
const permissions = getPermissions()
|
||||||
return permissions?.webAi === 1 ? fallbackValue : 0
|
const hasAutotkPermission = permissions?.autotk === 1
|
||||||
|
const hasWebAiPermission = permissions?.webAi === 1
|
||||||
|
return hasAutotkPermission || hasWebAiPermission ? fallbackValue : 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加主播弹窗状态
|
// 添加主播弹窗状态
|
||||||
@@ -402,23 +404,17 @@ watch(() => props.visible, (newVal) => {
|
|||||||
if (newVal) {
|
if (newVal) {
|
||||||
document.body.style.overflow = 'hidden'
|
document.body.style.overflow = 'hidden'
|
||||||
loadLocalGateConfig()
|
loadLocalGateConfig()
|
||||||
if (gateEnabled.value) {
|
if (gateEnabled.value) ensureHostListGateMonitorRunning()
|
||||||
claimGateOwnership()
|
|
||||||
}
|
|
||||||
loadHosts()
|
loadHosts()
|
||||||
loadConfig()
|
loadConfig()
|
||||||
} else {
|
} else {
|
||||||
document.body.style.overflow = ''
|
document.body.style.overflow = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshHostListMonitor()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadLocalGateConfig()
|
loadLocalGateConfig()
|
||||||
if (gateEnabled.value) {
|
if (gateEnabled.value) ensureHostListGateMonitorRunning()
|
||||||
claimGateOwnership()
|
|
||||||
}
|
|
||||||
loadConfig()
|
loadConfig()
|
||||||
|
|
||||||
if (props.visible) {
|
if (props.visible) {
|
||||||
@@ -426,11 +422,13 @@ onMounted(() => {
|
|||||||
loadHosts()
|
loadHosts()
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshHostListMonitor()
|
if (gateEnabled.value) {
|
||||||
|
void syncHostListGateDecision(true)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
releaseGateOwnership()
|
document.body.style.overflow = ''
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听过滤器变化,同步到后端配置
|
// 监听过滤器变化,同步到后端配置
|
||||||
@@ -501,76 +499,6 @@ const loadConfig = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getGateRuntime = () => {
|
|
||||||
if (typeof window === 'undefined') {
|
|
||||||
return { ownerId: null, timer: null }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!window.__hostListGateRuntime) {
|
|
||||||
window.__hostListGateRuntime = {
|
|
||||||
ownerId: null,
|
|
||||||
timer: null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return window.__hostListGateRuntime
|
|
||||||
}
|
|
||||||
|
|
||||||
const isGateOwner = () => {
|
|
||||||
return getGateRuntime().ownerId === hostListDialogInstanceId
|
|
||||||
}
|
|
||||||
|
|
||||||
const claimGateOwnership = () => {
|
|
||||||
const runtime = getGateRuntime()
|
|
||||||
if (runtime.ownerId === hostListDialogInstanceId) return
|
|
||||||
|
|
||||||
if (runtime.timer) {
|
|
||||||
clearInterval(runtime.timer)
|
|
||||||
runtime.timer = null
|
|
||||||
}
|
|
||||||
|
|
||||||
runtime.ownerId = hostListDialogInstanceId
|
|
||||||
}
|
|
||||||
|
|
||||||
const releaseGateOwnership = () => {
|
|
||||||
const runtime = getGateRuntime()
|
|
||||||
if (runtime.ownerId !== hostListDialogInstanceId) return
|
|
||||||
|
|
||||||
if (runtime.timer) {
|
|
||||||
clearInterval(runtime.timer)
|
|
||||||
runtime.timer = null
|
|
||||||
}
|
|
||||||
|
|
||||||
runtime.ownerId = null
|
|
||||||
}
|
|
||||||
|
|
||||||
const refreshHostListMonitor = () => {
|
|
||||||
if (!isElectron()) return
|
|
||||||
|
|
||||||
const runtime = getGateRuntime()
|
|
||||||
const shouldRun = gateEnabled.value && isGateOwner()
|
|
||||||
|
|
||||||
if (!shouldRun) {
|
|
||||||
if (runtime.timer && isGateOwner()) {
|
|
||||||
clearInterval(runtime.timer)
|
|
||||||
runtime.timer = null
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtime.timer) return
|
|
||||||
|
|
||||||
runtime.timer = setInterval(async () => {
|
|
||||||
if (!gateEnabled.value || !isGateOwner()) {
|
|
||||||
refreshHostListMonitor()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
await loadHosts()
|
|
||||||
await syncControlCheckTaskGate()
|
|
||||||
}, HOST_LIST_MONITOR_INTERVAL_MS)
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadLocalGateConfig = () => {
|
const loadLocalGateConfig = () => {
|
||||||
try {
|
try {
|
||||||
const savedGateEnabled = sessionStorage.getItem(HOST_LIST_GATE_ENABLED_SESSION_KEY)
|
const savedGateEnabled = sessionStorage.getItem(HOST_LIST_GATE_ENABLED_SESSION_KEY)
|
||||||
@@ -634,7 +562,6 @@ const persistGateState = (value) => {
|
|||||||
const syncControlCheckTaskGate = async (forceSync = false) => {
|
const syncControlCheckTaskGate = async (forceSync = false) => {
|
||||||
if (!isElectron()) return
|
if (!isElectron()) return
|
||||||
if (!gateEnabled.value) return
|
if (!gateEnabled.value) return
|
||||||
if (!isGateOwner()) return
|
|
||||||
|
|
||||||
const hostCount = filteredHosts.value.length
|
const hostCount = filteredHosts.value.length
|
||||||
const upperLimit = Number(maxCount.value)
|
const upperLimit = Number(maxCount.value)
|
||||||
@@ -766,16 +693,15 @@ watch(gateEnabled, async (enabled) => {
|
|||||||
persistGateEnabled()
|
persistGateEnabled()
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
claimGateOwnership()
|
ensureHostListGateMonitorRunning()
|
||||||
refreshHostListMonitor()
|
void syncHostListGateDecision(true)
|
||||||
void syncControlCheckTaskGate(true)
|
void syncControlCheckTaskGate(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
checkTaskGateState.value = null
|
checkTaskGateState.value = null
|
||||||
persistGateState(null)
|
persistGateState(null)
|
||||||
releaseGateOwnership()
|
stopHostListGateMonitor()
|
||||||
refreshHostListMonitor()
|
|
||||||
|
|
||||||
if (!isElectron()) return
|
if (!isElectron()) return
|
||||||
|
|
||||||
@@ -809,6 +735,8 @@ const filteredHosts = computed(() => {
|
|||||||
watch(
|
watch(
|
||||||
[() => filteredHosts.value.length, minCount, maxCount, gateEnabled],
|
[() => filteredHosts.value.length, minCount, maxCount, gateEnabled],
|
||||||
() => {
|
() => {
|
||||||
|
if (gateEnabled.value) ensureHostListGateMonitorRunning()
|
||||||
|
void syncHostListGateDecision()
|
||||||
void syncControlCheckTaskGate()
|
void syncControlCheckTaskGate()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,12 +30,12 @@
|
|||||||
<span class="text-base font-medium truncate">自动私信</span>
|
<span class="text-base font-medium truncate">自动私信</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- <button @click="currentView = 'auto_dm_tk'"
|
<button @click="currentView = 'auto_dm_tk'"
|
||||||
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200" style="height: 6vh;"
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200" style="height: 6vh;"
|
||||||
:class="currentView === 'auto_dm_tk' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'">
|
:class="currentView === 'auto_dm_tk' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'">
|
||||||
<img :src="currentView === 'auto_dm_tk' ? nav33 : nav3" class="w-9 h-9 object-contain flex-shrink-0" />
|
<img :src="currentView === 'auto_dm_tk' ? nav33 : nav3" class="w-9 h-9 object-contain flex-shrink-0" />
|
||||||
<span class="text-base font-medium truncate">自动私信TK版</span>
|
<span class="text-base font-medium truncate">自动私信TK版</span>
|
||||||
</button> -->
|
</button>
|
||||||
|
|
||||||
<button @click="currentView = 'FanWorkbench'"
|
<button @click="currentView = 'FanWorkbench'"
|
||||||
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200" style="height: 6vh;"
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200" style="height: 6vh;"
|
||||||
|
|||||||
143
src/utils/hostListGateMonitor.js
Normal file
143
src/utils/hostListGateMonitor.js
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
import { isElectron } from '@/utils/electronBridge'
|
||||||
|
|
||||||
|
const HOST_LIST_MIN_COUNT_KEY = 'host_list_dialog_min_count'
|
||||||
|
const HOST_LIST_GATE_ENABLED_SESSION_KEY = 'host_list_dialog_gate_enabled_session'
|
||||||
|
const HOST_LIST_GATE_STATE_SESSION_KEY = 'host_list_dialog_gate_state_session'
|
||||||
|
const HOST_LIST_MONITOR_INTERVAL_MS = 30000
|
||||||
|
|
||||||
|
let monitorTimer = null
|
||||||
|
let syncPromise = null
|
||||||
|
|
||||||
|
function getElectronAPI() {
|
||||||
|
if (typeof window === 'undefined') return null
|
||||||
|
return window.electronAPI || null
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGateEnabled() {
|
||||||
|
if (typeof window === 'undefined') return false
|
||||||
|
return sessionStorage.getItem(HOST_LIST_GATE_ENABLED_SESSION_KEY) === 'true'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLowerLimit() {
|
||||||
|
if (typeof window === 'undefined') return 5
|
||||||
|
const raw = Number(localStorage.getItem(HOST_LIST_MIN_COUNT_KEY))
|
||||||
|
return Number.isFinite(raw) && raw >= 0 ? raw : 5
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPersistedGateState() {
|
||||||
|
if (typeof window === 'undefined') return null
|
||||||
|
const raw = sessionStorage.getItem(HOST_LIST_GATE_STATE_SESSION_KEY)
|
||||||
|
if (raw === 'true') return true
|
||||||
|
if (raw === 'false') return false
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function persistGateState(value) {
|
||||||
|
if (typeof window === 'undefined') return
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
sessionStorage.removeItem(HOST_LIST_GATE_STATE_SESSION_KEY)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionStorage.setItem(HOST_LIST_GATE_STATE_SESSION_KEY, String(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFilteredHostCount(hosts, filters) {
|
||||||
|
const excludedLevels = Array.isArray(filters?.hostsLevelList) ? filters.hostsLevelList : []
|
||||||
|
const minOnlineFans = Number(filters?.minOnlineFans) || 0
|
||||||
|
const maxOnlineFans = Number(filters?.maxOnlineFans) || 0
|
||||||
|
|
||||||
|
return hosts.filter((host) => {
|
||||||
|
if (filters?.gold === false && host.invitationType === 2) return false
|
||||||
|
if (filters?.ordinary === false && host.invitationType === 1) return false
|
||||||
|
|
||||||
|
if (minOnlineFans > 0 && host.onlineFans !== undefined && host.onlineFans < minOnlineFans) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxOnlineFans > 0 && host.onlineFans !== undefined && host.onlineFans > maxOnlineFans) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludedLevels.length > 0 && host.hostsLevel && excludedLevels.includes(host.hostsLevel)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}).length
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function syncHostListGateDecision(forceSync = false) {
|
||||||
|
if (!isElectron()) return
|
||||||
|
if (!getGateEnabled()) return
|
||||||
|
if (syncPromise) return syncPromise
|
||||||
|
|
||||||
|
const electronAPI = getElectronAPI()
|
||||||
|
if (!electronAPI?.getAutomationConfig || !electronAPI?.loadAnchorData || !electronAPI?.tk?.controlCheckTask) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
syncPromise = (async () => {
|
||||||
|
const config = await electronAPI.getAutomationConfig()
|
||||||
|
const hosts = await electronAPI.loadAnchorData()
|
||||||
|
const filters = config?.filters || {}
|
||||||
|
const hostCount = getFilteredHostCount(hosts || [], filters)
|
||||||
|
const upperLimit = Number(filters.maxAnchorCount)
|
||||||
|
const lowerLimit = getLowerLimit()
|
||||||
|
const lastGateState = getPersistedGateState()
|
||||||
|
|
||||||
|
let nextState = null
|
||||||
|
|
||||||
|
if (Number.isFinite(upperLimit) && upperLimit >= 0 && hostCount >= upperLimit) {
|
||||||
|
nextState = false
|
||||||
|
} else if (Number.isFinite(lowerLimit) && lowerLimit >= 0 && hostCount < lowerLimit) {
|
||||||
|
nextState = true
|
||||||
|
} else if (lastGateState !== null) {
|
||||||
|
nextState = lastGateState
|
||||||
|
} else if (forceSync) {
|
||||||
|
nextState = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextState === null) return
|
||||||
|
if (!forceSync && lastGateState === nextState) return
|
||||||
|
|
||||||
|
const result = await electronAPI.tk.controlCheckTask({
|
||||||
|
isRunning: Boolean(nextState),
|
||||||
|
model: true
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result?.success === false) {
|
||||||
|
console.error('[HostListGateMonitor] controlCheckTask 调用失败:', result.error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
persistGateState(nextState)
|
||||||
|
console.log('[HostListGateMonitor] 门控状态已更新:', nextState, '当前数量:', hostCount)
|
||||||
|
})().catch((error) => {
|
||||||
|
console.error('[HostListGateMonitor] 同步门控状态失败:', error)
|
||||||
|
}).finally(() => {
|
||||||
|
syncPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
return syncPromise
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ensureHostListGateMonitorRunning() {
|
||||||
|
if (!isElectron()) return
|
||||||
|
if (monitorTimer) return
|
||||||
|
|
||||||
|
monitorTimer = setInterval(() => {
|
||||||
|
if (!getGateEnabled()) {
|
||||||
|
stopHostListGateMonitor()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
void syncHostListGateDecision()
|
||||||
|
}, HOST_LIST_MONITOR_INTERVAL_MS)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function stopHostListGateMonitor() {
|
||||||
|
if (!monitorTimer) return
|
||||||
|
clearInterval(monitorTimer)
|
||||||
|
monitorTimer = null
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user