feat(admin): add game manager menu

This commit is contained in:
hy 2026-04-22 20:16:10 +08:00
parent 32c4e70187
commit 22bf3427fe
8 changed files with 711 additions and 63 deletions

View File

@ -1,11 +1,27 @@
import { requestClient } from '#/api/request';
export async function getBaishunProviderConfig(params: Record<string, any>) {
return requestClient.get<Record<string, any>>('/go/operate/baishun-game/config', {
params,
});
}
export async function saveBaishunProviderConfig(data: Record<string, any>) {
return requestClient.post<Record<string, any>>('/go/operate/baishun-game/config', data);
}
export async function pageBaishunGames(params: Record<string, any>) {
return requestClient.get<Record<string, any>>('/go/operate/baishun-game/page', {
params,
});
}
export async function pageBaishunCatalog(params: Record<string, any>) {
return requestClient.get<Record<string, any>>('/go/operate/baishun-game/catalog/page', {
params,
});
}
export async function saveBaishunGame(data: Record<string, any>) {
return requestClient.post<Record<string, any>>('/go/operate/baishun-game/save', data);
}
@ -16,6 +32,13 @@ export async function deleteBaishunGame(id: number | string, sysOrigin: string)
});
}
export async function fetchBaishunCatalog(data: Record<string, any>) {
return requestClient.post<Record<string, any>>(
'/go/operate/baishun-game/catalog/fetch',
data,
);
}
export async function importBaishunCatalog(data: Record<string, any>) {
return requestClient.post<Record<string, any>>(
'/go/operate/baishun-game/import-catalog',

View File

@ -0,0 +1,30 @@
import type { RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [
{
meta: {
icon: 'lucide:gamepad-2',
order: 52,
title: '游戏管理',
},
name: 'OperateGameManager',
path: '/game-manager',
redirect: '/game-manager/game-config',
children: [
{
name: 'OperateGameConfig',
path: 'game-config',
component: () => import('#/views/operate/game-config.vue'),
meta: { title: '游戏列表' },
},
{
name: 'OperateBaishunConfig',
path: 'baishun-config',
component: () => import('#/views/operate/baishun-config.vue'),
meta: { title: '百顺配置' },
},
],
},
];
export default routes;

View File

@ -197,18 +197,6 @@ const routes: RouteRecordRaw[] = [
component: () => import('#/views/operate/mike-type-config.vue'),
meta: { title: '麦位类型管理' },
},
{
name: 'OperateGameConfig',
path: 'game-config',
component: () => import('#/views/operate/game-config.vue'),
meta: { title: '游戏列表' },
},
{
name: 'OperateBaishunGameManage',
path: 'baishun-game-manage',
component: () => import('#/views/operate/baishun-game-manage.vue'),
meta: { title: '百顺游戏管理' },
},
{
name: 'OperateMikeTypeList',
path: 'mike/type/list',

View File

@ -0,0 +1,471 @@
<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue';
import { Page } from '@vben/common-ui';
import { useAccessStore } from '@vben/stores';
import {
fetchBaishunCatalog,
getBaishunProviderConfig,
importBaishunCatalog,
pageBaishunCatalog,
saveBaishunProviderConfig,
} from '#/api/legacy/baishun-game';
import { getAllowedSysOrigins } from '#/views/system/shared';
import {
Button,
Card,
Form,
FormItem,
Image,
Input,
InputNumber,
Pagination,
Table,
Tag,
message,
} from 'antdv-next';
defineOptions({ name: 'OperateBaishunConfig' });
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 || []);
return options.length > 0 ? options : getAllowedSysOrigins([]);
});
const contextQuery = reactive({ sysOrigin: '' });
const providerForm = reactive(createProviderForm());
const catalogQuery = reactive<Record<string, any>>({
cursor: 1,
keyword: '',
limit: 20,
});
const providerLoading = ref(false);
const providerSaving = ref(false);
const catalogLoading = ref(false);
const catalogFetching = ref(false);
const catalogImporting = ref(false);
const totalCatalog = ref(0);
const catalogList = ref<Array<Record<string, any>>>([]);
const selectedCatalogKeys = ref<Array<number>>([]);
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: 120 },
{ dataIndex: 'downloadUrl', key: 'downloadUrl', title: '入口地址', width: 360 },
{ dataIndex: 'updateTime', key: 'updateTime', title: '更新时间', width: 180 },
];
const catalogRowSelection = computed(() => ({
selectedRowKeys: selectedCatalogKeys.value,
onChange: (keys: Array<number | string>) => {
selectedCatalogKeys.value = keys.map((item) => Number(item));
},
getCheckboxProps: (record: Record<string, any>) => ({
disabled: Boolean(record.added),
}),
}));
watch(
sysOriginOptions,
(options) => {
if (!contextQuery.sysOrigin) {
contextQuery.sysOrigin = String(options[0]?.value || '');
}
},
{ immediate: true },
);
watch(
() => contextQuery.sysOrigin,
(value) => {
if (!value) {
return;
}
Object.assign(providerForm, createProviderForm(value));
selectedCatalogKeys.value = [];
void Promise.all([loadProviderConfig(), loadCatalog(true)]);
},
{ immediate: true },
);
function applyProviderForm(record: Record<string, any>) {
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;
}
}
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 handleCatalogSearch() {
void loadCatalog(true);
}
function handleCatalogPageChange(page: number, pageSize: number) {
catalogQuery.cursor = page;
catalogQuery.limit = pageSize;
void loadCatalog();
}
async function handleSaveProviderConfig() {
await persistProviderConfig(true);
}
async function handleFetchCatalog() {
if (!(await persistProviderConfig(false))) {
return;
}
catalogFetching.value = true;
try {
const result = await fetchBaishunCatalog({
sysOrigin: contextQuery.sysOrigin,
});
message.success(
`获取完成:新增 ${Number(result.inserted || 0)},更新 ${Number(result.updated || 0)},跳过 ${Number(result.skipped || 0)}`,
);
await loadCatalog(true);
} finally {
catalogFetching.value = false;
}
}
async function handleImportSelected() {
if (!contextQuery.sysOrigin) {
return;
}
if (selectedCatalogKeys.value.length === 0) {
message.warning('请选择要添加到统一游戏列表的百顺游戏');
return;
}
catalogImporting.value = true;
try {
const result = await importBaishunCatalog({
sysOrigin: contextQuery.sysOrigin,
vendorGameIds: selectedCatalogKeys.value,
});
selectedCatalogKeys.value = [];
message.success(
`添加完成:新增 ${Number(result.imported || 0)},已存在 ${Number(result.existing || 0)}`,
);
await loadCatalog(true);
} finally {
catalogImporting.value = false;
}
}
</script>
<template>
<Page title="百顺配置">
<Card :loading="providerLoading" title="百顺接入配置">
<Form layout="vertical">
<div class="form-grid provider-grid">
<FormItem label="系统">
<SysOriginSelect
v-model:value="contextQuery.sysOrigin"
:options="sysOriginOptions"
/>
</FormItem>
<FormItem
label="平台地址"
extra="填写百顺平台接口地址,例如 https://game-cn-test.jieyou.shop不要填 Lucky Gift 域名。"
>
<Input
v-model:value="providerForm.platformBaseUrl"
placeholder="https://game-cn-test.jieyou.shop"
/>
</FormItem>
<FormItem label="AppId">
<InputNumber
v-model:value="providerForm.appId"
:min="1"
style="width: 100%"
/>
</FormItem>
<FormItem label="AppName">
<Input v-model:value="providerForm.appName" placeholder="可选" />
</FormItem>
<FormItem label="AppChannel">
<Input
v-model:value="providerForm.appChannel"
placeholder="yumiparty"
/>
</FormItem>
<FormItem label="AppKey">
<Input
v-model:value="providerForm.appKey"
placeholder="请输入百顺密钥"
type="password"
/>
</FormItem>
<FormItem label="默认 GSP">
<InputNumber
v-model:value="providerForm.gsp"
:min="1"
style="width: 100%"
/>
</FormItem>
<FormItem label="LaunchCode TTL(秒)">
<InputNumber
v-model:value="providerForm.launchCodeTtlSeconds"
:min="1"
style="width: 100%"
/>
</FormItem>
<FormItem label="SsToken TTL(秒)">
<InputNumber
v-model:value="providerForm.ssTokenTtlSeconds"
:min="1"
style="width: 100%"
/>
</FormItem>
</div>
<div class="toolbar">
<Button
type="primary"
:loading="providerSaving"
@click="handleSaveProviderConfig"
>
保存配置
</Button>
<Button :loading="catalogFetching" @click="handleFetchCatalog">
获取百顺游戏列表
</Button>
<span class="hint">
最终入库统一落到游戏管理 / 游戏列表这里仅负责百顺接入配置和目录导入
</span>
</div>
</Form>
</Card>
<Card class="content-card" title="百顺目录">
<div class="toolbar">
<Input
v-model:value="catalogQuery.keyword"
placeholder="搜索目录名称 / 内部ID / 百顺ID"
style="width: 260px"
@pressEnter="handleCatalogSearch"
/>
<Button :loading="catalogLoading" type="primary" @click="handleCatalogSearch">
搜索
</Button>
<Button :loading="catalogFetching" @click="handleFetchCatalog">
重新获取目录
</Button>
<Button
type="primary"
:loading="catalogImporting"
@click="handleImportSelected"
>
添加已选游戏
</Button>
</div>
<Table
:columns="catalogColumns"
:data-source="catalogList"
:loading="catalogLoading"
:pagination="false"
row-key="vendorGameId"
:row-selection="catalogRowSelection"
:scroll="{ x: 1700 }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'cover'">
<Image v-if="record.cover" :src="record.cover" class="cover" />
<span v-else>-</span>
</template>
<template v-else-if="column.key === 'status'">
<Tag :color="record.status === 'ENABLED' ? 'success' : 'default'">
{{ record.status || '-' }}
</Tag>
</template>
<template v-else-if="column.key === 'added'">
<Tag :color="record.added ? 'success' : 'default'">
{{ record.added ? '已进入统一游戏列表' : '未添加' }}
</Tag>
</template>
<template v-else-if="column.key === 'downloadUrl'">
<a
v-if="record.downloadUrl"
:href="record.downloadUrl"
class="link-cell"
rel="noreferrer"
target="_blank"
>
{{ record.downloadUrl }}
</a>
<span v-else>-</span>
</template>
</template>
</Table>
<div v-if="totalCatalog > 0" class="pager">
<Pagination
:current="catalogQuery.cursor"
:page-size="catalogQuery.limit"
:total="totalCatalog"
show-size-changer
@change="handleCatalogPageChange"
@showSizeChange="handleCatalogPageChange"
/>
</div>
</Card>
</Page>
</template>
<style scoped>
.content-card {
margin-top: 16px;
}
.toolbar {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-bottom: 16px;
}
.pager {
display: flex;
justify-content: flex-end;
margin-top: 16px;
}
.cover {
width: 50px;
height: 50px;
object-fit: cover;
border-radius: 6px;
}
.form-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0 16px;
}
.provider-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.hint {
color: rgb(100 116 139);
line-height: 32px;
}
.link-cell {
display: inline-block;
max-width: 340px;
overflow: hidden;
color: rgb(37 99 235);
text-overflow: ellipsis;
white-space: nowrap;
}
@media (max-width: 1200px) {
.provider-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 900px) {
.form-grid,
.provider-grid {
grid-template-columns: minmax(0, 1fr);
}
}
</style>

View File

@ -44,7 +44,7 @@ export const FREIGHT_RECHARGE_TYPE_OPTIONS = [
];
export const GAME_ORIGIN_OPTIONS = [
{ value: 'BAISHUN', name: 'Baishun' },
{ value: 'BAISHUN', name: 'BAISHUN' },
{ value: 'LINGXIAN', name: 'LingXian' },
{ value: 'HOTGAME', name: 'HOTGAME' },
{ value: 'YOMI', name: 'YOMI' },

View File

@ -1,6 +1,5 @@
<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue';
import { useRouter } from 'vue-router';
import { Page } from '@vben/common-ui';
import { useAccessStore } from '@vben/stores';
@ -67,7 +66,6 @@ function createForm() {
};
}
const router = useRouter();
const accessStore = useAccessStore();
const sysOriginOptions = computed(() => {
const options = getAllowedSysOrigins(accessStore.accessCodes || []);
@ -87,7 +85,6 @@ const query = reactive<Record<string, any>>({
cursor: 1,
gameOrigin: 'BAISHUN',
limit: 20,
showcase: true,
sysOrigin: '',
});
@ -124,15 +121,24 @@ const regionSelectOptions = computed(() =>
);
const columns = [
{ dataIndex: 'sysOrigin', key: 'sysOrigin', title: '系统', width: 100 },
{ dataIndex: 'cover', key: 'cover', title: '封面', width: 90 },
{ dataIndex: 'name', key: 'name', title: '名称', width: 160 },
{ dataIndex: 'gameCode', key: 'gameCode', title: '游戏编号', width: 120 },
{ dataIndex: 'amounts', key: 'amounts', title: '金额', width: 180 },
{ dataIndex: 'gameOrigin', key: 'gameOrigin', title: '三方类型', width: 120 },
{ dataIndex: 'gameId', key: 'gameId', title: '游戏ID', width: 160 },
{ dataIndex: 'gameCode', key: 'gameCode', title: '三方游戏ID', width: 120 },
{ dataIndex: 'category', key: 'category', title: '分类', width: 120 },
{ dataIndex: 'clientOrigin', key: 'clientOrigin', title: '客户端', width: 120 },
{ dataIndex: 'fullScreen', key: 'fullScreen', title: '是否全屏', width: 110 },
{ dataIndex: 'fullScreen', key: 'fullScreen', title: '全屏', width: 90 },
{ dataIndex: 'showcase', key: 'showcase', title: '状态', width: 100 },
{ dataIndex: 'sort', key: 'sort', title: '排序', width: 100 },
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 200 },
{ dataIndex: 'regionNameStr', key: 'regionNameStr', title: '区域', width: 180 },
{ dataIndex: 'gameMode', key: 'gameMode', title: '游戏模式', width: 120 },
{ dataIndex: 'amounts', key: 'amounts', title: '金额配置', width: 160 },
{ dataIndex: 'width', key: 'width', title: '宽', width: 90 },
{ dataIndex: 'height', key: 'height', title: '高', width: 90 },
{ dataIndex: 'createTime', key: 'createTime', title: '创建时间', width: 180 },
{ dataIndex: 'updateTime', key: 'updateTime', title: '更新时间', width: 180 },
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 140, fixed: 'right' as const },
];
watch(
@ -210,11 +216,6 @@ function resetForm() {
});
}
function openCreate() {
resetForm();
modalOpen.value = true;
}
function openEdit(record: Record<string, any>) {
Object.assign(form, createForm(), {
...record,
@ -298,14 +299,6 @@ async function handleUpload(event: Event) {
}
}
function openFruitConfig() {
router.push('/operate/manager/game/fruit/task-config');
}
function openBaishunManager() {
router.push('/operate/manager/baishun-game-manage');
}
void loadData(true);
</script>
@ -313,32 +306,16 @@ void loadData(true);
<Page title="游戏列表">
<Card>
<div class="toolbar">
<SysOriginSelect
v-model:value="query.sysOrigin"
style="width: 140px"
@change="handleSearch"
:options="sysOriginOptions"
/>
<Select
option-label-prop="label"
v-model:value="query.gameOrigin"
style="width: 140px"
@change="handleSearch"
:options="GAME_ORIGIN_OPTIONS.map((item) => ({ label: `${item.name}`, value: item.value as any }))"
/>
<Button :loading="loading" type="primary" @click="handleSearch">
搜索
</Button>
<Button type="primary" @click="openCreate">
新增
</Button>
<Button @click="openBaishunManager">
百顺游戏管理
</Button>
<Button @click="openFruitConfig">
摩天轮任务配置
</Button>
</div>
<Table
@ -347,18 +324,40 @@ void loadData(true);
:loading="loading"
:pagination="false"
row-key="id"
:scroll="{ x: 1680 }"
:scroll="{ x: 2160 }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'cover'">
<Image :src="record.cover" class="cover" />
</template>
<template v-else-if="column.key === 'gameOrigin'">
{{
GAME_ORIGIN_OPTIONS.find((item) => item.value === record.gameOrigin)?.name ||
record.gameOrigin ||
'-'
}}
</template>
<template v-else-if="column.key === 'fullScreen'">
{{ record.fullScreen ? '是' : '否' }}
</template>
<template v-else-if="column.key === 'showcase'">
{{ record.showcase ? '上架' : '下架' }}
</template>
<template v-else-if="column.key === 'regionNameStr'">
{{ record.regionNameStr || '-' }}
</template>
<template v-else-if="column.key === 'gameMode'">
{{ record.gameMode || '-' }}
</template>
<template v-else-if="column.key === 'amounts'">
{{ record.amounts || '-' }}
</template>
<template v-else-if="column.key === 'createTime'">
{{ formatDate(record.createTime) }}
</template>
<template v-else-if="column.key === 'updateTime'">
{{ formatDate(record.updateTime) }}
</template>
<template v-else-if="column.key === 'actions'">
<Space>
<Button size="small" type="link" @click="openEdit(record)">
@ -388,7 +387,7 @@ void loadData(true);
:confirm-loading="saving"
:open="modalOpen"
destroy-on-close
:title="form.id ? '编辑游戏' : '新增游戏'"
title="编辑游戏"
width="720px"
@cancel="modalOpen = false"
@ok="submitForm"

View File

@ -0,0 +1,14 @@
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT DISTINCT
child_link.role_id,
child.parent_id
FROM sys_role_menu AS child_link
JOIN sys_menu AS child
ON child.id = child_link.menu_id
LEFT JOIN sys_role_menu AS parent_link
ON parent_link.role_id = child_link.role_id
AND parent_link.menu_id = child.parent_id
WHERE child.menu_type IN (1, 2)
AND child.parent_id IS NOT NULL
AND child.parent_id <> 0
AND parent_link.menu_id IS NULL;

View File

@ -1,3 +1,5 @@
SET NAMES utf8mb4;
INSERT INTO sys_menu (
id,
parent_id,
@ -323,17 +325,92 @@ INSERT INTO sys_menu (
alias
)
SELECT
1700000257,
1700000057,
'百顺游戏管理',
'sys/game-config/baishun/index',
2,
1700000258,
0,
'游戏管理',
'/game-manager',
1,
'form',
'0',
'0',
133,
0,
'baishun-game-manage',
NULL,
'OperateGameManager'
WHERE NOT EXISTS (
SELECT 1 FROM sys_menu WHERE alias = 'OperateGameManager'
);
UPDATE sys_menu
SET
parent_id = 0,
menu_name = '游戏管理',
path = '/game-manager',
menu_type = 1,
icon = 'form',
create_user = '0',
update_user = '0',
sort = 133,
status = 0,
router = NULL
WHERE alias = 'OperateGameManager';
UPDATE sys_menu
SET
parent_id = (
SELECT game_manager.id
FROM (
SELECT id
FROM sys_menu
WHERE alias = 'OperateGameManager'
LIMIT 1
) AS game_manager
),
menu_name = '游戏列表',
path = 'sys/game-manager/list/index',
menu_type = 2,
icon = 'form',
create_user = '0',
update_user = '0',
sort = 1,
status = 0,
router = 'game-config'
WHERE alias = 'GameConfig';
INSERT INTO sys_menu (
id,
parent_id,
menu_name,
path,
menu_type,
icon,
create_user,
update_user,
sort,
status,
router,
alias
)
SELECT
1700000257,
(
SELECT game_manager.id
FROM (
SELECT id
FROM sys_menu
WHERE alias = 'OperateGameManager'
LIMIT 1
) AS game_manager
),
'百顺配置',
'sys/game-manager/baishun-config/index',
2,
'form',
'0',
'0',
2,
0,
'baishun-config',
'OperateBaishunGameManage'
WHERE NOT EXISTS (
SELECT 1 FROM sys_menu WHERE alias = 'OperateBaishunGameManage'
@ -341,16 +418,24 @@ WHERE NOT EXISTS (
UPDATE sys_menu
SET
parent_id = 1700000057,
menu_name = '百顺游戏管理',
path = 'sys/game-config/baishun/index',
parent_id = (
SELECT game_manager.id
FROM (
SELECT id
FROM sys_menu
WHERE alias = 'OperateGameManager'
LIMIT 1
) AS game_manager
),
menu_name = '百顺配置',
path = 'sys/game-manager/baishun-config/index',
menu_type = 2,
icon = 'form',
create_user = '0',
update_user = '0',
sort = 133,
sort = 2,
status = 0,
router = 'baishun-game-manage'
router = 'baishun-config'
WHERE alias = 'OperateBaishunGameManage';
INSERT INTO sys_role_menu (role_id, menu_id)
@ -366,6 +451,8 @@ JOIN sys_menu AS target_menu
'ResidentInviteConfig',
'ResidentInviteList',
'ResidentSpecifiedGiftWeeklyRank',
'OperateGameManager',
'GameConfig',
'OperateBaishunGameManage'
)
LEFT JOIN sys_role_menu AS existing_role_menu
@ -373,3 +460,39 @@ LEFT JOIN sys_role_menu AS existing_role_menu
AND existing_role_menu.menu_id = target_menu.id
WHERE parent_role.menu_id = 1700000057
AND existing_role_menu.id IS NULL;
UPDATE sys_menu
SET menu_name = CONVERT(0xE5B8B8E9A9BBE6B4BBE58AA8 USING utf8mb4)
WHERE alias = 'ResidentActivityManager';
UPDATE sys_menu
SET menu_name = CONVERT(0xE7ADBEE588B0E5A596E58AB1E9858DE7BDAE USING utf8mb4)
WHERE alias = 'ResidentSignInRewardConfig';
UPDATE sys_menu
SET menu_name = CONVERT(0xE6B3A8E5868CE5A596E58AB1E9858DE7BDAE USING utf8mb4)
WHERE alias = 'ResidentRegisterRewardConfig';
UPDATE sys_menu
SET menu_name = CONVERT(0xE98280E8AFB7E6B4BBE58AA8E9858DE7BDAE USING utf8mb4)
WHERE alias = 'ResidentInviteConfig';
UPDATE sys_menu
SET menu_name = CONVERT(0xE98280E8AFB7E6B4BBE58AA8E58897E8A1A8 USING utf8mb4)
WHERE alias = 'ResidentInviteList';
UPDATE sys_menu
SET menu_name = CONVERT(0xE68C87E5AE9AE7A4BCE789A9E591A8E6A69C USING utf8mb4)
WHERE alias = 'ResidentSpecifiedGiftWeeklyRank';
UPDATE sys_menu
SET menu_name = CONVERT(0xE6B8B8E6888FE7AEA1E79086 USING utf8mb4)
WHERE alias = 'OperateGameManager';
UPDATE sys_menu
SET menu_name = CONVERT(0xE6B8B8E6888FE58897E8A1A8 USING utf8mb4)
WHERE alias = 'GameConfig';
UPDATE sys_menu
SET menu_name = CONVERT(0xE799BEE9A1BAE9858DE7BDAE USING utf8mb4)
WHERE alias = 'OperateBaishunGameManage';