Compare commits

...

1 Commits
main ... test

Author SHA1 Message Date
zhx
d81c9548a2 fix admin reward group bigint ids 2026-05-26 20:50:42 +08:00
6 changed files with 74 additions and 24 deletions

View File

@ -41,9 +41,11 @@
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"@vueuse/core": "catalog:",
"@types/json-bigint": "catalog:",
"ali-oss": "^6.23.0",
"antdv-next": "catalog:",
"dayjs": "catalog:",
"json-bigint": "catalog:",
"pinia": "catalog:",
"sockjs-client": "^1.6.1",
"stompjs": "^2.3.3",

View File

@ -1,3 +1,5 @@
import JsonBigint from 'json-bigint';
import { requestClient } from '#/api/request';
export interface LegacyPageResult<T = Record<string, any>> {
@ -5,6 +7,16 @@ export interface LegacyPageResult<T = Record<string, any>> {
total: number;
}
const jsonBigint = JsonBigint({ storeAsString: true });
function parseLegacyBodyWithBigint<T>(raw: string) {
const data = jsonBigint.parse(raw);
if (data?.errorCode === 401 || data?.errorCode !== 0) {
throw new Error(data?.errorMsg || data?.message || 'Error');
}
return data?.body as T;
}
export async function pagePropsSource(params: Record<string, any>) {
return requestClient.get<LegacyPageResult<Record<string, any>>>(
'/props/source/record/page',
@ -53,12 +65,18 @@ export async function listNotFamilyBySysOriginType(
}
export async function pagePropsActivityRewardGroup(params: Record<string, any>) {
return requestClient.get<LegacyPageResult<Record<string, any>>>(
const response = await requestClient.get<{ data: string }>(
'/props/activity/reward/group/page',
{
params,
responseReturn: 'raw',
responseType: 'text',
transformResponse: [(data) => data],
},
);
return parseLegacyBodyWithBigint<LegacyPageResult<Record<string, any>>>(
response.data,
);
}
export async function getByGroupId(id: number | string) {

View File

@ -1,8 +1,6 @@
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue';
import { pagePropsActivityRewardGroup } from '#/api/legacy/props';
import {
Button,
Drawer,
@ -13,8 +11,10 @@ import {
Table,
} from 'antdv-next';
import RewardRow from './reward-row.vue';
import { pagePropsActivityRewardGroup } from '#/api/legacy/props';
import { PROPS_SHELF_STATUS_OPTIONS } from '../shared';
import RewardRow from './reward-row.vue';
const props = defineProps<{
open: boolean;
@ -52,6 +52,11 @@ const shelfStatusOptions = PROPS_SHELF_STATUS_OPTIONS.map((item) => ({
value: item.value as any,
}));
function normalizeID(value: unknown) {
const text = String(value ?? '').trim();
return text && text !== '0' ? text : '';
}
async function loadData(reset = false) {
if (!props.open || !query.sysOrigin) {
return;
@ -62,7 +67,10 @@ async function loadData(reset = false) {
loading.value = true;
try {
const result = await pagePropsActivityRewardGroup({ ...query });
list.value = result.records || [];
list.value = (result.records || []).map((item: Record<string, any>) => ({
...item,
id: normalizeID(item.id),
}));
total.value = result.total || 0;
} finally {
loading.value = false;
@ -156,7 +164,7 @@ watch(
:total="total"
show-size-changer
@change="handlePageChange"
@showSizeChange="handlePageChange"
@show-size-change="handlePageChange"
/>
</div>
</Drawer>

View File

@ -16,8 +16,8 @@ import {
Spin,
Switch,
Table,
Tabs,
TabPane,
Tabs,
Tag,
} from 'antdv-next';
@ -53,6 +53,15 @@ function createLevel(level = 1, rechargeAmount = 10) {
};
}
function normalizeID(value: unknown) {
const text = String(value ?? '').trim();
return text && text !== '0' ? text : '';
}
function hasPositiveID(value: unknown) {
return /^\d+$/.test(normalizeID(value));
}
function defaultLevels() {
return [createLevel(1, 10), createLevel(2, 50), createLevel(3, 100)];
}
@ -170,7 +179,7 @@ function normalizeConfig(result: null | Record<string, any> | undefined) {
level: Number(item.level || index + 1),
rechargeAmount: Number.isFinite(rechargeAmount) ? rechargeAmount : 0,
rechargeAmountCents: Number(item.rechargeAmountCents || 0),
rewardGroupId: item.rewardGroupId ?? null,
rewardGroupId: normalizeID(item.rewardGroupId) || null,
rewardGroupName: String(item.rewardGroupName || ''),
rewardItems: Array.isArray(item.rewardItems) ? item.rewardItems : [],
rowKey: createRowKey(item.id || index),
@ -254,8 +263,8 @@ function handleRewardGroupSelect(row: Record<string, any>) {
groupPickerOpen.value = false;
return;
}
target.rewardGroupId = row.id;
target.rewardGroupName = row.name;
target.rewardGroupId = normalizeID(row.id) || null;
target.rewardGroupName = String(row.name || '');
target.rewardItems = Array.isArray(row.rewardConfigList) ? row.rewardConfigList : [];
groupPickerOpen.value = false;
}
@ -271,7 +280,6 @@ function validateBeforeSave() {
for (const item of levels) {
const level = Number(item.level || 0);
const amountCents = toAmountCents(item.rechargeAmount);
const rewardGroupId = Number(item.rewardGroupId || 0);
if (level <= 0) {
message.warning('档位必须大于 0');
return false;
@ -280,7 +288,7 @@ function validateBeforeSave() {
message.warning('首冲金额必须大于 0');
return false;
}
if (rewardGroupId <= 0) {
if (!hasPositiveID(item.rewardGroupId)) {
message.warning('每个档位都需要配置奖励资源组');
return false;
}
@ -317,7 +325,7 @@ async function submitForm() {
level: Number(item.level || 0),
rechargeAmount: formatAmount(item.rechargeAmount),
rechargeAmountCents: toAmountCents(item.rechargeAmount),
rewardGroupId: item.rewardGroupId ?? null,
rewardGroupId: normalizeID(item.rewardGroupId) || null,
rewardGroupName: String(item.rewardGroupName || ''),
})),
sysOrigin: selectedSysOrigin.value,
@ -407,7 +415,7 @@ watch(activeTab, (value) => {
<Button :loading="loading" @click="loadConfig">刷新</Button>
</div>
<Tabs v-model:activeKey="activeTab">
<Tabs v-model:active-key="activeTab">
<TabPane key="config" tab="奖励配置">
<div class="config-row">
<Space align="center" wrap>
@ -518,7 +526,7 @@ watch(activeTab, (value) => {
v-if="record.userAvatar"
class="user-avatar"
:style="avatarBackgroundStyle(record.userAvatar)"
/>
></div>
<div class="user-main">
<div class="user-name">{{ record.userNickname || '-' }}</div>
<div class="sub-text">

View File

@ -16,8 +16,8 @@ import {
Spin,
Switch,
Table,
Tabs,
TabPane,
Tabs,
Tag,
} from 'antdv-next';
@ -54,6 +54,15 @@ function createLevel(level = 1, rechargeAmount = 100, rewardGold = 0) {
};
}
function normalizeID(value: unknown) {
const text = String(value ?? '').trim();
return text && text !== '0' ? text : '';
}
function hasPositiveID(value: unknown) {
return /^\d+$/.test(normalizeID(value));
}
function defaultLevels() {
return [
createLevel(1, 100, 0),
@ -170,7 +179,7 @@ function normalizeConfig(result: null | Record<string, any> | undefined) {
rechargeAmount: Number.isFinite(rechargeAmount) ? rechargeAmount : 0,
rechargeAmountCents: Number(item.rechargeAmountCents || 0),
rewardGold: Number(item.rewardGold || 0),
rewardGroupId: item.rewardGroupId ?? null,
rewardGroupId: normalizeID(item.rewardGroupId) || null,
rewardGroupName: String(item.rewardGroupName || ''),
rewardItems: Array.isArray(item.rewardItems) ? item.rewardItems : [],
rowKey: createRowKey(item.id || index),
@ -259,8 +268,8 @@ function handleRewardGroupSelect(row: Record<string, any>) {
groupPickerOpen.value = false;
return;
}
target.rewardGroupId = row.id;
target.rewardGroupName = row.name;
target.rewardGroupId = normalizeID(row.id) || null;
target.rewardGroupName = String(row.name || '');
target.rewardItems = Array.isArray(row.rewardConfigList) ? row.rewardConfigList : [];
groupPickerOpen.value = false;
}
@ -277,7 +286,6 @@ function validateBeforeSave() {
const level = Number(item.level || 0);
const amountCents = toAmountCents(item.rechargeAmount);
const rewardGold = Number(item.rewardGold || 0);
const rewardGroupId = Number(item.rewardGroupId || 0);
if (level <= 0) {
message.warning('档位必须大于 0');
return false;
@ -286,7 +294,7 @@ function validateBeforeSave() {
message.warning('充值金额必须大于 0');
return false;
}
if (rewardGold <= 0 && rewardGroupId <= 0) {
if (rewardGold <= 0 && !hasPositiveID(item.rewardGroupId)) {
message.warning('每个档位至少要配置金币或奖励组');
return false;
}
@ -324,7 +332,7 @@ async function submitForm() {
rechargeAmount: formatAmount(item.rechargeAmount),
rechargeAmountCents: toAmountCents(item.rechargeAmount),
rewardGold: Number(item.rewardGold || 0),
rewardGroupId: item.rewardGroupId ?? null,
rewardGroupId: normalizeID(item.rewardGroupId) || null,
rewardGroupName: String(item.rewardGroupName || ''),
})),
sysOrigin: selectedSysOrigin.value,
@ -429,7 +437,7 @@ watch(activeTab, (value) => {
<Button :loading="loading" @click="loadConfig">刷新</Button>
</div>
<Tabs v-model:activeKey="activeTab">
<Tabs v-model:active-key="activeTab">
<TabPane key="config" tab="奖励配置">
<div class="config-row">
<Space align="center" wrap>
@ -551,7 +559,7 @@ watch(activeTab, (value) => {
v-if="record.userAvatar"
class="user-avatar"
:style="avatarBackgroundStyle(record.userAvatar)"
/>
></div>
<div class="user-main">
<div class="user-name">{{ record.userNickname || '-' }}</div>
<div class="sub-text">

6
pnpm-lock.yaml generated
View File

@ -480,6 +480,9 @@ importers:
apps:
dependencies:
'@types/json-bigint':
specifier: 'catalog:'
version: 1.0.4
'@vben/access':
specifier: workspace:*
version: link:../packages/effects/access
@ -534,6 +537,9 @@ importers:
dayjs:
specifier: 'catalog:'
version: 1.11.20
json-bigint:
specifier: 'catalog:'
version: 1.0.0
pinia:
specifier: ^3.0.4
version: 3.0.4(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3))