diff --git a/apps/src/views/operate/baishun-game-manage.vue b/apps/src/views/operate/baishun-game-manage.vue index 62bd8aa..d0288b8 100644 --- a/apps/src/views/operate/baishun-game-manage.vue +++ b/apps/src/views/operate/baishun-game-manage.vue @@ -6,10 +6,13 @@ import { useAccessStore } from '@vben/stores'; import { deleteBaishunGame, + fetchBaishunCatalog, + getBaishunProviderConfig, importBaishunCatalog, + pageBaishunCatalog, pageBaishunGames, saveBaishunGame, - syncBaishunGames, + saveBaishunProviderConfig, } from '#/api/legacy/baishun-game'; import { getAllowedSysOrigins } from '#/views/system/shared'; @@ -26,6 +29,8 @@ import { Select, Space, Table, + TabPane, + Tabs, Tag, message, } from 'antdv-next'; @@ -37,7 +42,7 @@ import { defineOptions({ name: 'OperateBaishunGameManage' }); -function createForm(sysOrigin = '') { +function createGameForm(sysOrigin = '') { return { amounts: '', category: 'OTHER', @@ -58,7 +63,7 @@ function createForm(sysOrigin = '') { previewUrl: '', regions: '', safeHeight: 0, - showcase: false as any, + showcase: true as any, sort: 0, sysOrigin, vendorGameId: undefined as any, @@ -67,6 +72,20 @@ function createForm(sysOrigin = '') { }; } +function createProviderForm(sysOrigin = '') { + return { + sysOrigin, + platformBaseUrl: '', + appId: undefined as any, + appName: '', + appChannel: '', + appKey: '', + gsp: 101 as any, + launchCodeTtlSeconds: 300 as any, + ssTokenTtlSeconds: 86400 as any, + }; +} + const accessStore = useAccessStore(); const sysOriginOptions = computed(() => { const options = getAllowedSysOrigins(accessStore.accessCodes || []); @@ -105,24 +124,37 @@ const orientationOptions = [ { label: '2', value: 2 as any }, ]; -const query = reactive>({ +const activeTab = ref('configured'); +const contextQuery = reactive({ sysOrigin: '' }); +const gameQuery = reactive>({ cursor: 1, keyword: '', limit: 20, showcase: '', - sysOrigin: '', +}); +const catalogQuery = reactive>({ + cursor: 1, + keyword: '', + limit: 20, }); -const loading = ref(false); -const saving = ref(false); -const importing = ref(false); -const syncing = ref(false); -const total = ref(0); +const gameLoading = ref(false); +const gameSaving = ref(false); +const providerLoading = ref(false); +const providerSaving = ref(false); +const catalogLoading = ref(false); +const catalogFetching = ref(false); +const catalogImporting = ref(false); +const totalGames = ref(0); +const totalCatalog = ref(0); const modalOpen = ref(false); -const list = ref>>([]); -const form = reactive>(createForm()); +const gameList = ref>>([]); +const catalogList = ref>>([]); +const selectedCatalogKeys = ref>([]); +const gameForm = reactive>(createGameForm()); +const providerForm = reactive>(createProviderForm()); -const columns = [ +const gameColumns = [ { dataIndex: 'cover', key: 'cover', title: '封面', width: 90 }, { dataIndex: 'name', key: 'name', title: '名称', width: 180 }, { dataIndex: 'gameId', key: 'gameId', title: '内部ID', width: 150 }, @@ -137,37 +169,124 @@ const columns = [ { dataIndex: 'actions', key: 'actions', title: '操作', width: 160 }, ]; +const catalogColumns = [ + { dataIndex: 'cover', key: 'cover', title: '封面', width: 90 }, + { dataIndex: 'name', key: 'name', title: '名称', width: 180 }, + { dataIndex: 'gameId', key: 'gameId', title: '内部ID', width: 150 }, + { dataIndex: 'vendorGameId', key: 'vendorGameId', title: '百顺ID', width: 120 }, + { dataIndex: 'status', key: 'status', title: '目录状态', width: 110 }, + { dataIndex: 'packageVersion', key: 'packageVersion', title: '包版本', width: 110 }, + { dataIndex: 'gsp', key: 'gsp', title: 'GSP', width: 90 }, + { dataIndex: 'added', key: 'added', title: '后台列表', width: 110 }, + { dataIndex: 'downloadUrl', key: 'downloadUrl', title: '入口地址', width: 360 }, + { dataIndex: 'updateTime', key: 'updateTime', title: '更新时间', width: 180 }, +]; + +const catalogRowSelection = computed(() => ({ + selectedRowKeys: selectedCatalogKeys.value, + onChange: (keys: Array) => { + selectedCatalogKeys.value = keys.map((item) => Number(item)); + }, + getCheckboxProps: (record: Record) => ({ + disabled: Boolean(record.added), + }), +})); + watch( sysOriginOptions, (options) => { - if (!query.sysOrigin) { - query.sysOrigin = String(options[0]?.value || ''); + if (!contextQuery.sysOrigin) { + contextQuery.sysOrigin = String(options[0]?.value || ''); } }, { immediate: true }, ); watch( - () => query.sysOrigin, + () => contextQuery.sysOrigin, (value) => { - if (value) { - void loadData(true); + if (!value) { + return; } + Object.assign(providerForm, createProviderForm(value)); + selectedCatalogKeys.value = []; + void Promise.all([loadProviderConfig(), loadGames(true), loadCatalog(true)]); }, { immediate: true }, ); -function resetForm() { - Object.assign(form, createForm(query.sysOrigin)); +function resetGameForm() { + Object.assign(gameForm, createGameForm(contextQuery.sysOrigin)); +} + +function applyProviderForm(record: Record) { + Object.assign(providerForm, createProviderForm(contextQuery.sysOrigin), { + ...record, + sysOrigin: contextQuery.sysOrigin, + appId: Number(record.appId || 0) || undefined, + gsp: Number(record.gsp || 101) || 101, + launchCodeTtlSeconds: + Number(record.launchCodeTtlSeconds || 300) || 300, + ssTokenTtlSeconds: + Number(record.ssTokenTtlSeconds || 86400) || 86400, + }); +} + +async function loadProviderConfig() { + if (!contextQuery.sysOrigin) { + return; + } + providerLoading.value = true; + try { + const result = await getBaishunProviderConfig({ + sysOrigin: contextQuery.sysOrigin, + }); + applyProviderForm(result || {}); + } finally { + providerLoading.value = false; + } +} + +async function persistProviderConfig(showSuccess = true) { + if ( + !contextQuery.sysOrigin || + !providerForm.platformBaseUrl || + !providerForm.appId || + !providerForm.appChannel || + !providerForm.appKey + ) { + message.warning('请补全百顺平台地址、AppId、AppChannel、AppKey'); + return false; + } + providerSaving.value = true; + try { + const result = await saveBaishunProviderConfig({ + ...providerForm, + sysOrigin: contextQuery.sysOrigin, + appId: Number(providerForm.appId || 0), + gsp: Number(providerForm.gsp || 101), + launchCodeTtlSeconds: Number(providerForm.launchCodeTtlSeconds || 300), + ssTokenTtlSeconds: Number(providerForm.ssTokenTtlSeconds || 86400), + }); + applyProviderForm(result || providerForm); + if (showSuccess) { + message.success('百顺配置已保存'); + } + return true; + } catch { + return false; + } finally { + providerSaving.value = false; + } } function openCreate() { - resetForm(); + resetGameForm(); modalOpen.value = true; } function openEdit(record: Record) { - Object.assign(form, createForm(query.sysOrigin), { + Object.assign(gameForm, createGameForm(contextQuery.sysOrigin), { ...record, id: String(record.id || ''), vendorGameId: Number(record.vendorGameId || 0) || undefined, @@ -175,50 +294,88 @@ function openEdit(record: Record) { modalOpen.value = true; } -async function loadData(reset = false) { - if (!query.sysOrigin) { +async function loadGames(reset = false) { + if (!contextQuery.sysOrigin) { return; } if (reset) { - query.cursor = 1; + gameQuery.cursor = 1; } - loading.value = true; + gameLoading.value = true; try { - const result = await pageBaishunGames({ ...query }); - list.value = Array.isArray(result.records) ? result.records : []; - total.value = Number(result.total || 0); + const result = await pageBaishunGames({ + ...gameQuery, + sysOrigin: contextQuery.sysOrigin, + }); + gameList.value = Array.isArray(result.records) ? result.records : []; + totalGames.value = Number(result.total || 0); } finally { - loading.value = false; + gameLoading.value = false; } } -function handleSearch() { - void loadData(true); +async function loadCatalog(reset = false) { + if (!contextQuery.sysOrigin) { + return; + } + if (reset) { + catalogQuery.cursor = 1; + } + catalogLoading.value = true; + try { + const result = await pageBaishunCatalog({ + ...catalogQuery, + sysOrigin: contextQuery.sysOrigin, + }); + catalogList.value = Array.isArray(result.records) ? result.records : []; + totalCatalog.value = Number(result.total || 0); + } finally { + catalogLoading.value = false; + } } -function handlePageChange(page: number, pageSize: number) { - query.cursor = page; - query.limit = pageSize; - void loadData(); +function handleGameSearch() { + void loadGames(true); } -async function submitForm() { - if (!form.sysOrigin || !form.name || !form.gameId || !form.vendorGameId) { +function handleCatalogSearch() { + void loadCatalog(true); +} + +function handleGamePageChange(page: number, pageSize: number) { + gameQuery.cursor = page; + gameQuery.limit = pageSize; + void loadGames(); +} + +function handleCatalogPageChange(page: number, pageSize: number) { + catalogQuery.cursor = page; + catalogQuery.limit = pageSize; + void loadCatalog(); +} + +async function submitGameForm() { + if ( + !gameForm.sysOrigin || + !gameForm.name || + !gameForm.gameId || + !gameForm.vendorGameId + ) { message.warning('请补全系统、名称、内部ID和百顺ID'); return; } - saving.value = true; + gameSaving.value = true; try { await saveBaishunGame({ - ...form, - id: Number(form.id || 0), - vendorGameId: Number(form.vendorGameId || 0), + ...gameForm, + id: Number(gameForm.id || 0), + vendorGameId: Number(gameForm.vendorGameId || 0), }); message.success('保存成功'); modalOpen.value = false; - await loadData(true); + await Promise.all([loadGames(true), loadCatalog(true)]); } finally { - saving.value = false; + gameSaving.value = false; } } @@ -228,207 +385,391 @@ function handleDelete(record: Record) { async onOk() { await deleteBaishunGame(record.id, record.sysOrigin); message.success('删除成功'); - await loadData(true); + await Promise.all([loadGames(true), loadCatalog(true)]); }, }); } -async function handleImportCatalog() { - if (!query.sysOrigin) { +async function handleSaveProviderConfig() { + await persistProviderConfig(true); +} + +async function handleFetchCatalog() { + if (!(await persistProviderConfig(false))) { return; } - importing.value = true; + catalogFetching.value = true; try { - const result = await importBaishunCatalog({ sysOrigin: query.sysOrigin }); - message.success(`导入完成:新增 ${Number(result.imported || 0)},已存在 ${Number(result.existing || 0)}`); - await loadData(true); + const result = await fetchBaishunCatalog({ + sysOrigin: contextQuery.sysOrigin, + }); + message.success( + `获取完成:新增 ${Number(result.inserted || 0)},更新 ${Number(result.updated || 0)},跳过 ${Number(result.skipped || 0)}`, + ); + activeTab.value = 'catalog'; + await loadCatalog(true); } finally { - importing.value = false; + catalogFetching.value = false; } } -async function handleSync() { - if (!query.sysOrigin) { +async function handleImportSelected() { + if (!contextQuery.sysOrigin) { return; } - syncing.value = true; + if (selectedCatalogKeys.value.length === 0) { + message.warning('请选择要添加到后台列表的百顺游戏'); + return; + } + catalogImporting.value = true; try { - const result = await syncBaishunGames({ sysOrigin: query.sysOrigin }); + const result = await importBaishunCatalog({ + sysOrigin: contextQuery.sysOrigin, + vendorGameIds: selectedCatalogKeys.value, + }); + selectedCatalogKeys.value = []; message.success( - `同步完成:目录新增 ${Number(result.inserted || 0)},更新 ${Number(result.updated || 0)},导入 ${Number(result.imported || 0)}`, + `添加完成:新增 ${Number(result.imported || 0)},已存在 ${Number(result.existing || 0)}`, ); - await loadData(true); + await Promise.all([loadGames(true), loadCatalog(true)]); } finally { - syncing.value = false; + catalogImporting.value = false; } }