From e3d4ec46243f9e1bfd3d72c1486cc9af352e5ba1 Mon Sep 17 00:00:00 2001 From: zhenhui <1276357500@qq.com> Date: Fri, 24 Jul 2026 12:01:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=AF=8F=E6=97=A5=E6=8E=A8?= =?UTF-8?q?=E9=80=81=E5=92=8C=E7=A7=AF=E5=88=86=E8=BD=AC=E5=8C=96=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/mall/PlayxConfig.php | 12 ++- app/admin/lang/en.php | 2 + app/admin/lang/zh-cn.php | 2 + app/common/library/MallPointsConversion.php | 4 +- web/src/api/backend/mall/playxConfig.ts | 13 +-- web/src/lang/backend/en/mall/pageIntro.ts | 4 +- web/src/lang/backend/en/mall/playxConfig.ts | 1 + .../lang/backend/en/mall/playxDailyPush.ts | 24 ++--- web/src/lang/backend/en/mall/userAsset.ts | 26 ++--- web/src/lang/backend/zh-cn/mall/pageIntro.ts | 4 +- .../lang/backend/zh-cn/mall/playxConfig.ts | 1 + .../views/backend/mall/dailyPush/index.vue | 11 ++- .../views/backend/mall/playxConfig/index.vue | 12 ++- .../backend/mall/playxDailyPush/index.vue | 95 ++++++++++++++++--- .../views/backend/mall/userAsset/index.vue | 58 +++++++++-- 15 files changed, 204 insertions(+), 65 deletions(-) diff --git a/app/admin/controller/mall/PlayxConfig.php b/app/admin/controller/mall/PlayxConfig.php index 8ae7aee..9f2663f 100644 --- a/app/admin/controller/mall/PlayxConfig.php +++ b/app/admin/controller/mall/PlayxConfig.php @@ -144,9 +144,17 @@ class PlayxConfig extends Backend } catch (\Throwable $e) { Db::rollback(); - return $this->error($e->getMessage()); + return $this->error(__($e->getMessage())); } - return $this->success(__('Operation completed'), $stats); + return $this->success( + sprintf( + __('Lifetime points calculation completed'), + $stats['processed'], + $stats['updated'], + $stats['skipped'] + ), + $stats + ); } } diff --git a/app/admin/lang/en.php b/app/admin/lang/en.php index d1dfe68..f85d677 100644 --- a/app/admin/lang/en.php +++ b/app/admin/lang/en.php @@ -28,6 +28,8 @@ return [ 'Deleted successfully' => 'Deleted successfully!', 'Parameter error' => 'Parameter error!', 'Lifetime points source is disabled' => 'Lifetime points source is disabled', + 'Operation completed' => 'Operation completed!', + 'Lifetime points calculation completed' => 'Lifetime conversion done: %d processed, %d updated, %d skipped', 'File uploaded successfully' => 'File uploaded successfully', 'No files were uploaded' => 'No files were uploaded', 'The uploaded file format is not allowed' => 'The uploaded file format is no allowance.', diff --git a/app/admin/lang/zh-cn.php b/app/admin/lang/zh-cn.php index 9f797dc..a26b869 100644 --- a/app/admin/lang/zh-cn.php +++ b/app/admin/lang/zh-cn.php @@ -28,6 +28,8 @@ return [ 'Deleted successfully' => '删除成功!', 'Parameter error' => '参数错误!', 'Lifetime points source is disabled' => '终身总输赢积分来源未启用', + 'Operation completed' => '操作完成!', + 'Lifetime points calculation completed' => '终身总输赢积分折算完成:共处理 %d 条,更新 %d 条,跳过 %d 条', 'Please use the %s field to sort before operating' => '请使用 %s 字段排序后再操作', 'File uploaded successfully' => '文件上传成功!', 'No files were uploaded' => '没有文件被上传', diff --git a/app/common/library/MallPointsConversion.php b/app/common/library/MallPointsConversion.php index a14440d..662dff4 100644 --- a/app/common/library/MallPointsConversion.php +++ b/app/common/library/MallPointsConversion.php @@ -142,13 +142,13 @@ final class MallPointsConversion public static function recalculateAllLifetimePoints(MallBusinessConfig $row): array { if (intval($row->lifetime_points_enabled ?? 0) !== 1) { - throw new \RuntimeException(__('Lifetime points source is disabled')); + throw new \RuntimeException('Lifetime points source is disabled'); } $config = self::configFromRow($row); $ratio = floatval($config['lifetime_points_ratio'] ?? 0); if ($ratio < 0) { - throw new \RuntimeException(__('Parameter error')); + throw new \RuntimeException('Parameter error'); } $stats = ['processed' => 0, 'updated' => 0, 'skipped' => 0]; diff --git a/web/src/api/backend/mall/playxConfig.ts b/web/src/api/backend/mall/playxConfig.ts index e6ed998..8327ae9 100644 --- a/web/src/api/backend/mall/playxConfig.ts +++ b/web/src/api/backend/mall/playxConfig.ts @@ -29,13 +29,8 @@ export function save(data: anyObj) { } export function calculateLifetimePoints() { - return createAxios( - { - url: actionUrl.get('calculateLifetimePoints'), - method: 'post', - }, - { - showSuccessMessage: true, - } - ) + return createAxios({ + url: actionUrl.get('calculateLifetimePoints'), + method: 'post', + }) } diff --git a/web/src/lang/backend/en/mall/pageIntro.ts b/web/src/lang/backend/en/mall/pageIntro.ts index b514972..516c5ac 100644 --- a/web/src/lang/backend/en/mall/pageIntro.ts +++ b/web/src/lang/backend/en/mall/pageIntro.ts @@ -13,7 +13,7 @@ export default { }, dailyPush: { title: 'About this page', - desc: 'Daily T+1 snapshots pushed by the partner; rows are stored here and drive user-asset related updates.', + desc: 'Daily T+1 snapshots from the partner; each row stores converted points per mall settings and syncs user assets.', }, claimLog: { title: 'About this page', @@ -57,6 +57,6 @@ export default { }, playxConfig: { title: 'About this page', - desc: 'Edit return/unlock/points-to-cash ratios used by daily push and asset APIs; values are stored in mall_business_config and apply immediately after save.', + desc: 'Configure daily and lifetime loss-to-points sources (switches and ratios), mall open date, unlock ratio, and points-to-cash ratio. Open date changes take effect the next calendar day.', }, } diff --git a/web/src/lang/backend/en/mall/playxConfig.ts b/web/src/lang/backend/en/mall/playxConfig.ts index c0401d8..29fa759 100644 --- a/web/src/lang/backend/en/mall/playxConfig.ts +++ b/web/src/lang/backend/en/mall/playxConfig.ts @@ -12,6 +12,7 @@ export default { calculate_lifetime_btn: 'Calculate lifetime loss points', calculate_lifetime_tip: 'Batch update from latest daily push lifetime field and ratio above.', calculate_lifetime_confirm: 'Recalculate all members with the current lifetime ratio (reverses previous lifetime conversion first). Continue?', + calculate_lifetime_success: 'Lifetime conversion done: {processed} processed, {updated} updated, {skipped} skipped', section_mall_open: 'Mall open date', mall_open_date: 'Mall open date', mall_open_date_tip: 'Takes effect the next calendar day. E.g. set Aug 1: from Aug 2, daily push rows with business date on/after Aug 1 convert yesterday loss to points.', diff --git a/web/src/lang/backend/en/mall/playxDailyPush.ts b/web/src/lang/backend/en/mall/playxDailyPush.ts index 13fff88..2c6e7b8 100644 --- a/web/src/lang/backend/en/mall/playxDailyPush.ts +++ b/web/src/lang/backend/en/mall/playxDailyPush.ts @@ -1,14 +1,14 @@ export default { - id: 'id', - user_id: 'user_id', - date: 'date', - username: 'username', - yesterday_win_loss_net: 'yesterday_win_loss_net', - converted_points: 'converted_points', - yesterday_total_deposit: 'yesterday_total_deposit', - lifetime_total_deposit: 'lifetime_total_deposit', - lifetime_total_withdraw: 'lifetime_total_withdraw', - lifetime_win_loss_net: 'lifetime_win_loss_net', - create_time: 'create_time', - 'quick Search Fields': 'id', + id: 'ID', + user_id: 'PlayX user ID', + date: 'Business date', + username: 'Username', + yesterday_win_loss_net: 'Yesterday net win/loss', + converted_points: 'Converted points', + yesterday_total_deposit: 'Yesterday total deposit', + lifetime_total_deposit: 'Lifetime total deposit', + lifetime_total_withdraw: 'Lifetime total withdraw', + lifetime_win_loss_net: 'Lifetime net win/loss', + create_time: 'Created at', + 'quick Search Fields': 'ID', } diff --git a/web/src/lang/backend/en/mall/userAsset.ts b/web/src/lang/backend/en/mall/userAsset.ts index 3908987..648d0ce 100644 --- a/web/src/lang/backend/en/mall/userAsset.ts +++ b/web/src/lang/backend/en/mall/userAsset.ts @@ -1,17 +1,17 @@ export default { - id: 'id', - username: 'username', - phone: 'phone', - playx_user_id: 'playX_user_id', - locked_points: 'locked_points', - available_points: 'available_points', + id: 'ID', + username: 'Username', + phone: 'Phone', + playx_user_id: 'PlayX user ID', + locked_points: 'Locked points', + available_points: 'Available points', adjust_available_points: 'Adjust points', - today_limit: 'today_limit', - today_claimed: 'today_claimed', - today_limit_date: 'today_limit_date', - points_claim_cap: 'Points claim cap', + today_limit: 'Daily claim cap', + today_claimed: 'Claimed today', + today_limit_date: 'Daily cap date', + points_claim_cap: 'Lifetime claim cap', total_points_claimed: 'Total points claimed', - create_time: 'create_time', - update_time: 'update_time', - 'quick Search Fields': 'id, playX_user_id, username, phone', + create_time: 'Created at', + update_time: 'Updated at', + 'quick Search Fields': 'ID, PlayX user ID, username, phone', } diff --git a/web/src/lang/backend/zh-cn/mall/pageIntro.ts b/web/src/lang/backend/zh-cn/mall/pageIntro.ts index 8f06c0b..c86dfea 100644 --- a/web/src/lang/backend/zh-cn/mall/pageIntro.ts +++ b/web/src/lang/backend/zh-cn/mall/pageIntro.ts @@ -13,7 +13,7 @@ export default { }, dailyPush: { title: '页面说明', - desc: '展示合作方 T+1 每日推送的经营数据快照;接口写入后在此留痕,并用于同步用户资产相关字段。', + desc: '展示合作方 T+1 每日推送的经营数据快照;入库时按商城参数折算「转换积分」并同步用户资产。', }, claimLog: { title: '页面说明', @@ -57,6 +57,6 @@ export default { }, playxConfig: { title: '页面说明', - desc: '配置每日推送用到的返还比例、解锁比例及积分折算现金比例;保存后立即作用于接口逻辑(mall_business_config)。', + desc: '配置昨日净输赢、终身总输赢两种积分来源(开关与兑换比例)、商城开放日,以及解锁比例与积分折算现金比例;保存后按规则生效(开放日隔日生效)。', }, } diff --git a/web/src/lang/backend/zh-cn/mall/playxConfig.ts b/web/src/lang/backend/zh-cn/mall/playxConfig.ts index fc6fc38..ff5cbce 100644 --- a/web/src/lang/backend/zh-cn/mall/playxConfig.ts +++ b/web/src/lang/backend/zh-cn/mall/playxConfig.ts @@ -12,6 +12,7 @@ export default { calculate_lifetime_btn: '一键计算终身总输赢', calculate_lifetime_tip: '按各会员最新每日推送中的终身总输赢与上方比例,批量更新待领取积分与领取上限。无终身总输赢数据的会员将跳过。', calculate_lifetime_confirm: '将按当前终身总输赢兑换比例重新折算全部会员积分,已折算部分会先扣回再按新比例增加。是否继续?', + calculate_lifetime_success: '终身总输赢积分折算完成:共处理 {processed} 条,更新 {updated} 条,跳过 {skipped} 条', section_mall_open: '商城开放日', mall_open_date: '商城开放日', mall_open_date_tip: '设置后隔日生效。例如设为 8 月 1 日,则从 8 月 2 日起对业务日期为 8 月 1 日及之后的每日推送执行「昨日净输赢」转积分(T+1:开放日前一日产生的输赢在开放日次日开始折算)。', diff --git a/web/src/views/backend/mall/dailyPush/index.vue b/web/src/views/backend/mall/dailyPush/index.vue index 983d077..f38c0b4 100644 --- a/web/src/views/backend/mall/dailyPush/index.vue +++ b/web/src/views/backend/mall/dailyPush/index.vue @@ -70,7 +70,9 @@ const baTable = new baTableClass( label: t('mall.dailyPush.username'), prop: 'username', align: 'center', + minWidth: 95, operatorPlaceholder: t('Fuzzy query'), + showOverflowTooltip: true, sortable: false, operator: 'LIKE', }, @@ -78,6 +80,7 @@ const baTable = new baTableClass( label: t('mall.dailyPush.yesterday_win_loss_net'), prop: 'yesterday_win_loss_net', align: 'center', + minWidth: 90, operator: 'RANGE', sortable: 'custom', }, @@ -85,14 +88,15 @@ const baTable = new baTableClass( label: t('mall.dailyPush.converted_points'), prop: 'converted_points', align: 'center', + minWidth: 80, operator: 'RANGE', sortable: 'custom', - width: 100, }, { label: t('mall.dailyPush.yesterday_total_deposit'), prop: 'yesterday_total_deposit', align: 'center', + minWidth: 90, operator: 'RANGE', sortable: 'custom', }, @@ -100,6 +104,7 @@ const baTable = new baTableClass( label: t('mall.dailyPush.lifetime_total_deposit'), prop: 'lifetime_total_deposit', align: 'center', + minWidth: 90, operator: 'RANGE', sortable: 'custom', }, @@ -107,7 +112,7 @@ const baTable = new baTableClass( label: t('mall.dailyPush.lifetime_total_withdraw'), prop: 'lifetime_total_withdraw', align: 'center', - minWidth: 95, + minWidth: 90, operator: 'RANGE', sortable: 'custom', }, @@ -115,7 +120,7 @@ const baTable = new baTableClass( label: t('mall.dailyPush.lifetime_win_loss_net'), prop: 'lifetime_win_loss_net', align: 'center', - minWidth: 95, + minWidth: 90, operator: 'RANGE', sortable: 'custom', }, diff --git a/web/src/views/backend/mall/playxConfig/index.vue b/web/src/views/backend/mall/playxConfig/index.vue index ae95aa5..4838475 100644 --- a/web/src/views/backend/mall/playxConfig/index.vue +++ b/web/src/views/backend/mall/playxConfig/index.vue @@ -113,7 +113,7 @@ - diff --git a/web/src/views/backend/mall/userAsset/index.vue b/web/src/views/backend/mall/userAsset/index.vue index 2d033a3..1c1bdf2 100644 --- a/web/src/views/backend/mall/userAsset/index.vue +++ b/web/src/views/backend/mall/userAsset/index.vue @@ -45,6 +45,7 @@ const baTable = new baTableClass( prop: 'username', align: 'center', operatorPlaceholder: t('Fuzzy query'), + showOverflowTooltip: true, sortable: false, operator: 'LIKE', }, @@ -52,7 +53,9 @@ const baTable = new baTableClass( label: t('mall.userAsset.phone'), prop: 'phone', align: 'center', + minWidth: 100, operatorPlaceholder: t('Fuzzy query'), + showOverflowTooltip: true, sortable: false, operator: 'LIKE', }, @@ -60,16 +63,59 @@ const baTable = new baTableClass( label: t('mall.userAsset.playx_user_id'), prop: 'playx_user_id', align: 'center', + minWidth: 120, operatorPlaceholder: t('Fuzzy query'), sortable: false, operator: 'LIKE', }, - { label: t('mall.userAsset.locked_points'), prop: 'locked_points', align: 'center', operator: 'RANGE', sortable: false }, - { label: t('mall.userAsset.available_points'), prop: 'available_points', align: 'center', operator: 'RANGE', sortable: false }, - { label: t('mall.userAsset.today_limit'), prop: 'today_limit', align: 'center', operator: 'RANGE', sortable: false }, - { label: t('mall.userAsset.today_claimed'), prop: 'today_claimed', align: 'center', operator: 'RANGE', sortable: false }, - { label: t('mall.userAsset.points_claim_cap'), prop: 'points_claim_cap', align: 'center', operator: 'RANGE', sortable: false }, - { label: t('mall.userAsset.total_points_claimed'), prop: 'total_points_claimed', align: 'center', operator: 'RANGE', sortable: false }, + { + label: t('mall.userAsset.locked_points'), + prop: 'locked_points', + align: 'center', + minWidth: 120, + operator: 'RANGE', + sortable: true, + }, + { + label: t('mall.userAsset.available_points'), + prop: 'available_points', + align: 'center', + minWidth: 120, + operator: 'RANGE', + sortable: true, + }, + { + label: t('mall.userAsset.today_limit'), + prop: 'today_limit', + align: 'center', + minWidth: 160, + operator: 'RANGE', + sortable: true, + }, + { + label: t('mall.userAsset.today_claimed'), + prop: 'today_claimed', + align: 'center', + minWidth: 120, + operator: 'RANGE', + sortable: true, + }, + { + label: t('mall.userAsset.points_claim_cap'), + prop: 'points_claim_cap', + align: 'center', + minWidth: 160, + operator: 'RANGE', + sortable: true, + }, + { + label: t('mall.userAsset.total_points_claimed'), + prop: 'total_points_claimed', + align: 'center', + minWidth: 160, + operator: 'RANGE', + sortable: true, + }, { label: t('mall.userAsset.today_limit_date'), prop: 'today_limit_date',