From 42c88e62824ca86c4948afbf4bd9c2b4e32086b1 Mon Sep 17 00:00:00 2001 From: zhx Date: Mon, 25 May 2026 21:19:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=81=E7=BB=AD=E6=A8=A1=E6=8B=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/src/api/legacy/region-broadcast.ts | 19 ++ apps/src/views/operate/region-broadcast.vue | 241 +++++++++++++++++++- 2 files changed, 258 insertions(+), 2 deletions(-) diff --git a/apps/src/api/legacy/region-broadcast.ts b/apps/src/api/legacy/region-broadcast.ts index 57443f2..a28e62d 100644 --- a/apps/src/api/legacy/region-broadcast.ts +++ b/apps/src/api/legacy/region-broadcast.ts @@ -6,3 +6,22 @@ export async function simulateRegionBroadcast(data: Record) { data, ); } + +export async function getRegionBroadcastWorkerStatus() { + return requestClient.get>( + '/go/operate/region-broadcast/worker/status', + ); +} + +export async function startRegionBroadcastWorker(data: Record) { + return requestClient.post>( + '/go/operate/region-broadcast/worker/start', + data, + ); +} + +export async function stopRegionBroadcastWorker() { + return requestClient.post>( + '/go/operate/region-broadcast/worker/stop', + ); +} diff --git a/apps/src/views/operate/region-broadcast.vue b/apps/src/views/operate/region-broadcast.vue index 49c9ce7..7cda27c 100644 --- a/apps/src/views/operate/region-broadcast.vue +++ b/apps/src/views/operate/region-broadcast.vue @@ -4,7 +4,13 @@ import { computed, reactive, ref, watch } from 'vue'; import { Page } from '@vben/common-ui'; import { useAccessStore } from '@vben/stores'; -import { simulateRegionBroadcast } from '#/api/legacy/region-broadcast'; +import { + getRegionBroadcastWorkerStatus, + simulateRegionBroadcast, + startRegionBroadcastWorker, + stopRegionBroadcastWorker, +} from '#/api/legacy/region-broadcast'; +import { regionConfigTable } from '#/api/legacy/system'; import { getAllowedSysOrigins } from '#/views/system/shared'; import SystemRegionSelect from './components/system-region-select.vue'; @@ -12,9 +18,13 @@ import SystemRegionSelect from './components/system-region-select.vue'; import { Button, Card, + Checkbox, Form, FormItem, Input, + InputNumber, + Descriptions, + DescriptionsItem, Select, Space, TextArea, @@ -58,7 +68,24 @@ const form = reactive>({ }); const sending = ref(false); +const workerLoading = ref(false); const resultText = ref(''); +const regionLoading = ref(false); +const regionOptions = ref>>([]); +const workerStatus = ref>({}); +const workerForm = reactive>({ + betAmounts: '100,200,500,1000', + enableGameWin: true, + enableLuckyGift: true, + gameWinAmounts: '1000,2000,5000,10000', + giftCandyOptions: '100,200,500', + giftQuantityOptions: '1,5,10', + luckyGiftWinAmounts: '1000,2000,5000,10000', + maxDelaySeconds: 20, + minDelaySeconds: 0, + multiples: '10,20,50,100', + regionCodes: [] as string[], +}); const isLuckyGift = computed(() => form.kind === 'LUCKY_GIFT'); @@ -74,12 +101,36 @@ watch( watch( () => form.sysOrigin, - () => { + (value) => { form.regionId = ''; form.regionCode = ''; + workerForm.regionCodes = []; + if (value) { + void loadRegions(); + void refreshWorkerStatus(); + } }, ); +async function loadRegions() { + if (!form.sysOrigin) { + regionOptions.value = []; + return; + } + regionLoading.value = true; + try { + const list = await regionConfigTable({ sysOrigin: form.sysOrigin }); + regionOptions.value = (list || []) + .map((item) => ({ + label: item.regionName || item.regionCode || item.code || String(item.id), + value: item.regionCode || item.code || '', + })) + .filter((item) => item.value); + } finally { + regionLoading.value = false; + } +} + function handleRegionChange(_value: any, item: Record | null) { form.regionCode = item?.regionCode || item?.code || ''; } @@ -143,6 +194,80 @@ async function handleSend() { sending.value = false; } } + +function parseIntList(value: any) { + return String(value || '') + .split(/[,,\s]+/) + .map((item) => Number(item.trim())) + .filter((item) => Number.isFinite(item) && item > 0) + .map((item) => Math.trunc(item)); +} + +function parseFloatList(value: any) { + return String(value || '') + .split(/[,,\s]+/) + .map((item) => Number(item.trim())) + .filter((item) => Number.isFinite(item) && item > 0); +} + +function buildWorkerPayload() { + return { + betAmounts: parseIntList(workerForm.betAmounts), + enableGameWin: Boolean(workerForm.enableGameWin), + enableLuckyGift: Boolean(workerForm.enableLuckyGift), + gameWinAmounts: parseIntList(workerForm.gameWinAmounts), + giftCandyOptions: parseIntList(workerForm.giftCandyOptions), + giftQuantityOptions: parseIntList(workerForm.giftQuantityOptions), + luckyGiftWinAmounts: parseIntList(workerForm.luckyGiftWinAmounts), + maxDelaySeconds: Number(workerForm.maxDelaySeconds || 0), + minDelaySeconds: Number(workerForm.minDelaySeconds || 0), + multiples: parseFloatList(workerForm.multiples), + regionCodes: workerForm.regionCodes || [], + sysOrigin: form.sysOrigin, + }; +} + +async function refreshWorkerStatus() { + workerLoading.value = true; + try { + workerStatus.value = (await getRegionBroadcastWorkerStatus()) || {}; + } finally { + workerLoading.value = false; + } +} + +async function handleStartWorker() { + const payload = buildWorkerPayload(); + if (!payload.sysOrigin) { + message.warning('请选择系统来源'); + return; + } + if (!payload.regionCodes.length) { + message.warning('请至少选择一个区域'); + return; + } + if (!payload.enableGameWin && !payload.enableLuckyGift) { + message.warning('请至少开启一种飘屏'); + return; + } + workerLoading.value = true; + try { + workerStatus.value = (await startRegionBroadcastWorker(payload)) || {}; + message.success('持续模拟已启动'); + } finally { + workerLoading.value = false; + } +} + +async function handleStopWorker() { + workerLoading.value = true; + try { + workerStatus.value = (await stopRegionBroadcastWorker()) || {}; + message.success('持续模拟已停止'); + } finally { + workerLoading.value = false; + } +} @@ -244,4 +477,8 @@ async function handleSend() { .result-card { margin-top: 16px; } + +.summary { + margin-top: 16px; +}