Compare commits
2 Commits
72b43759f1
...
502404af17
| Author | SHA1 | Date | |
|---|---|---|---|
| 502404af17 | |||
| 76aa9bde8b |
@@ -99,6 +99,7 @@
|
|||||||
"eslint-plugin-vue": "^9.27.0",
|
"eslint-plugin-vue": "^9.27.0",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
"husky": "^9.1.5",
|
"husky": "^9.1.5",
|
||||||
|
"iconv-lite": "^0.7.2",
|
||||||
"lint-staged": "^15.5.2",
|
"lint-staged": "^15.5.2",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
|
|||||||
11
saiadmin-artd/pnpm-lock.yaml
generated
11
saiadmin-artd/pnpm-lock.yaml
generated
@@ -144,6 +144,9 @@ importers:
|
|||||||
husky:
|
husky:
|
||||||
specifier: ^9.1.5
|
specifier: ^9.1.5
|
||||||
version: 9.1.7
|
version: 9.1.7
|
||||||
|
iconv-lite:
|
||||||
|
specifier: ^0.7.2
|
||||||
|
version: 0.7.2
|
||||||
lint-staged:
|
lint-staged:
|
||||||
specifier: ^15.5.2
|
specifier: ^15.5.2
|
||||||
version: 15.5.2
|
version: 15.5.2
|
||||||
@@ -2549,6 +2552,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
iconv-lite@0.7.2:
|
||||||
|
resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
ieee754@1.2.1:
|
ieee754@1.2.1:
|
||||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||||
|
|
||||||
@@ -6767,6 +6774,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer: 2.1.2
|
safer-buffer: 2.1.2
|
||||||
|
|
||||||
|
iconv-lite@0.7.2:
|
||||||
|
dependencies:
|
||||||
|
safer-buffer: 2.1.2
|
||||||
|
|
||||||
ieee754@1.2.1: {}
|
ieee754@1.2.1: {}
|
||||||
|
|
||||||
ignore@5.3.2: {}
|
ignore@5.3.2: {}
|
||||||
|
|||||||
@@ -30,3 +30,37 @@ export function fetchRechargeBarChart() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 玩家充值记录项 */
|
||||||
|
export interface WalletRecordItem {
|
||||||
|
player_name: string
|
||||||
|
coin: number
|
||||||
|
create_time: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作台-玩家充值记录(最新50条)
|
||||||
|
* @returns 列表
|
||||||
|
*/
|
||||||
|
export function fetchWalletRecordList() {
|
||||||
|
return request.get<WalletRecordItem[]>({
|
||||||
|
url: '/core/dice/dashboard/walletRecordList'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增玩家记录项 */
|
||||||
|
export interface NewPlayerItem {
|
||||||
|
name: string
|
||||||
|
coin: number
|
||||||
|
total_ticket_count: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作台-新增玩家记录(最新50条)
|
||||||
|
* @returns 列表
|
||||||
|
*/
|
||||||
|
export function fetchNewPlayerList() {
|
||||||
|
return request.get<NewPlayerItem[]>({
|
||||||
|
url: '/core/dice/dashboard/newPlayerList'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,15 @@
|
|||||||
<SalesOverview />
|
<SalesOverview />
|
||||||
</ElCol>
|
</ElCol>
|
||||||
</ElRow>
|
</ElRow>
|
||||||
|
|
||||||
|
<ElRow :gutter="20">
|
||||||
|
<ElCol :sm="24" :md="12" :lg="12">
|
||||||
|
<WalletRecordList />
|
||||||
|
</ElCol>
|
||||||
|
<ElCol :sm="24" :md="12" :lg="12">
|
||||||
|
<NewPlayerList />
|
||||||
|
</ElCol>
|
||||||
|
</ElRow>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="userInfo.dashboard === 'work'">
|
<template v-if="userInfo.dashboard === 'work'">
|
||||||
@@ -34,6 +43,8 @@
|
|||||||
import CardList from './modules/card-list.vue'
|
import CardList from './modules/card-list.vue'
|
||||||
import ActiveUser from './modules/active-user.vue'
|
import ActiveUser from './modules/active-user.vue'
|
||||||
import SalesOverview from './modules/sales-overview.vue'
|
import SalesOverview from './modules/sales-overview.vue'
|
||||||
|
import WalletRecordList from './modules/wallet-record-list.vue'
|
||||||
|
import NewPlayerList from './modules/new-player-list.vue'
|
||||||
import NewUser from './modules/new-user.vue'
|
import NewUser from './modules/new-user.vue'
|
||||||
import Dynamic from './modules/dynamic-stats.vue'
|
import Dynamic from './modules/dynamic-stats.vue'
|
||||||
import TodoList from './modules/todo-list.vue'
|
import TodoList from './modules/todo-list.vue'
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<template>
|
||||||
|
<div class="art-card p-5 overflow-hidden mb-5 max-sm:mb-4">
|
||||||
|
<div class="art-card-header mb-4">
|
||||||
|
<div class="title">
|
||||||
|
<h4>新增玩家</h4>
|
||||||
|
<p class="text-g-600 text-sm mt-1">最新50条新增玩家记录</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ArtTable
|
||||||
|
class="w-full"
|
||||||
|
:data="tableData"
|
||||||
|
style="width: 100%"
|
||||||
|
size="default"
|
||||||
|
:border="false"
|
||||||
|
:stripe="true"
|
||||||
|
:header-cell-style="{ background: 'transparent' }"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
<ElTableColumn label="玩家" prop="name" min-width="120" />
|
||||||
|
<ElTableColumn label="余额" prop="coin" min-width="120" align="right">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ formatCoin(scope.row.coin) }}
|
||||||
|
</template>
|
||||||
|
</ElTableColumn>
|
||||||
|
<ElTableColumn label="抽奖券" prop="total_ticket_count" min-width="100" align="right" />
|
||||||
|
</template>
|
||||||
|
</ArtTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { fetchNewPlayerList, type NewPlayerItem } from '@/api/dashboard'
|
||||||
|
|
||||||
|
const tableData = ref<NewPlayerItem[]>([])
|
||||||
|
|
||||||
|
function formatCoin(val: number | undefined): string {
|
||||||
|
if (val === undefined || val === null) return '0.00'
|
||||||
|
return Number(val).toFixed(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchNewPlayerList().then((data) => {
|
||||||
|
tableData.value = Array.isArray(data) ? data : []
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<template>
|
||||||
|
<div class="art-card p-5 overflow-hidden mb-5 max-sm:mb-4">
|
||||||
|
<div class="art-card-header mb-4">
|
||||||
|
<div class="title">
|
||||||
|
<h4>玩家充值记录</h4>
|
||||||
|
<p class="text-g-600 text-sm mt-1">最新50条充值记录</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ArtTable
|
||||||
|
class="w-full"
|
||||||
|
:data="tableData"
|
||||||
|
style="width: 100%"
|
||||||
|
size="default"
|
||||||
|
:border="false"
|
||||||
|
:stripe="true"
|
||||||
|
:header-cell-style="{ background: 'transparent' }"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
<ElTableColumn label="玩家" prop="player_name" min-width="120" />
|
||||||
|
<ElTableColumn label="充值金额" prop="coin" min-width="120" align="right">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ formatCoin(scope.row.coin) }}
|
||||||
|
</template>
|
||||||
|
</ElTableColumn>
|
||||||
|
<ElTableColumn label="充值时间" prop="create_time" min-width="170" />
|
||||||
|
</template>
|
||||||
|
</ArtTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { fetchWalletRecordList, type WalletRecordItem } from '@/api/dashboard'
|
||||||
|
|
||||||
|
const tableData = ref<WalletRecordItem[]>([])
|
||||||
|
|
||||||
|
function formatCoin(val: number | undefined): string {
|
||||||
|
if (val === undefined || val === null) return '0.00'
|
||||||
|
return Number(val).toFixed(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchWalletRecordList().then((data) => {
|
||||||
|
tableData.value = Array.isArray(data) ? data : []
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
1-10000,档位内按权重比抽取。
|
1-10000,档位内按权重比抽取。
|
||||||
</div>
|
</div>
|
||||||
<div v-loading="loading" class="dialog-body">
|
<div v-loading="loading" class="dialog-body">
|
||||||
<!-- 一级:方向;二级档位放在各方向 pane 内,切换方向时二级能正常显示 -->
|
<!-- 一级:方向(懒加载避免逆时针柱状图在隐藏容器内初始化导致不显示);二级档位 -->
|
||||||
<el-tabs v-model="activeDirection" type="card" class="direction-tabs">
|
<el-tabs v-model="activeDirection" type="card" class="direction-tabs" :lazy="true">
|
||||||
<el-tab-pane label="顺时针" name="0">
|
<el-tab-pane label="顺时针" name="0">
|
||||||
<el-tabs v-model="activeTier" type="card" class="tier-tabs">
|
<el-tabs v-model="activeTier" type="card" class="tier-tabs">
|
||||||
<el-tab-pane v-for="t in tierKeys" :key="'cw-' + t" :label="t" :name="t">
|
<el-tab-pane v-for="t in tierKeys" :key="'cw-' + t" :label="t" :name="t">
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="chart-wrap" v-if="t !== 'T4' && t !== 'T5'">
|
<div class="chart-wrap" v-if="t !== 'T4' && t !== 'T5'">
|
||||||
<ArtBarChart
|
<ArtBarChart
|
||||||
|
:key="'cw-' + activeDirection + '-' + t"
|
||||||
x-axis-name="点数"
|
x-axis-name="点数"
|
||||||
:x-axis-data="getTierChartLabels(t)"
|
:x-axis-data="getTierChartLabels(t)"
|
||||||
:data="getTierChartDataForCurrentDirection(t)"
|
:data="getTierChartDataForCurrentDirection(t)"
|
||||||
@@ -162,6 +163,7 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="chart-wrap" v-if="t !== 'T4' && t !== 'T5'">
|
<div class="chart-wrap" v-if="t !== 'T4' && t !== 'T5'">
|
||||||
<ArtBarChart
|
<ArtBarChart
|
||||||
|
:key="'ccw-' + activeDirection + '-' + t"
|
||||||
x-axis-name="点数"
|
x-axis-name="点数"
|
||||||
:x-axis-data="getTierChartLabels(t)"
|
:x-axis-data="getTierChartLabels(t)"
|
||||||
:data="getTierChartDataForCurrentDirection(t)"
|
:data="getTierChartDataForCurrentDirection(t)"
|
||||||
@@ -470,9 +472,9 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 按 DiceReward 主键 id 收集:每条记录一条 { id, weight },直接用于后端按 id 更新 */
|
/** 按 DiceReward 主键 id 收集:每条记录一条 { id, reward_id, weight },后端按 id 更新(reward_id 作回退) */
|
||||||
function collectItems(): Array<{ id: number; weight: number }> {
|
function collectItems(): Array<{ id: number; reward_id: number; weight: number }> {
|
||||||
const items: Array<{ id: number; weight: number }> = []
|
const items: Array<{ id: number; reward_id: number; weight: number }> = []
|
||||||
for (const t of TIER_KEYS) {
|
for (const t of TIER_KEYS) {
|
||||||
const tierData = grouped.value[t]
|
const tierData = grouped.value[t]
|
||||||
if (!tierData) continue
|
if (!tierData) continue
|
||||||
@@ -482,7 +484,7 @@
|
|||||||
const rid = row.reward_id != null ? Number(row.reward_id) : 0
|
const rid = row.reward_id != null ? Number(row.reward_id) : 0
|
||||||
if (rid <= 0) continue
|
if (rid <= 0) continue
|
||||||
const w = isWeightDisabled(row, t) ? 10000 : toWeightPrecision(row.weight ?? 1)
|
const w = isWeightDisabled(row, t) ? 10000 : toWeightPrecision(row.weight ?? 1)
|
||||||
items.push({ id: rid, weight: w })
|
items.push({ id: rid, reward_id: rid, weight: w })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -536,6 +538,7 @@
|
|||||||
}
|
}
|
||||||
.chart-wrap {
|
.chart-wrap {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
min-height: 200px;
|
||||||
}
|
}
|
||||||
.weight-sum {
|
.weight-sum {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
|||||||
@@ -173,6 +173,60 @@ class DiceDashboardController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作台-玩家充值记录:最新50条(admin_id=当前管理员及子管理员,type=0)
|
||||||
|
* 返回:玩家账号(DicePlayer.username)、充值金额(coin)、充值时间(create_time)
|
||||||
|
*/
|
||||||
|
#[Permission('工作台数据统计', 'core:console:list')]
|
||||||
|
public function walletRecordList(): Response
|
||||||
|
{
|
||||||
|
$adminInfo = $this->adminInfo ?? null;
|
||||||
|
$query = DicePlayerWalletRecord::with([
|
||||||
|
'dicePlayer' => function ($q) {
|
||||||
|
$q->field('id,username');
|
||||||
|
},
|
||||||
|
])
|
||||||
|
->where('type', 0)
|
||||||
|
->order('create_time', 'desc')
|
||||||
|
->limit(50);
|
||||||
|
AdminScopeHelper::applyAdminScope($query, $adminInfo);
|
||||||
|
$list = $query->select();
|
||||||
|
$rows = [];
|
||||||
|
foreach ($list as $row) {
|
||||||
|
$player = $row->dicePlayer;
|
||||||
|
$rows[] = [
|
||||||
|
'player_name' => $player ? $player->getAttr('username') : '',
|
||||||
|
'coin' => $row->getAttr('coin'),
|
||||||
|
'create_time' => $row->getAttr('create_time'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $this->success($rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作台-新增玩家记录:最新50条(admin_id=当前管理员及子管理员)
|
||||||
|
* 返回:玩家账号(username)、余额(coin)、抽奖券(total_ticket_count)
|
||||||
|
*/
|
||||||
|
#[Permission('工作台数据统计', 'core:console:list')]
|
||||||
|
public function newPlayerList(): Response
|
||||||
|
{
|
||||||
|
$adminInfo = $this->adminInfo ?? null;
|
||||||
|
$query = DicePlayer::field('username,coin,total_ticket_count,create_time')
|
||||||
|
->order('create_time', 'desc')
|
||||||
|
->limit(50);
|
||||||
|
AdminScopeHelper::applyAdminScope($query, $adminInfo);
|
||||||
|
$list = $query->select();
|
||||||
|
$rows = [];
|
||||||
|
foreach ($list as $row) {
|
||||||
|
$rows[] = [
|
||||||
|
'name' => $row->getAttr('username'),
|
||||||
|
'coin' => $row->getAttr('coin'),
|
||||||
|
'total_ticket_count' => $row->getAttr('total_ticket_count'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $this->success($rows);
|
||||||
|
}
|
||||||
|
|
||||||
private function calcWeekChange($current, $last): float
|
private function calcWeekChange($current, $last): float
|
||||||
{
|
{
|
||||||
if ($last == 0) {
|
if ($last == 0) {
|
||||||
|
|||||||
@@ -69,10 +69,12 @@ class DiceRewardController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* 权重编辑弹窗:按档位分组获取配置+顺时针/逆时针权重(dice_reward 双方向)
|
* 权重编辑弹窗:按档位分组获取配置+顺时针/逆时针权重(dice_reward 双方向)
|
||||||
* 返回与 reward_config 权重配比一致结构,供奖励对照页弹窗同时编辑 direction=0/1
|
* 返回与 reward_config 权重配比一致结构,供奖励对照页弹窗同时编辑 direction=0/1
|
||||||
|
* 拉取前先刷新缓存,保证与列表页(直查 DB)数据一致,避免表格与弹窗权重不一致
|
||||||
*/
|
*/
|
||||||
#[Permission('奖励对照列表', 'dice:reward:index:index')]
|
#[Permission('奖励对照列表', 'dice:reward:index:index')]
|
||||||
public function weightRatioListWithDirection(Request $request): Response
|
public function weightRatioListWithDirection(Request $request): Response
|
||||||
{
|
{
|
||||||
|
DiceReward::refreshCache();
|
||||||
$logic = new DiceRewardLogic();
|
$logic = new DiceRewardLogic();
|
||||||
$data = $logic->getListGroupedByTierWithDirection();
|
$data = $logic->getListGroupedByTierWithDirection();
|
||||||
return $this->success($data);
|
return $this->success($data);
|
||||||
|
|||||||
@@ -195,12 +195,19 @@ class DiceRewardLogic
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$id = isset($item['id']) ? (int) $item['id'] : 0;
|
$id = isset($item['id']) ? (int) $item['id'] : 0;
|
||||||
$weight = isset($item['weight']) ? (int) $item['weight'] : self::WEIGHT_MIN;
|
if ($id <= 0) {
|
||||||
|
$id = isset($item['reward_id']) ? (int) $item['reward_id'] : 0;
|
||||||
|
}
|
||||||
if ($id <= 0) {
|
if ($id <= 0) {
|
||||||
throw new ApiException('存在无效的 DiceReward id');
|
throw new ApiException('存在无效的 DiceReward id');
|
||||||
}
|
}
|
||||||
|
$weight = isset($item['weight']) ? (int) $item['weight'] : self::WEIGHT_MIN;
|
||||||
$weight = max(self::WEIGHT_MIN, min(self::WEIGHT_MAX, $weight));
|
$weight = max(self::WEIGHT_MIN, min(self::WEIGHT_MAX, $weight));
|
||||||
DiceReward::where('id', $id)->update(['weight' => $weight]);
|
$model = DiceReward::find($id);
|
||||||
|
if ($model !== null) {
|
||||||
|
$model->weight = $weight;
|
||||||
|
$model->save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DiceReward::refreshCache();
|
DiceReward::refreshCache();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
|||||||
->where('grid_number', $gridNumber)
|
->where('grid_number', $gridNumber)
|
||||||
->update(['weight' => $weight]);
|
->update(['weight' => $weight]);
|
||||||
}
|
}
|
||||||
|
DiceRewardConfig::refreshCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
$tiers = ['T1', 'T2', 'T3', 'T4', 'T5'];
|
$tiers = ['T1', 'T2', 'T3', 'T4', 'T5'];
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ use app\api\logic\PlayStartLogic;
|
|||||||
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
|
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
|
||||||
use app\dice\model\play_record_test\DicePlayRecordTest;
|
use app\dice\model\play_record_test\DicePlayRecordTest;
|
||||||
use app\dice\model\reward_config_record\DiceRewardConfigRecord;
|
use app\dice\model\reward_config_record\DiceRewardConfigRecord;
|
||||||
|
use app\dice\model\reward\DiceReward;
|
||||||
|
use app\dice\model\reward_config\DiceRewardConfig;
|
||||||
use support\Log;
|
use support\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,6 +84,10 @@ class WeightTestRunner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 每次测试开始前清空进程内静态缓存,强制从共享缓存读取最新 BIGWIN/奖励配置,与数据库一致
|
||||||
|
DiceRewardConfig::clearRequestInstance();
|
||||||
|
DiceReward::clearRequestInstance();
|
||||||
|
|
||||||
$playLogic = new PlayStartLogic();
|
$playLogic = new PlayStartLogic();
|
||||||
$resultCounts = [];
|
$resultCounts = [];
|
||||||
$tierCounts = [];
|
$tierCounts = [];
|
||||||
|
|||||||
@@ -46,18 +46,19 @@ class DiceReward extends BaseModel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取奖励对照实例(按档位+方向索引,用于抽奖与权重配比)
|
* 获取奖励对照实例(按档位+方向索引,用于抽奖与权重配比)
|
||||||
|
* 优先从共享缓存读取,保证多进程(如一键测试 worker)与数据库一致
|
||||||
* @return array{list: array, by_tier_direction: array}
|
* @return array{list: array, by_tier_direction: array}
|
||||||
*/
|
*/
|
||||||
public static function getCachedInstance(): array
|
public static function getCachedInstance(): array
|
||||||
{
|
{
|
||||||
if (self::$instance !== null) {
|
|
||||||
return self::$instance;
|
|
||||||
}
|
|
||||||
$instance = Cache::get(self::CACHE_KEY_INSTANCE);
|
$instance = Cache::get(self::CACHE_KEY_INSTANCE);
|
||||||
if ($instance !== null && is_array($instance)) {
|
if ($instance !== null && is_array($instance)) {
|
||||||
self::$instance = $instance;
|
self::$instance = $instance;
|
||||||
return $instance;
|
return $instance;
|
||||||
}
|
}
|
||||||
|
if (self::$instance !== null) {
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
self::refreshCache();
|
self::refreshCache();
|
||||||
$instance = Cache::get(self::CACHE_KEY_INSTANCE);
|
$instance = Cache::get(self::CACHE_KEY_INSTANCE);
|
||||||
self::$instance = is_array($instance) ? $instance : self::buildEmptyInstance();
|
self::$instance = is_array($instance) ? $instance : self::buildEmptyInstance();
|
||||||
|
|||||||
@@ -42,18 +42,19 @@ class DiceRewardConfig extends BaseModel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取彩金池实例(含 list / by_tier / by_tier_grid),无则从库加载并写入缓存
|
* 获取彩金池实例(含 list / by_tier / by_tier_grid),无则从库加载并写入缓存
|
||||||
|
* 优先从共享缓存读取,保证多进程(如一键测试 worker)能拿到最新配置,与数据库一致
|
||||||
* @return array{list: array, by_tier: array, by_tier_grid: array, min_real_ev: float}
|
* @return array{list: array, by_tier: array, by_tier_grid: array, min_real_ev: float}
|
||||||
*/
|
*/
|
||||||
public static function getCachedInstance(): array
|
public static function getCachedInstance(): array
|
||||||
{
|
{
|
||||||
if (self::$instance !== null) {
|
|
||||||
return self::$instance;
|
|
||||||
}
|
|
||||||
$instance = Cache::get(self::CACHE_KEY_INSTANCE);
|
$instance = Cache::get(self::CACHE_KEY_INSTANCE);
|
||||||
if ($instance !== null && is_array($instance)) {
|
if ($instance !== null && is_array($instance)) {
|
||||||
self::$instance = $instance;
|
self::$instance = $instance;
|
||||||
return $instance;
|
return $instance;
|
||||||
}
|
}
|
||||||
|
if (self::$instance !== null) {
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
self::refreshCache();
|
self::refreshCache();
|
||||||
$instance = Cache::get(self::CACHE_KEY_INSTANCE);
|
$instance = Cache::get(self::CACHE_KEY_INSTANCE);
|
||||||
self::$instance = is_array($instance) ? $instance : self::buildEmptyInstance();
|
self::$instance = is_array($instance) ? $instance : self::buildEmptyInstance();
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ Route::group('/core', function () {
|
|||||||
Route::get('/dice/dashboard/statistics', [\app\dice\controller\DiceDashboardController::class, 'statistics']);
|
Route::get('/dice/dashboard/statistics', [\app\dice\controller\DiceDashboardController::class, 'statistics']);
|
||||||
Route::get('/dice/dashboard/rechargeChart', [\app\dice\controller\DiceDashboardController::class, 'rechargeChart']);
|
Route::get('/dice/dashboard/rechargeChart', [\app\dice\controller\DiceDashboardController::class, 'rechargeChart']);
|
||||||
Route::get('/dice/dashboard/rechargeBarChart', [\app\dice\controller\DiceDashboardController::class, 'rechargeBarChart']);
|
Route::get('/dice/dashboard/rechargeBarChart', [\app\dice\controller\DiceDashboardController::class, 'rechargeBarChart']);
|
||||||
|
Route::get('/dice/dashboard/walletRecordList', [\app\dice\controller\DiceDashboardController::class, 'walletRecordList']);
|
||||||
|
Route::get('/dice/dashboard/newPlayerList', [\app\dice\controller\DiceDashboardController::class, 'newPlayerList']);
|
||||||
Route::get('/system/clearAllCache', [plugin\saiadmin\app\controller\SystemController::class, 'clearAllCache']);
|
Route::get('/system/clearAllCache', [plugin\saiadmin\app\controller\SystemController::class, 'clearAllCache']);
|
||||||
|
|
||||||
Route::get("/system/getResourceCategory", [plugin\saiadmin\app\controller\SystemController::class, 'getResourceCategory']);
|
Route::get("/system/getResourceCategory", [plugin\saiadmin\app\controller\SystemController::class, 'getResourceCategory']);
|
||||||
|
|||||||
Reference in New Issue
Block a user