diff --git a/src/styles/global.less b/src/assets/styles/global.less
similarity index 97%
rename from src/styles/global.less
rename to src/assets/styles/global.less
index 30ef07a..b5dd72e 100644
--- a/src/styles/global.less
+++ b/src/assets/styles/global.less
@@ -45,6 +45,10 @@ html.theme-dark body {
margin: 0 1rem;
}
+.content-margin {
+ margin: 0 1rem;
+}
+
.t-input--password {
letter-spacing: 0;
}
diff --git a/src/styles/tdesign-custom.css b/src/assets/styles/tdesign-custom.css
similarity index 100%
rename from src/styles/tdesign-custom.css
rename to src/assets/styles/tdesign-custom.css
diff --git a/src/components/EventSelector.vue b/src/components/EventSelector.vue
index 5fbd0f1..3380a08 100644
--- a/src/components/EventSelector.vue
+++ b/src/components/EventSelector.vue
@@ -7,12 +7,12 @@
:key="item.id || item.name"
type="button"
class="item bg-white"
- :class="{selected: isSelected(item.id)}"
+ :class="{selected: isSelected(item)}"
:title="item.name"
- :disabled="props.disabled || !item.id"
- :aria-pressed="isSelected(item.id)"
+ :disabled="props.disabled || !normalizeEventId(item)"
+ :aria-pressed="isSelected(item)"
v-entrance-transition="index * 30"
- @click="toggleEvent(item.id)"
+ @click="toggleEvent(item)"
>
-
+
暂无可用登记事件
@@ -46,20 +46,29 @@ const props = withDefaults(defineProps(), {
const modelValue = defineModel({ required: true });
const defaultColor = "#2f88ff";
-const isSelected = (eventId?: string) => Boolean(eventId && modelValue.value.includes(eventId));
+function normalizeEventId(item: EventItem): string {
+ if (item.id === undefined || item.id === null) {
+ return "";
+ }
+ return String(item.id);
+}
-const toggleEvent = (eventId?: string) => {
+function isSelected(item: EventItem): boolean {
+ const eventId = normalizeEventId(item);
+ return Boolean(eventId && modelValue.value.includes(eventId));
+}
+
+function toggleEvent(item: EventItem): void {
+ const eventId = normalizeEventId(item);
if (props.disabled || !eventId) {
return;
}
-
- if (isSelected(eventId)) {
+ if (modelValue.value.includes(eventId)) {
modelValue.value = modelValue.value.filter(id => id !== eventId);
return;
}
-
modelValue.value = [...modelValue.value, eventId];
-};
+}
diff --git a/src/utils/eventValue.ts b/src/utils/eventValue.ts
index 7c8678a..eee6d43 100644
--- a/src/utils/eventValue.ts
+++ b/src/utils/eventValue.ts
@@ -19,9 +19,9 @@ export function getEventValueUnitText(valueUnit?: EventItem["valueUnit"]): strin
*/
export function getEventNumberValuePlaceholder(event: EventItem): string {
if (event.valueUnit === "CENT") {
- return event.requireValue ? "请输入金额(元),最多两位小数" : "请输入金额(元),可留空,最多两位小数";
+ return event.requireValue ? "金额(元),最多两位小数" : "金额(元),可留空,最多两位小数";
}
- return event.requireValue ? "请输入次数,必须是大于等于 0 的整数" : "请输入次数,可留空,必须是大于等于 0 的整数";
+ return event.requireValue ? "次数,必须是大于等于 0 的整数" : "次数,可留空,必须是大于等于 0 的整数";
}
/**
diff --git a/src/utils/point.ts b/src/utils/point.ts
index 4046f24..bfe06d2 100644
--- a/src/utils/point.ts
+++ b/src/utils/point.ts
@@ -35,37 +35,99 @@ export async function loadSourceValueConfig(eventIdList: string[]): Promise result.list || [])
- .filter(isSourceValueRule);
+ const ruleList = resultList.flatMap(result => result.list || []);
if (!ruleList.length) {
return undefined;
}
const rangeList = ruleList
- .map(rule => ({ min: rule.conditionJson?.min, max: rule.conditionJson?.max }))
- .filter((range): range is { min: number; max: number } => (
- range.min !== undefined
- && range.max !== undefined
- && Number.isSafeInteger(range.min)
- && Number.isSafeInteger(range.max)
- && range.min !== 0
- && range.max !== 0
- && (range.min < 0) === (range.max < 0)
- ));
- if (rangeList.length !== ruleList.length) {
+ .map(resolvePointValueRuleConfig)
+ .filter((range): range is SourceValueConfig => !!range);
+ const action = rangeList[0]?.action;
+ if (!action) {
return undefined;
}
-
- const action = rangeList[0].min < 0 ? "CONSUME" : "EARN";
- if (rangeList.some(range => (range.min < 0 ? "CONSUME" : "EARN") !== action)) {
+ if (rangeList.some(range => range.action !== action)) {
return undefined;
}
- const min = Math.max(...rangeList.map(range => action === "CONSUME" ? Math.abs(range.max) : range.min), 1);
- const max = Math.min(...rangeList.map(range => action === "CONSUME" ? Math.abs(range.min) : range.max));
+ const min = Math.max(...rangeList.map(range => range.range[0]), 1);
+ const max = Math.min(...rangeList.map(range => range.range[1]));
return min <= max ? { range: [min, max], action } : undefined;
}
-function isSourceValueRule(rule: PointRule): boolean {
- return rule.status === "ACTIVE" && rule.triggerType === "SOURCE_VALUE" && rule.pointMode === "SOURCE_VALUE";
+/**
+ * 解析积分规则动作。
+ *
+ * 固定积分优先按 pointValue 正负判定;登记时自定义积分按 conditionJson.min 正负判定。
+ *
+ * @param rule 积分规则
+ * @returns 积分动作;缺少有效积分值时返回 undefined
+ */
+export function resolvePointRuleAction(rule: PointRule): PointAction | undefined {
+ if (rule.pointValue !== undefined && rule.pointValue !== null && rule.pointValue !== 0) {
+ return rule.pointValue < 0 ? "CONSUME" : "EARN";
+ }
+ const min = rule.conditionJson?.min;
+ if (min === undefined || min === 0) {
+ return undefined;
+ }
+ return min < 0 ? "CONSUME" : "EARN";
+}
+
+function resolvePointValueRuleConfig(rule: PointRule): SourceValueConfig | undefined {
+ if (rule.status !== "ACTIVE") {
+ return undefined;
+ }
+ if (rule.pointMode === "FIXED") {
+ return resolveFixedPointValueRuleConfig(rule);
+ }
+ if (rule.triggerType === "SOURCE_VALUE" && rule.pointMode === "SOURCE_VALUE") {
+ return resolveSourceValueRuleConfig(rule);
+ }
+ return undefined;
+}
+
+function resolveFixedPointValueRuleConfig(rule: PointRule): SourceValueConfig | undefined {
+ const action = resolvePointRuleAction(rule);
+ const pointValue = rule.pointValue;
+ if (
+ action === undefined
+ || pointValue === undefined
+ || pointValue === null
+ || !Number.isSafeInteger(pointValue)
+ || pointValue === 0
+ ) {
+ return undefined;
+ }
+
+ const value = Math.abs(pointValue);
+ return {
+ action,
+ range: [value, value]
+ };
+}
+
+function resolveSourceValueRuleConfig(rule: PointRule): SourceValueConfig | undefined {
+ const min = rule.conditionJson?.min;
+ const max = rule.conditionJson?.max;
+ const action = resolvePointRuleAction(rule);
+ if (
+ min === undefined
+ || max === undefined
+ || action === undefined
+ || !Number.isSafeInteger(min)
+ || !Number.isSafeInteger(max)
+ || min === 0
+ || max === 0
+ || (action === "CONSUME") !== (min < 0)
+ || (action === "CONSUME") !== (max < 0)
+ ) {
+ return undefined;
+ }
+
+ const boundaryList = [Math.abs(min), Math.abs(max)];
+ return {
+ action,
+ range: [Math.min(...boundaryList), Math.max(...boundaryList)]
+ };
}