fix point rule unit

This commit is contained in:
Timi
2026-08-19 15:46:03 +08:00
parent ff156926f5
commit 84bc6d137d
5 changed files with 150 additions and 103 deletions
@@ -1,8 +1,8 @@
<template>
<div class="tier-editor">
<div class="title">
<div>累计数值分档</div>
<div class="tips gray">首档从 0 开始,末档不设上限;积分为 0 不产生流水</div>
<div v-text="`累计数值分档(${valueUnitText})`" />
<div class="tips gray" v-text="`首档从 0 开始,末档不设上限;分档单位为${valueUnitText},积分为 0 不产生流水`" />
</div>
<div class="list">
<div
@@ -15,7 +15,11 @@
<span class="index" v-text="`第 ${index + 1} 档`" />
<strong v-text="getTierRangeText(index)" />
</div>
<div class="points text-bold" v-text="getTierPointText(tier)" />
<div
class="point text-bold"
:class="{ 'consume': tier.pointAction === 'CONSUME' }"
v-text="getTierPointText(tier)"
/>
<t-button
v-if="1 < tiers.length"
theme="danger"
@@ -38,20 +42,28 @@
>
<div class="tier-editor-popup">
<t-form v-if="tierEditorIndex >= 0" class="form" label-align="left" label-width="10rem">
<t-form-item label="最小值" content-align="right">
<span class="gray" v-text="getTierMinText(tiers, tierEditorIndex)" />
<t-form-item :label="`最小值(${valueUnitText})`" content-align="right">
<span class="gray" v-text="getTierMinText(tiers, tierEditorIndex, valueUnit)" />
</t-form-item>
<t-form-item v-if="!isLastTier(tiers, tierEditorIndex) || tierEditorAdding" :label="tierEditorAdding ? '当前档最大值' : '最大值'" required-mark>
<t-form-item
v-if="!isLastTier(tiers, tierEditorIndex) || tierEditorAdding"
:label="`${tierEditorAdding ? '当前档最大值' : '最大值'}(${valueUnitText})`"
required-mark
>
<t-input
v-model.trim="tierEditorDraft.maxText"
type="number"
:step="valueUnit === 'CENT' ? '0.01' : '1'"
align="right"
borderless
placeholder="请输入最大值"
:placeholder="valueUnit === 'CENT' ? '最多两位小数' : '请输入整数'"
/>
</t-form-item>
<t-form-item label="积分动作" arrow @click="openActionPicker">
<span class="picker-text" v-text="getPointActionText(tierEditorDraft.pointAction)" />
<t-form-item label="积分动作" content-align="right">
<t-radio-group v-model="tierEditorDraft.pointAction" variant="default-filled">
<t-radio :block="false" borderless value="EARN">发放</t-radio>
<t-radio :block="false" borderless value="CONSUME">消耗</t-radio>
</t-radio-group>
</t-form-item>
<t-form-item label="积分数量" required-mark>
<t-input
@@ -66,26 +78,21 @@
</t-form>
</div>
</bottom-popup>
<t-popup v-model="actionPickerVisible" placement="bottom">
<t-picker
v-model="actionPickerDraft"
:columns="actionPickerColumns"
title="积分动作"
@cancel="actionPickerVisible = false"
@confirm="confirmActionPicker"
/>
</t-popup>
</template>
<script setup lang="ts">
import type { EventValueUnit } from "@/types/EventItem";
import type { PointAction, PointRuleTierForm } from "@/types/Point";
import { getTierMinText, getTierMinValue, isLastTier, resolveNonNegativeInteger } from "@/utils/pointRule";
import { formatTierBoundaryValue, getTierMinText, getTierMinValue, isLastTier, resolveNonNegativeInteger, resolveTierBoundaryValue } from "@/utils/pointRule";
import { Toast } from "tdesign-mobile-vue";
defineOptions({
name: "PointRuleTierEditor"
});
const props = defineProps<{
valueUnit?: EventValueUnit | null;
}>();
const tiers = defineModel<PointRuleTierForm[]>({ required: true });
const tierEditorVisible = ref(false);
const tierEditorIndex = ref(-1);
@@ -95,31 +102,26 @@ const tierEditorDraft = reactive({
pointAction: "EARN" as PointAction,
pointValueText: ""
});
const actionOptions: Array<{ label: string; value: PointAction }> = [
{ label: "发放积分", value: "EARN" },
{ label: "消耗积分", value: "CONSUME" }
];
const actionPickerVisible = ref(false);
const actionPickerDraft = ref<Array<string | number>>([]);
const actionPickerColumns = [actionOptions];
const tierEditorTitle = computed(() => {
if (tierEditorIndex.value < 0) {
return "编辑分档";
}
return tierEditorAdding.value ? `编辑第 ${tierEditorIndex.value + 1} 档并新增下一档` : `编辑第 ${tierEditorIndex.value + 1} 档`;
});
const valueUnit = computed(() => props.valueUnit);
const valueUnitText = computed(() => valueUnit.value === "CENT" ? "元" : valueUnit.value === "COUNT" ? "次" : "数值");
function getTierRangeText(index: number): string {
const tier = tiers.value[index];
if (!tier) {
return "待填写";
}
const minText = getTierMinText(tiers.value, index);
const minText = getTierMinText(tiers.value, index, valueUnit.value);
if (isLastTier(tiers.value, index)) {
return `${minText} 及以上`;
}
const max = resolveNonNegativeInteger(tier.maxText);
return max === undefined ? `${minText} - 待填写` : `${minText}-${max}`;
const max = resolveTierBoundaryValue(tier.maxText, valueUnit.value);
return max === undefined ? `${minText} - 待填写` : `${minText}-${formatTierBoundaryValue(max, valueUnit.value)}`;
}
function getTierPointText(tier: PointRuleTierForm): string {
@@ -127,7 +129,7 @@ function getTierPointText(tier: PointRuleTierForm): string {
if (pointValue === undefined) {
return "待填写";
}
return `${tier.pointAction === "CONSUME" ? "消耗" : "发放"} ${pointValue} 分`;
return `${tier.pointAction === "CONSUME" ? "-" : "+"}${pointValue} 分`;
}
function openTierEditor(index: number, adding = false): void {
@@ -138,7 +140,7 @@ function openTierEditor(index: number, adding = false): void {
tierEditorIndex.value = index;
tierEditorAdding.value = adding;
tierEditorDraft.maxText = adding ? "" : tier.maxText;
tierEditorDraft.pointAction = tier.pointAction;
tierEditorDraft.pointAction = tier.pointAction === "CONSUME" ? "CONSUME" : "EARN";
tierEditorDraft.pointValueText = tier.pointValueText;
tierEditorVisible.value = true;
}
@@ -154,7 +156,7 @@ function confirmTierEditor(): void {
if (!tier) {
return;
}
const min = getTierMinValue(tiers.value, index);
const min = getTierMinValue(tiers.value, index, valueUnit.value);
const pointValue = resolveNonNegativeInteger(tierEditorDraft.pointValueText);
if (min === undefined) {
Toast.warning("请先修正上一档的最大值");
@@ -166,12 +168,12 @@ function confirmTierEditor(): void {
}
const shouldAddTier = tierEditorAdding.value && isLastTier(tiers.value, index);
if (!isLastTier(tiers.value, index) || shouldAddTier) {
const max = resolveNonNegativeInteger(tierEditorDraft.maxText);
const max = resolveTierBoundaryValue(tierEditorDraft.maxText, valueUnit.value);
if (max === undefined || max < min) {
Toast.warning("当前档最大值必须是不小于最小值的整数");
Toast.warning(valueUnit.value === "CENT" ? "当前档最大值必须是不小于最小值且最多两位小数" : "当前档最大值必须是不小于最小值的整数");
return;
}
tier.maxText = String(max);
tier.maxText = formatTierBoundaryValue(max, valueUnit.value);
} else {
tier.maxText = "";
}
@@ -203,23 +205,6 @@ function removeTier(index: number): void {
tiers.value.splice(index, 1);
}
function openActionPicker(): void {
actionPickerDraft.value = [tierEditorDraft.pointAction];
actionPickerVisible.value = true;
}
function confirmActionPicker(value: Array<string | number>): void {
const action = value[0];
if (action === "EARN" || action === "CONSUME") {
tierEditorDraft.pointAction = action;
}
actionPickerVisible.value = false;
}
function getPointActionText(action: PointAction): string {
return action === "CONSUME" ? "消耗积分" : "发放积分";
}
function createTierForm(): PointRuleTierForm {
const key = tiers.value.reduce((max, tier) => Math.max(max, tier.key), -1) + 1;
return {
@@ -271,13 +256,17 @@ function createTierForm(): PointRuleTierForm {
}
}
.points {
.point {
gap: .25rem;
color: var(--td-brand-color);
display: flex;
font-size: 1.5rem;
align-items: baseline;
white-space: nowrap;
&.consume {
color: var(--td-error-color);
}
}
}
@@ -297,6 +286,7 @@ function createTierForm(): PointRuleTierForm {
padding: 0 1rem;
font-size: .75rem;
line-height: 1.5;
margin-top: .5rem;
}
}
}