3.6
This commit is contained in:
@@ -79,7 +79,7 @@ import { getToken, setToken, setUser, setUserPass, getUserPass } from '@/stores/
|
|||||||
import { ElLoading, ElMessage } from 'element-plus';
|
import { ElLoading, ElMessage } from 'element-plus';
|
||||||
import { passToken } from '@/api/ios';
|
import { passToken } from '@/api/ios';
|
||||||
|
|
||||||
let version = ref('3.3.0');
|
let version = ref('3.6.0');
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,16 @@
|
|||||||
<el-button type="info" @click="uploadLogFile">上传日志</el-button>
|
<el-button type="info" @click="uploadLogFile">上传日志</el-button>
|
||||||
<div>
|
<div>
|
||||||
<!-- 监听 q.tenant.*(爬虫) -->
|
<!-- 监听 q.tenant.*(爬虫) -->
|
||||||
<el-switch v-model="sseCrawlerEnabled" inline-prompt active-text="" inactive-text="监听爬虫"
|
<el-switch v-model="sseCrawlerEnabled" inline-prompt active-text="监听爬虫" inactive-text="监听爬虫"
|
||||||
style="margin-left: 8px;" @change="onToggleCrawler" />监听爬虫
|
style="margin-left: 8px;" @change="onToggleCrawler" />
|
||||||
|
<el-button size="small" style="margin-left: 8px;" @click="setSseLimit('crawler')">设置</el-button>
|
||||||
|
<span style="margin-left: 4px;">剩余 {{ sseCrawlerRemaining }}/{{ sseCrawlerLimit }} 条</span>
|
||||||
|
|
||||||
<!-- 监听 b.tenant.*(大哥) -->
|
<!-- 监听 b.tenant.*(大哥) -->
|
||||||
<el-switch v-model="sseBossEnabled" inline-prompt active-text="监听大哥" inactive-text="监听大哥"
|
<el-switch v-model="sseBossEnabled" inline-prompt active-text="监听大哥" inactive-text="监听大哥"
|
||||||
style="margin-left: 8px;" @change="onToggleBoss" />
|
style="margin-left: 8px;" @change="onToggleBoss" />
|
||||||
|
<el-button size="small" style="margin-left: 8px;" @click="setSseLimit('boss')">设置</el-button>
|
||||||
|
<span style="margin-left: 4px;">剩余 {{ sseBossRemaining }}/{{ sseBossLimit }} 条</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -118,7 +122,7 @@
|
|||||||
<div style="display:flex; gap:8px; align-items:center;">
|
<div style="display:flex; gap:8px; align-items:center;">
|
||||||
<el-switch v-model="interruptEnabled" active-text="开启换号" />
|
<el-switch v-model="interruptEnabled" active-text="开启换号" />
|
||||||
<el-input-number v-model="interruptEveryMin" :min="1" :max="24" />
|
<el-input-number v-model="interruptEveryMin" :min="1" :max="24" />
|
||||||
<span>分钟换一次</span>
|
<span>小时换一次</span>
|
||||||
</div>
|
</div>
|
||||||
<div>联盟号</div>
|
<div>联盟号</div>
|
||||||
<div style="display:flex; gap:8px; align-items:center;">
|
<div style="display:flex; gap:8px; align-items:center;">
|
||||||
@@ -287,18 +291,122 @@ const isLocked = (type) => !!runType.value && runType.value !== type
|
|||||||
// —— SSE 开关(分别控制爬虫队列 & 大哥队列)——
|
// —— SSE 开关(分别控制爬虫队列 & 大哥队列)——
|
||||||
const sseCrawlerEnabled = ref(JSON.parse(localStorage.getItem('SSE_CRAWLER_ENABLED') ?? 'true')) // q.tenant.*
|
const sseCrawlerEnabled = ref(JSON.parse(localStorage.getItem('SSE_CRAWLER_ENABLED') ?? 'true')) // q.tenant.*
|
||||||
const sseBossEnabled = ref(JSON.parse(localStorage.getItem('SSE_BOSS_ENABLED') ?? 'false')) // b.tenant.*
|
const sseBossEnabled = ref(JSON.parse(localStorage.getItem('SSE_BOSS_ENABLED') ?? 'false')) // b.tenant.*
|
||||||
|
const sseCrawlerLimit = ref(Number(localStorage.getItem('SSE_CRAWLER_LIMIT') ?? '500'))
|
||||||
|
const sseBossLimit = ref(Number(localStorage.getItem('SSE_BOSS_LIMIT') ?? '500'))
|
||||||
|
const sseCrawlerRemaining = ref(Number(localStorage.getItem('SSE_CRAWLER_REMAIN') ?? sseCrawlerLimit.value))
|
||||||
|
const sseBossRemaining = ref(Number(localStorage.getItem('SSE_BOSS_REMAIN') ?? sseBossLimit.value))
|
||||||
|
|
||||||
|
const normalizeSseLimit = (val, fallback) => {
|
||||||
|
const n = Number(val)
|
||||||
|
if (!Number.isFinite(n) || n <= 0) return fallback
|
||||||
|
return Math.floor(n)
|
||||||
|
}
|
||||||
|
|
||||||
watch(sseCrawlerEnabled, v => {
|
watch(sseCrawlerEnabled, v => {
|
||||||
localStorage.setItem('SSE_CRAWLER_ENABLED', JSON.stringify(v))
|
localStorage.setItem('SSE_CRAWLER_ENABLED', JSON.stringify(v))
|
||||||
|
if (v && sseCrawlerRemaining.value <= 0) {
|
||||||
|
sseCrawlerEnabled.value = false
|
||||||
|
ElMessage.warning('请先设置监听爬虫条数')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(sseBossEnabled, v => {
|
watch(sseBossEnabled, v => {
|
||||||
localStorage.setItem('SSE_BOSS_ENABLED', JSON.stringify(v))
|
localStorage.setItem('SSE_BOSS_ENABLED', JSON.stringify(v))
|
||||||
|
if (v && sseBossRemaining.value <= 0) {
|
||||||
|
sseBossEnabled.value = false
|
||||||
|
ElMessage.warning('请先设置监听大哥条数')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(sseCrawlerLimit, v => {
|
||||||
|
const next = normalizeSseLimit(v, 500)
|
||||||
|
if (next !== v) {
|
||||||
|
sseCrawlerLimit.value = next
|
||||||
|
return
|
||||||
|
}
|
||||||
|
localStorage.setItem('SSE_CRAWLER_LIMIT', String(next))
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(sseBossLimit, v => {
|
||||||
|
const next = normalizeSseLimit(v, 500)
|
||||||
|
if (next !== v) {
|
||||||
|
sseBossLimit.value = next
|
||||||
|
return
|
||||||
|
}
|
||||||
|
localStorage.setItem('SSE_BOSS_LIMIT', String(next))
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(sseCrawlerRemaining, v => {
|
||||||
|
const next = normalizeSseLimit(v, 0)
|
||||||
|
if (next !== v) {
|
||||||
|
sseCrawlerRemaining.value = next
|
||||||
|
return
|
||||||
|
}
|
||||||
|
localStorage.setItem('SSE_CRAWLER_REMAIN', String(next))
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(sseBossRemaining, v => {
|
||||||
|
const next = normalizeSseLimit(v, 0)
|
||||||
|
if (next !== v) {
|
||||||
|
sseBossRemaining.value = next
|
||||||
|
return
|
||||||
|
}
|
||||||
|
localStorage.setItem('SSE_BOSS_REMAIN', String(next))
|
||||||
})
|
})
|
||||||
|
|
||||||
// 至少有一个开着才算启用 SSE
|
// 至少有一个开着才算启用 SSE
|
||||||
const sseAnyEnabled = computed(() => sseCrawlerEnabled.value || sseBossEnabled.value)
|
const sseAnyEnabled = computed(() => sseCrawlerEnabled.value || sseBossEnabled.value)
|
||||||
|
|
||||||
|
const bumpSseCount = (type) => {
|
||||||
|
const isCrawler = type === 'crawler'
|
||||||
|
const remainingRef = isCrawler ? sseCrawlerRemaining : sseBossRemaining
|
||||||
|
if (remainingRef.value <= 0) {
|
||||||
|
if (isCrawler) {
|
||||||
|
sseCrawlerEnabled.value = false
|
||||||
|
} else {
|
||||||
|
sseBossEnabled.value = false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
remainingRef.value -= 1
|
||||||
|
if (remainingRef.value <= 0) {
|
||||||
|
if (isCrawler) {
|
||||||
|
sseCrawlerEnabled.value = false
|
||||||
|
} else {
|
||||||
|
sseBossEnabled.value = false
|
||||||
|
}
|
||||||
|
ElMessage.info(`监听${isCrawler ? '爬虫' : '大哥'}条数已用完,已自动关闭`)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const setSseLimit = async (type) => {
|
||||||
|
const isCrawler = type === 'crawler'
|
||||||
|
const label = isCrawler ? '爬虫' : '大哥'
|
||||||
|
const limitRef = isCrawler ? sseCrawlerLimit : sseBossLimit
|
||||||
|
const remainingRef = isCrawler ? sseCrawlerRemaining : sseBossRemaining
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { value } = await ElMessageBox.prompt(
|
||||||
|
`请输入监听${label}条数`,
|
||||||
|
'设置监听条数',
|
||||||
|
{
|
||||||
|
inputValue: String(limitRef.value || 0),
|
||||||
|
inputPattern: /^[1-9]\d*$/,
|
||||||
|
inputErrorMessage: '请输入正整数',
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const next = normalizeSseLimit(value, limitRef.value || 500)
|
||||||
|
limitRef.value = next
|
||||||
|
remainingRef.value = next
|
||||||
|
} catch (e) {
|
||||||
|
// 用户取消
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 互斥按钮的样式:激活=红,锁定=半透明且禁点
|
// 互斥按钮的样式:激活=红,锁定=半透明且禁点
|
||||||
const ctrlStyle = (type) => {
|
const ctrlStyle = (type) => {
|
||||||
const lockedByMode = isLocked(type)
|
const lockedByMode = isLocked(type)
|
||||||
@@ -797,6 +905,11 @@ onMounted(async () => {
|
|||||||
// 2️⃣ 按开关过滤
|
// 2️⃣ 按开关过滤
|
||||||
if (fromCrawler && !sseCrawlerEnabled.value) return
|
if (fromCrawler && !sseCrawlerEnabled.value) return
|
||||||
if (fromBoss && !sseBossEnabled.value) return
|
if (fromBoss && !sseBossEnabled.value) return
|
||||||
|
if (fromCrawler) {
|
||||||
|
if (!bumpSseCount('crawler')) return
|
||||||
|
} else if (fromBoss) {
|
||||||
|
if (!bumpSseCount('boss')) return
|
||||||
|
}
|
||||||
if (isUnknown && !sseCrawlerEnabled.value) return // 老数据当爬虫看
|
if (isUnknown && !sseCrawlerEnabled.value) return // 老数据当爬虫看
|
||||||
|
|
||||||
// 3️⃣ 按来源取不同字段
|
// 3️⃣ 按来源取不同字段
|
||||||
@@ -1226,8 +1339,8 @@ function startScheduleLoop() {
|
|||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
if (!lastInterruptTs) lastInterruptTs = now // 首次初始化
|
if (!lastInterruptTs) lastInterruptTs = now // 首次初始化
|
||||||
|
|
||||||
// const due = now - lastInterruptTs >= interruptEveryMin.value * 60_000 * 60
|
const due = now - lastInterruptTs >= interruptEveryMin.value * 60_000 * 60
|
||||||
const due = now - lastInterruptTs >= interruptEveryMin.value * 60_000
|
// const due = now - lastInterruptTs >= interruptEveryMin.value * 60_000
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
'due=', due,
|
'due=', due,
|
||||||
@@ -1658,11 +1771,13 @@ const markPendingForOffline = (ids) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onToggleCrawler = (val) => {
|
const onToggleCrawler = (val) => {
|
||||||
if (val) sseBossEnabled.value = false
|
if (val) sseBossEnabled.value = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
const onToggleBoss = (val) => {
|
const onToggleBoss = (val) => {
|
||||||
if (val) sseCrawlerEnabled.value = false
|
if (val) sseCrawlerEnabled.value = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
function timestampToTime(timestamp_ms) {
|
function timestampToTime(timestamp_ms) {
|
||||||
const date = new Date(timestamp_ms);
|
const date = new Date(timestamp_ms);
|
||||||
|
|||||||
Reference in New Issue
Block a user