[积分商城]PlayX对接中心
This commit is contained in:
8
web/src/lang/backend/en/mall/playxCenter.ts
Normal file
8
web/src/lang/backend/en/mall/playxCenter.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export default {
|
||||||
|
title: 'PlayX Integration Center',
|
||||||
|
desc: 'Manage orders, daily push, claim logs and user assets in one place.',
|
||||||
|
orders: 'Orders',
|
||||||
|
dailyPush: 'Daily Push',
|
||||||
|
claimLog: 'Claim Log',
|
||||||
|
userAsset: 'User Asset',
|
||||||
|
}
|
||||||
9
web/src/lang/backend/zh-cn/mall/playxCenter.ts
Normal file
9
web/src/lang/backend/zh-cn/mall/playxCenter.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export default {
|
||||||
|
title: 'PlayX 对接中心',
|
||||||
|
desc: '集中管理积分商城与 PlayX 的订单、推送、领取与资产数据。建议优先处理“发放子状态=失败可重试”的订单。',
|
||||||
|
orders: '统一订单',
|
||||||
|
dailyPush: '每日推送',
|
||||||
|
claimLog: '领取记录',
|
||||||
|
userAsset: '用户资产',
|
||||||
|
}
|
||||||
|
|
||||||
102
web/src/views/backend/mall/playxCenter/index.vue
Normal file
102
web/src/views/backend/mall/playxCenter/index.vue
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<template>
|
||||||
|
<div class="default-main">
|
||||||
|
<!-- 语言包注入是异步的:把 t() 调用和子组件渲染都延后到注入完成后,避免 intlify Not found -->
|
||||||
|
<template v-if="langReady">
|
||||||
|
<el-card shadow="never" class="mb-4">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">{{ t('mall.playxCenter.title') }}</div>
|
||||||
|
</template>
|
||||||
|
<div class="desc">{{ t('mall.playxCenter.desc') }}</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-tabs v-model="activeName" type="border-card">
|
||||||
|
<el-tab-pane :label="t('mall.playxCenter.orders')" name="orders">
|
||||||
|
<PlayxOrderIndex />
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="t('mall.playxCenter.dailyPush')" name="dailyPush">
|
||||||
|
<PlayxDailyPushIndex />
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="t('mall.playxCenter.claimLog')" name="claimLog">
|
||||||
|
<PlayxClaimLogIndex />
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="t('mall.playxCenter.userAsset')" name="userAsset">
|
||||||
|
<PlayxUserAssetIndex />
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import PlayxOrderIndex from '/@/views/backend/mall/playxOrder/index.vue'
|
||||||
|
import PlayxDailyPushIndex from '/@/views/backend/mall/playxDailyPush/index.vue'
|
||||||
|
import PlayxClaimLogIndex from '/@/views/backend/mall/playxClaimLog/index.vue'
|
||||||
|
import PlayxUserAssetIndex from '/@/views/backend/mall/playxUserAsset/index.vue'
|
||||||
|
import { useConfig } from '/@/stores/config'
|
||||||
|
import { mergeMessage } from '/@/lang/index'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'mall/playxCenter',
|
||||||
|
})
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const activeName = ref('orders')
|
||||||
|
const langReady = ref(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 由于语言包是按“路由”懒加载的:
|
||||||
|
* playxCenter 内部直接渲染了多个子页面组件(订单/推送/领取/资产),
|
||||||
|
* 如果对应菜单被禁用,子页面路由可能不会触发语言包加载,导致 t('mall.playx*') 显示为 key。
|
||||||
|
* 关键点:子页面组件在首次渲染阶段就会执行 t()。
|
||||||
|
* 因此语言包需要在首次渲染前(而不是 onMounted)完成 merge。
|
||||||
|
*/
|
||||||
|
async function ensurePlayxCenterLang() {
|
||||||
|
const config = useConfig()
|
||||||
|
const locale = config.lang.defaultLang
|
||||||
|
const prefix = `./backend/${locale}`
|
||||||
|
|
||||||
|
const loadPaths = [
|
||||||
|
`${prefix}/mall/playxCenter.ts`,
|
||||||
|
`${prefix}/mall/playxOrder.ts`,
|
||||||
|
`${prefix}/mall/playxDailyPush.ts`,
|
||||||
|
`${prefix}/mall/playxClaimLog.ts`,
|
||||||
|
`${prefix}/mall/playxUserAsset.ts`,
|
||||||
|
]
|
||||||
|
|
||||||
|
// 某些场景下 i18n 初始化可能晚于组件创建,这里做一次最小等待。
|
||||||
|
// 不会阻塞很久:通常 window.loadLangHandle 会在应用启动阶段就准备好。
|
||||||
|
while (!window.loadLangHandle) {
|
||||||
|
await new Promise((r) => setTimeout(r, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMap = window.loadLangHandle
|
||||||
|
for (const p of loadPaths) {
|
||||||
|
const loader = handleMap[p]
|
||||||
|
if (!loader) continue
|
||||||
|
const mod = await loader()
|
||||||
|
// 与 getLangFileMessage 的命名规则一致:namespace 应为 `mall/playxOrder` 这类路径
|
||||||
|
const pathName = p.slice(p.lastIndexOf(prefix) + (prefix.length + 1), p.lastIndexOf('.'))
|
||||||
|
mergeMessage(mod?.default ?? {}, pathName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await ensurePlayxCenterLang()
|
||||||
|
langReady.value = true
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.mb-4 {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
.card-header {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.desc {
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
Reference in New Issue
Block a user