1.优化奖励配置设置-创建奖励对照表单样式

This commit is contained in:
2026-06-02 15:24:17 +08:00
parent 79c84c198a
commit 13dacc8fdd
4 changed files with 144 additions and 31 deletions

View File

@@ -60,6 +60,7 @@
"createRefPreviewImportNoop": "Mapping unchanged, nothing to import (existing weights kept)",
"createRefPreviewDiff": "Diff (old → new)",
"createRefPreviewNoDiff": "No change",
"createRefPreviewWeightsSaved": "Weights saved",
"createRefSuccess": "Created for 26 dice points (530), clockwise + counter-clockwise: clockwise added {cwNew}, counter-clockwise added {ccwNew}; clockwise updated {cwUp}, counter-clockwise updated {ccwUp}{skippedPart}",
"createRefSuccessSkipped": "; {n} point(s) used fallback start index",
"createRefSuccessSimple": "Created successfully",

View File

@@ -60,6 +60,7 @@
"createRefPreviewImportNoop": "色子点数映射未变化,无需导入(已保留现有权重)",
"createRefPreviewDiff": "差异(旧 → 新)",
"createRefPreviewNoDiff": "无变化",
"createRefPreviewWeightsSaved": "已保存权重",
"createRefSuccess": "已按 5-30 共 26 个点数、顺时针+逆时针创建:顺时针新增 {cwNew} 条、逆时针新增 {ccwNew} 条;顺时针更新 {cwUp} 条、逆时针更新 {ccwUp} 条{skippedPart}",
"createRefSuccessSkipped": "{n} 个点数使用兜底起始索引",
"createRefSuccessSimple": "创建成功",

View File

@@ -2,7 +2,7 @@
<ElDialog
v-model="visible"
:title="$t('page.configPage.createRefPreviewTitle')"
width="980px"
width="860px"
align-center
:close-on-click-modal="false"
@close="handleClose"
@@ -31,15 +31,26 @@
size="small"
class="preview-table"
>
<ElTableColumn :label="$t('page.table.dicePoints')" prop="grid_number" width="120" align="center" />
<ElTableColumn label="start_index" prop="start_index" width="110" align="center" />
<ElTableColumn :label="$t('page.table.endIndex')" prop="id" width="110" align="center" />
<ElTableColumn :label="$t('page.table.tier')" prop="tier" width="90" align="center" />
<ElTableColumn :label="$t('page.table.displayText')" prop="ui_text" min-width="110" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.realEv')" prop="real_ev" width="110" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.remark')" prop="remark" min-width="140" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.weight')" prop="weight" width="110" align="center" />
<ElTableColumn :label="$t('page.configPage.createRefPreviewDiff')" min-width="220" align="center">
<ElTableColumn :label="$t('page.table.dicePoints')" prop="grid_number" width="90" align="center" />
<ElTableColumn label="start" prop="start_index" width="78" align="center" />
<ElTableColumn :label="$t('page.table.endIndex')" prop="id" width="78" align="center" />
<ElTableColumn :label="$t('page.table.displayText')" prop="ui_text" width="90" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.realEv')" prop="real_ev" width="90" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.remark')" prop="remark" min-width="80" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.weight')" width="130" align="center">
<template #default="{ row }">
<ElInputNumber
v-model="row.weight"
:min="1"
:max="10000"
:step="1"
controls-position="right"
size="small"
class="weight-input"
/>
</template>
</ElTableColumn>
<ElTableColumn :label="$t('page.configPage.createRefPreviewDiff')" min-width="120" align="center">
<template #default="{ row }">
<span v-if="row?.diff_changed" class="diff-text">
{{ formatDiff(row) }}
@@ -62,15 +73,26 @@
size="small"
class="preview-table"
>
<ElTableColumn :label="$t('page.table.dicePoints')" prop="grid_number" width="120" align="center" />
<ElTableColumn label="start_index" prop="start_index" width="110" align="center" />
<ElTableColumn :label="$t('page.table.endIndex')" prop="id" width="110" align="center" />
<ElTableColumn :label="$t('page.table.tier')" prop="tier" width="90" align="center" />
<ElTableColumn :label="$t('page.table.displayText')" prop="ui_text" min-width="110" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.realEv')" prop="real_ev" width="110" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.remark')" prop="remark" min-width="140" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.weight')" prop="weight" width="110" align="center" />
<ElTableColumn :label="$t('page.configPage.createRefPreviewDiff')" min-width="220" align="center">
<ElTableColumn :label="$t('page.table.dicePoints')" prop="grid_number" width="90" align="center" />
<ElTableColumn label="start" prop="start_index" width="78" align="center" />
<ElTableColumn :label="$t('page.table.endIndex')" prop="id" width="78" align="center" />
<ElTableColumn :label="$t('page.table.displayText')" prop="ui_text" width="90" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.realEv')" prop="real_ev" width="90" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.remark')" prop="remark" min-width="80" align="center" show-overflow-tooltip />
<ElTableColumn :label="$t('page.table.weight')" width="120" align="center">
<template #default="{ row }">
<ElInputNumber
v-model="row.weight"
:min="1"
:max="10000"
:step="1"
controls-position="right"
size="small"
class="weight-input"
/>
</template>
</ElTableColumn>
<ElTableColumn :label="$t('page.configPage.createRefPreviewDiff')" min-width="120" align="center">
<template #default="{ row }">
<span v-if="row?.diff_changed" class="diff-text">
{{ formatDiff(row) }}
@@ -175,15 +197,74 @@
}
}
function toWeight(v: unknown): number {
const num = typeof v === 'number' && !Number.isNaN(v) ? v : Number(v)
if (Number.isNaN(num)) return 1
return Math.max(1, Math.min(10000, Math.floor(num)))
}
function collectDesiredWeights(): Record<string, number> {
const map: Record<string, number> = {}
for (const t of tierKeys) {
const tierData = preview.value?.[t]
if (!tierData) continue
const cw = Array.isArray(tierData[0]) ? tierData[0] : []
const ccw = Array.isArray(tierData[1]) ? tierData[1] : []
for (const r of cw) {
const gn = r?.grid_number != null ? Number(r.grid_number) : NaN
if (!Number.isNaN(gn)) map[`0:${gn}`] = toWeight(r?.weight)
}
for (const r of ccw) {
const gn = r?.grid_number != null ? Number(r.grid_number) : NaN
if (!Number.isNaN(gn)) map[`1:${gn}`] = toWeight(r?.weight)
}
}
return map
}
async function applyWeights(desired: Record<string, number>) {
const res: any = await api.weightRatioList({ dept_id: props.deptId })
const raw = res?.data ?? res
const items: Array<{ id: number; weight: number }> = []
for (const t of tierKeys) {
const tierData = raw?.[t]
if (!tierData) continue
const list0 = Array.isArray(tierData[0]) ? tierData[0] : []
const list1 = Array.isArray(tierData[1]) ? tierData[1] : []
for (const r of list0) {
const rid = r?.reward_id != null ? Number(r.reward_id) : 0
const gn = r?.grid_number != null ? Number(r.grid_number) : NaN
if (rid > 0 && !Number.isNaN(gn)) {
const w = desired[`0:${gn}`]
if (w != null) items.push({ id: rid, weight: w })
}
}
for (const r of list1) {
const rid = r?.reward_id != null ? Number(r.reward_id) : 0
const gn = r?.grid_number != null ? Number(r.grid_number) : NaN
if (rid > 0 && !Number.isNaN(gn)) {
const w = desired[`1:${gn}`]
if (w != null) items.push({ id: rid, weight: w })
}
}
}
if (items.length > 0) {
await api.batchUpdateWeights(items, { dept_id: props.deptId })
}
}
async function handleImport() {
submitting.value = true
try {
const res: any = await api.createRewardReference({ dept_id: props.deptId })
const data = res?.data ?? res
if (data?.unchanged) {
ElMessage.success(t('page.configPage.createRefPreviewImportNoop'))
} else {
const desired = collectDesiredWeights()
if (!meta.unchanged) {
await api.createRewardReference({ dept_id: props.deptId })
await applyWeights(desired)
ElMessage.success(t('page.configPage.createRefPreviewImportOk'))
} else {
// 映射未变化:直接保存权重即可
await applyWeights(desired)
ElMessage.success(t('page.configPage.createRefPreviewWeightsSaved'))
}
emit('success')
handleClose()
@@ -210,12 +291,12 @@
<style scoped lang="scss">
.dialog-body {
min-height: 240px;
min-height: 120px;
}
.preview-tip {
margin-bottom: 12px;
padding: 10px 12px;
font-size: 13px;
margin-bottom: 8px;
padding: 8px 10px;
font-size: 12px;
color: var(--el-text-color-regular);
background: var(--el-fill-color-light);
border-radius: 6px;
@@ -225,7 +306,10 @@
margin-top: 4px;
}
.preview-table {
margin-top: 8px;
margin-top: 4px;
}
.weight-input {
width: 110px;
}
:deep(.row-diff td) {
background: var(--el-color-warning-light-9);
@@ -239,5 +323,23 @@
.diff-text-ok {
color: var(--el-text-color-secondary);
}
/* 减少弹窗内容区与表格留白 */
:deep(.el-dialog__body) {
padding: 12px 14px;
}
:deep(.el-tabs__header) {
margin: 0 0 8px 0;
}
:deep(.el-tabs__item) {
height: 34px;
line-height: 34px;
}
:deep(.el-table .cell) {
padding: 4px 6px;
}
:deep(.el-table__row) {
height: 34px;
}
</style>

View File

@@ -344,10 +344,14 @@ class DiceRewardLogic
$compare = $this->compareReferenceRows($computed['rows'], $existing);
$unchanged = $compare['unchanged'];
$specialGrids = [5, 10, 15, 20, 25, 30];
$previewRows = [];
foreach ($computed['rows'] as $row) {
$key = $row['direction'] . ':' . $row['grid_number'];
$weight = self::WEIGHT_MIN;
$gridNumber = isset($row['grid_number']) ? (int) $row['grid_number'] : 0;
$weight = $unchanged
? self::WEIGHT_MIN
: (in_array($gridNumber, $specialGrids, true) ? self::WEIGHT_MIN : 100);
$oldStart = null;
$oldEnd = null;
$oldTier = null;
@@ -358,8 +362,13 @@ class DiceRewardLogic
$oldTier = isset($existing[$key]['tier']) ? (string) $existing[$key]['tier'] : null;
$oldWeight = isset($existing[$key]['weight']) ? (int) $existing[$key]['weight'] : null;
}
// 映射未变化时:通常复用旧权重;但若旧权重为 1 且非特殊点数,则按新默认建议展示为 100方便管理员快速落配置
if ($unchanged && $oldWeight !== null) {
$weight = max(self::WEIGHT_MIN, min(self::WEIGHT_MAX, (int) $oldWeight));
$oldWeight = (int) $oldWeight;
$weight = max(self::WEIGHT_MIN, min(self::WEIGHT_MAX, $oldWeight));
if ($weight === self::WEIGHT_MIN && !in_array($gridNumber, $specialGrids, true)) {
$weight = 100;
}
}
$diffChanged = false;