feat(admin): 从已有玩家升级代理、修复 i18n 与过期 .js 冲突

- 新建一级代理改为选择已有玩家;新建用户可选一级代理

- 操作日志/注单等扁平 key 翻译;清理 src 内误生成 .js,Vite 优先解析 .ts

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-03 15:42:15 +08:00
parent cbfa18d1d3
commit 3b739982a1
27 changed files with 625 additions and 165 deletions

View File

@@ -15,7 +15,7 @@ import {
type PlayerDetail,
type PlayerCreateForm,
type PlayerEditForm,
} from './user-form';
} from './user-form.ts';
import {
formatAmount,
formatAmountFull,
@@ -121,7 +121,9 @@ async function submitCreate() {
createLoading.value = true;
try {
await api.post('/admin/users', payload);
ElMessage.success(t('msg.player_created'));
ElMessage.success(
createForm.value.asTier1Agent ? t('msg.agent_created') : t('msg.player_created'),
);
createVisible.value = false;
load();
} catch (e: unknown) {
@@ -388,35 +390,68 @@ function statusLabel(s: string) {
<el-form-item :label="t('user.field.confirm_password')" required>
<el-input v-model="createForm.confirmPassword" type="text" autocomplete="off" />
</el-form-item>
<el-form-item :label="t('user.filter.agent')">
<el-select
v-model="createForm.parentId"
:placeholder="t('user.ph.no_agent')"
clearable
style="width: 100%"
>
<el-option
v-for="a in agentOptions"
:key="a.id"
:label="`${a.username} (#${a.id})`"
:value="a.id"
/>
</el-select>
<div class="field-hint">{{ t('user.hint.no_agent') }}</div>
<el-form-item :label="t('user.field.account_type')">
<el-radio-group v-model="createForm.asTier1Agent">
<el-radio :value="false">{{ t('user.type.player') }}</el-radio>
<el-radio :value="true">{{ t('user.type.tier1_agent') }}</el-radio>
</el-radio-group>
<div class="field-hint">{{ t('user.hint.account_type') }}</div>
</el-form-item>
<template v-if="!createForm.asTier1Agent">
<el-form-item :label="t('user.filter.agent')">
<el-select
v-model="createForm.parentId"
:placeholder="t('user.ph.no_agent')"
clearable
style="width: 100%"
>
<el-option
v-for="a in agentOptions"
:key="a.id"
:label="`${a.username} (#${a.id})`"
:value="a.id"
/>
</el-select>
<div class="field-hint">{{ t('user.hint.no_agent') }}</div>
</el-form-item>
</template>
<template v-else>
<el-form-item :label="t('agent.field.credit_limit')" required>
<el-input-number
v-model="createForm.creditLimit"
:min="0"
:step="10000"
style="width: 100%"
/>
<div class="field-hint">{{ t('agent.hint.credit_limit') }}</div>
</el-form-item>
<el-form-item :label="t('agent.field.cashback_rate')">
<el-input-number
v-model="createForm.cashbackRate"
:min="0"
:max="1"
:step="0.001"
:precision="4"
style="width: 100%"
/>
<div class="field-hint">{{ t('agent.hint.cashback_example') }}</div>
</el-form-item>
</template>
<el-form-item :label="t('user.field.phone')">
<el-input v-model="createForm.phone" :placeholder="t('common.optional')" />
</el-form-item>
<el-form-item :label="t('user.field.email')">
<el-input v-model="createForm.email" :placeholder="t('common.optional')" />
</el-form-item>
<el-form-item :label="t('user.field.initial_balance')">
<el-input-number v-model="createForm.initialDeposit" :min="0" :step="100" style="width: 100%" />
<div class="field-hint">{{ t('user.hint.initial_balance') }}</div>
</el-form-item>
<el-form-item :label="t('user.field.deposit_remark')">
<el-input v-model="createForm.remark" :placeholder="t('user.ph.remark_initial')" />
</el-form-item>
<template v-if="!createForm.asTier1Agent">
<el-form-item :label="t('user.field.initial_balance')">
<el-input-number v-model="createForm.initialDeposit" :min="0" :step="100" style="width: 100%" />
<div class="field-hint">{{ t('user.hint.initial_balance') }}</div>
</el-form-item>
<el-form-item :label="t('user.field.deposit_remark')">
<el-input v-model="createForm.remark" :placeholder="t('user.ph.remark_initial')" />
</el-form-item>
</template>
</el-form>
<template #footer>
<el-button @click="createVisible = false">{{ t('common.cancel') }}</el-button>