add PointLedgerDetail.vue
This commit is contained in:
@@ -0,0 +1,394 @@
|
|||||||
|
<template>
|
||||||
|
<div v-can="permissionCodes.point.ledgerRead" class="point-ledger-detail">
|
||||||
|
<customer-profile-card
|
||||||
|
v-if="customer"
|
||||||
|
class="customer-profile"
|
||||||
|
:customer="customer"
|
||||||
|
@click="toCustomerDetail"
|
||||||
|
/>
|
||||||
|
<template v-if="ledger">
|
||||||
|
<t-cell-group title="积分流水" theme="card">
|
||||||
|
<t-cell title="流水类型">
|
||||||
|
<template #note>
|
||||||
|
<t-tag
|
||||||
|
:theme="getDeltaTheme(ledger.pointDelta)"
|
||||||
|
:content="getChangeTypeText(ledger.changeType)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</t-cell>
|
||||||
|
<t-cell title="积分变化" :note="getPointDeltaText(ledger.pointDelta)" />
|
||||||
|
<t-cell title="变化前余额" :note="getPointText(ledger.balanceBefore)" />
|
||||||
|
<t-cell title="变化后余额" :note="getPointText(ledger.balanceAfter)" />
|
||||||
|
<t-cell title="发生时间">
|
||||||
|
<template #note>
|
||||||
|
<pass-time-label :timestamp="ledger.occurredAt" underline />
|
||||||
|
</template>
|
||||||
|
</t-cell>
|
||||||
|
<t-cell title="流水备注" :note="Text.display(ledger.remark)" />
|
||||||
|
</t-cell-group>
|
||||||
|
|
||||||
|
<t-cell-group title="触发事件" theme="card">
|
||||||
|
<template v-if="triggerEvent">
|
||||||
|
<t-cell title="事件名称" :note="triggerEvent.name || '未命名事件'" />
|
||||||
|
<t-cell title="事件类型" :note="getEventValueTypeText(triggerEvent)" />
|
||||||
|
<t-cell title="事件说明" :note="Text.display(triggerEvent.description)" />
|
||||||
|
</template>
|
||||||
|
<div v-else class="empty" v-text="getEventEmptyText()" />
|
||||||
|
</t-cell-group>
|
||||||
|
|
||||||
|
<t-cell-group title="事件记录" theme="card">
|
||||||
|
<template v-if="eventRecord">
|
||||||
|
<t-cell title="登记事件" :note="eventRecord.event?.name || triggerEvent?.name || '未知事件'" />
|
||||||
|
<t-cell title="登记时间">
|
||||||
|
<template #note>
|
||||||
|
<pass-time-label :timestamp="eventRecord.registeredAt" underline />
|
||||||
|
</template>
|
||||||
|
</t-cell>
|
||||||
|
<t-cell v-if="hasEventNumberValue" title="事件数值" :note="getEventNumberValueText()" />
|
||||||
|
<t-cell v-if="hasSubmittedPointValue" title="提交积分值" :note="getPointText(eventRecord.pointValue)" />
|
||||||
|
<t-cell v-if="hasEarnedPointValue" title="记录获得积分" :note="getPointText(eventRecord.earnedPointValue)" />
|
||||||
|
<t-cell title="登记人" :note="Text.display(eventRecord.operator?.nick || eventRecord.operator?.name)" />
|
||||||
|
<t-cell title="记录备注" :note="Text.display(eventRecord.remark)" />
|
||||||
|
</template>
|
||||||
|
<div v-else class="empty" v-text="getRecordEmptyText()" />
|
||||||
|
</t-cell-group>
|
||||||
|
|
||||||
|
<t-cell-group title="命中规则" theme="card">
|
||||||
|
<template v-if="hitRule">
|
||||||
|
<t-cell title="规则名称" :note="hitRule.name || '未命名规则'" />
|
||||||
|
<t-cell title="触发类型" :note="getTriggerTypeText(hitRule.triggerType)" />
|
||||||
|
<t-cell title="积分模式" :note="getPointModeText(hitRule.pointMode)" />
|
||||||
|
<t-cell title="规则积分" :note="getRulePointText(hitRule)" />
|
||||||
|
<t-cell title="匹配条件" :note="getRuleConditionText(hitRule)" />
|
||||||
|
<t-cell title="规则状态" :note="getRuleStatusText(hitRule.status)" />
|
||||||
|
<t-cell title="规则优先级" :note="getPointText(hitRule.priority)" />
|
||||||
|
<t-cell title="命中后停止匹配" :note="hitRule.exclusive ? '是' : '否'" />
|
||||||
|
<t-cell title="规则备注" :note="Text.display(hitRule.remark)" />
|
||||||
|
</template>
|
||||||
|
<div v-else class="empty" v-text="getRuleEmptyText()" />
|
||||||
|
</t-cell-group>
|
||||||
|
</template>
|
||||||
|
<t-empty v-else :description="isLoading ? '正在加载积分流水' : '积分流水快照不存在,请从积分流水列表进入'" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { PassTimeLabel, Text, useUserStore } from "timi-web";
|
||||||
|
import CustomerAPI from "@/api/CustomerAPI";
|
||||||
|
import EventAPI from "@/api/EventAPI";
|
||||||
|
import EventRecordAPI from "@/api/EventRecordAPI";
|
||||||
|
import PointAPI from "@/api/PointAPI";
|
||||||
|
import CustomerProfileCard from "@/components/CustomerProfileCard.vue";
|
||||||
|
import type { Customer } from "@/types/Customer";
|
||||||
|
import type { EventItem } from "@/types/EventItem";
|
||||||
|
import type { EventRecord } from "@/types/EventRecord";
|
||||||
|
import type { PointLedger, PointRule, PointRuleMode, PointRuleStatus, PointRuleTriggerType } from "@/types/Point";
|
||||||
|
import { formatEventNumberValue, getEventValueUnitText } from "@/utils/eventValue";
|
||||||
|
import { permissionCodes } from "@/utils/permission";
|
||||||
|
|
||||||
|
type SourcePayloadItem = {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "PointLedgerDetail"
|
||||||
|
});
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
// ---------- 权限 ----------
|
||||||
|
|
||||||
|
const canReadCustomer = computed(() => userStore.hasPermissions(permissionCodes.customer.read));
|
||||||
|
const canReadEvent = computed(() => userStore.hasPermissions(permissionCodes.event.read));
|
||||||
|
const canReadEventRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.read));
|
||||||
|
const canReadRule = computed(() => userStore.hasPermissions(permissionCodes.pointRule.read));
|
||||||
|
|
||||||
|
// ---------- 流水与关联数据 ----------
|
||||||
|
|
||||||
|
const ledger = ref<PointLedger>();
|
||||||
|
const customer = ref<Customer>();
|
||||||
|
const triggerEvent = ref<EventItem>();
|
||||||
|
const sourceEvent = ref<EventItem>();
|
||||||
|
const eventRecord = ref<EventRecord>();
|
||||||
|
const hitRule = ref<PointRule>();
|
||||||
|
const isLoading = ref(false);
|
||||||
|
|
||||||
|
const hasEventNumberValue = computed(() => eventRecord.value?.numberValue !== undefined && eventRecord.value?.numberValue !== null);
|
||||||
|
const hasSubmittedPointValue = computed(() => eventRecord.value?.pointValue !== undefined && eventRecord.value?.pointValue !== null);
|
||||||
|
const hasEarnedPointValue = computed(() => eventRecord.value?.earnedPointValue !== undefined && eventRecord.value?.earnedPointValue !== null);
|
||||||
|
const sourcePayloadList = computed<SourcePayloadItem[]>(() => {
|
||||||
|
const payload = ledger.value?.sourcePayload;
|
||||||
|
if (!payload) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return Object.entries(payload).map(([key, value]) => ({
|
||||||
|
key,
|
||||||
|
value: formatSourceValue(value)
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
function getQueryText(key: string): string {
|
||||||
|
const value = route.query[key];
|
||||||
|
return Array.isArray(value) ? String(value[0] || "") : String(value || "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseLedgerSnapshot(): PointLedger | undefined {
|
||||||
|
const snapshotText = getQueryText("snapshot");
|
||||||
|
if (!snapshotText) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const snapshot = JSON.parse(snapshotText) as PointLedger;
|
||||||
|
if (!snapshot || typeof snapshot !== "object") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...snapshot,
|
||||||
|
id: String(route.params.id || snapshot.id || "")
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("积分流水快照解析失败", error);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadOptional<T>(loader: () => Promise<T>, message: string): Promise<T | undefined> {
|
||||||
|
try {
|
||||||
|
return await loader();
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(message, error);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadPageData(): Promise<void> {
|
||||||
|
ledger.value = parseLedgerSnapshot();
|
||||||
|
customer.value = undefined;
|
||||||
|
triggerEvent.value = undefined;
|
||||||
|
sourceEvent.value = undefined;
|
||||||
|
eventRecord.value = undefined;
|
||||||
|
hitRule.value = undefined;
|
||||||
|
if (!ledger.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading.value = true;
|
||||||
|
try {
|
||||||
|
if (ledger.value.eventRecordId && canReadEventRecord.value) {
|
||||||
|
eventRecord.value = await loadOptional(() => EventRecordAPI.detail(ledger.value!.eventRecordId!), "积分流水关联事件记录加载失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventId = eventRecord.value?.eventId || ledger.value.eventId;
|
||||||
|
const eventResult = eventRecord.value?.event
|
||||||
|
? Promise.resolve(eventRecord.value.event)
|
||||||
|
: eventId && canReadEvent.value
|
||||||
|
? loadOptional(() => EventAPI.detail(eventId), "积分流水触发事件加载失败")
|
||||||
|
: Promise.resolve(undefined);
|
||||||
|
const ruleResult = ledger.value.ruleId && canReadRule.value
|
||||||
|
? loadOptional(() => PointAPI.ruleDetail(ledger.value!.ruleId!), "积分流水命中规则加载失败")
|
||||||
|
: Promise.resolve(undefined);
|
||||||
|
const customerResult = !eventRecord.value?.customer && ledger.value.customerId && canReadCustomer.value
|
||||||
|
? loadOptional(() => CustomerAPI.detail(ledger.value!.customerId!), "积分流水客户加载失败")
|
||||||
|
: Promise.resolve(undefined);
|
||||||
|
|
||||||
|
[triggerEvent.value, hitRule.value, customer.value] = await Promise.all([eventResult, ruleResult, customerResult]);
|
||||||
|
if (eventRecord.value?.customer) {
|
||||||
|
customer.value = eventRecord.value.customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceEventId = hitRule.value?.conditionJson?.sourceEventId;
|
||||||
|
if (sourceEventId && sourceEventId !== eventId && canReadEvent.value) {
|
||||||
|
sourceEvent.value = await loadOptional(() => EventAPI.detail(sourceEventId), "积分规则来源事件加载失败");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- 展示 ----------
|
||||||
|
|
||||||
|
function getChangeTypeText(changeType?: PointLedger["changeType"]): string {
|
||||||
|
return ({
|
||||||
|
EARN: "获得积分",
|
||||||
|
REVOKE: "撤销积分",
|
||||||
|
ADJUST: "人工调整"
|
||||||
|
} as Record<string, string>)[changeType || ""] || "未知流水";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDeltaTheme(pointDelta?: number): "success" | "danger" {
|
||||||
|
return pointDelta !== undefined && 0 < pointDelta ? "success" : "danger";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPointDeltaText(pointDelta?: number): string {
|
||||||
|
if (pointDelta === undefined || pointDelta === null) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
return `${0 < pointDelta ? "+" : ""}${pointDelta} 分`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPointText(value?: number | null): string {
|
||||||
|
return value === undefined || value === null ? "-" : `${value} 分`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEventValueTypeText(event: EventItem): string {
|
||||||
|
if (event.valueType === "NUMBER") {
|
||||||
|
return `数值事件(${getEventValueUnitText(event.valueUnit)})`;
|
||||||
|
}
|
||||||
|
return "普通事件";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEventNumberValueText(): string {
|
||||||
|
return formatEventNumberValue(eventRecord.value?.event || triggerEvent.value, eventRecord.value?.numberValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTriggerTypeText(triggerType?: PointRuleTriggerType): string {
|
||||||
|
return ({
|
||||||
|
EVERY_TIME: "每次登记",
|
||||||
|
FIRST_TIME: "首次登记",
|
||||||
|
AFTER_COUNT_EVERY_TIME: "达到阈值后每次登记",
|
||||||
|
SOURCE_VALUE: "登记时自定义积分",
|
||||||
|
CUSTOMER_EVENT_VALUE_TIER: "按来源事件累计分档"
|
||||||
|
} as Record<string, string>)[triggerType || ""] || "未知触发类型";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPointModeText(pointMode?: PointRuleMode): string {
|
||||||
|
return ({
|
||||||
|
FIXED: "固定积分",
|
||||||
|
SOURCE_VALUE: "使用登记时填写的积分",
|
||||||
|
TIER: "分档积分"
|
||||||
|
} as Record<string, string>)[pointMode || ""] || "未知积分模式";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRulePointText(rule: PointRule): string {
|
||||||
|
if (rule.pointMode === "TIER") {
|
||||||
|
return rule.conditionJson?.tiers?.length ? `${rule.conditionJson.tiers.length} 档` : "分档积分";
|
||||||
|
}
|
||||||
|
return getPointText(rule.pointValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRuleConditionText(rule: PointRule): string {
|
||||||
|
const condition = rule.conditionJson;
|
||||||
|
if (!condition) {
|
||||||
|
return "无额外条件";
|
||||||
|
}
|
||||||
|
|
||||||
|
const textList: string[] = [];
|
||||||
|
if (condition.min !== undefined || condition.max !== undefined) {
|
||||||
|
textList.push(`数值范围 ${condition.min ?? "不限"}~${condition.max ?? "不限"}`);
|
||||||
|
}
|
||||||
|
if (condition.threshold !== undefined) {
|
||||||
|
textList.push(`累计达到 ${condition.threshold} 次`);
|
||||||
|
}
|
||||||
|
if (condition.includeCurrent !== undefined) {
|
||||||
|
textList.push(condition.includeCurrent ? "包含本次登记" : "不含本次登记");
|
||||||
|
}
|
||||||
|
if (condition.window) {
|
||||||
|
textList.push(`累计窗口 ${condition.window.amount} ${condition.window.unit === "YEAR" ? "年" : condition.window.unit}`);
|
||||||
|
}
|
||||||
|
if (condition.sourceEventId) {
|
||||||
|
textList.push(`来源事件:${sourceEvent.value?.name || sourceEvent.value?.id || condition.sourceEventId}`);
|
||||||
|
}
|
||||||
|
if (condition.tiers?.length) {
|
||||||
|
textList.push(condition.tiers.map(tier => `${tier.min}~${tier.max ?? "以上"}:${tier.pointValue} 分`).join(","));
|
||||||
|
}
|
||||||
|
return textList.join(";") || "无额外条件";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRuleStatusText(status?: PointRuleStatus): string {
|
||||||
|
return ({
|
||||||
|
DRAFT: "草稿",
|
||||||
|
ACTIVE: "启用",
|
||||||
|
INACTIVE: "停用",
|
||||||
|
DELETED: "已删除"
|
||||||
|
} as Record<string, string>)[status || ""] || "未知状态";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEventEmptyText(): string {
|
||||||
|
if (ledger.value?.changeType === "ADJUST") {
|
||||||
|
return "该流水为人工调整,未关联触发事件";
|
||||||
|
}
|
||||||
|
return canReadEvent.value ? "未找到触发事件" : "暂无触发事件查看权限";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRecordEmptyText(): string {
|
||||||
|
if (ledger.value?.changeType === "ADJUST") {
|
||||||
|
return "该流水为人工调整,未关联事件记录";
|
||||||
|
}
|
||||||
|
return canReadEventRecord.value ? "未找到事件记录" : "暂无事件记录查看权限";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRuleEmptyText(): string {
|
||||||
|
if (ledger.value?.changeType === "ADJUST") {
|
||||||
|
return "该流水为人工调整,未命中积分规则";
|
||||||
|
}
|
||||||
|
return canReadRule.value ? "未找到命中规则" : "暂无命中规则查看权限";
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatSourceValue(value: unknown): string {
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value || "-";
|
||||||
|
}
|
||||||
|
const text = JSON.stringify(value);
|
||||||
|
return text === undefined ? String(value) : text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- 导航 ----------
|
||||||
|
|
||||||
|
async function toCustomerDetail(): Promise<void> {
|
||||||
|
if (customer.value?.id) {
|
||||||
|
await router.push(`/management/customers/${customer.value.id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => [route.params.id, route.query.snapshot], async () => {
|
||||||
|
await loadPageData();
|
||||||
|
}, { immediate: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.point-ledger-detail {
|
||||||
|
gap: 1rem;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: calc(var(--app-nav-height) + 1rem) 0 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.customer-profile,
|
||||||
|
.payload-panel {
|
||||||
|
margin: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
padding: 1.5rem 1rem;
|
||||||
|
color: #52607a;
|
||||||
|
font-size: .875rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payload-panel {
|
||||||
|
.title {
|
||||||
|
margin: 0 0 .5rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html.theme-dark) {
|
||||||
|
.point-ledger-detail {
|
||||||
|
.empty {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payload-panel .title {
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -83,9 +83,9 @@
|
|||||||
v-for="item in pageResult.list"
|
v-for="item in pageResult.list"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
class="item"
|
class="item"
|
||||||
:arrow="!!item.eventRecordId"
|
:arrow="!!item.id"
|
||||||
:hover="!!item.eventRecordId"
|
:hover="!!item.id"
|
||||||
@click="toRecord(item)"
|
@click="toDetail(item)"
|
||||||
>
|
>
|
||||||
<template #leftIcon>
|
<template #leftIcon>
|
||||||
<t-image
|
<t-image
|
||||||
@@ -410,16 +410,6 @@ function buildListOptions(): { allStores?: boolean; storeId?: string } | undefin
|
|||||||
|
|
||||||
// ---------- 展示与导航 ----------
|
// ---------- 展示与导航 ----------
|
||||||
|
|
||||||
// function getLedgerTitle(item: PointLedger): string {
|
|
||||||
// if (item.changeType === "EARN") {
|
|
||||||
// return "登记事件获得积分";
|
|
||||||
// }
|
|
||||||
// if (item.changeType === "REVOKE") {
|
|
||||||
// return "删除登记记录撤销积分";
|
|
||||||
// }
|
|
||||||
// return "人工调整积分";
|
|
||||||
// }
|
|
||||||
|
|
||||||
function getLedgerDescription(item: PointLedger): string {
|
function getLedgerDescription(item: PointLedger): string {
|
||||||
const parts = [`余额 ${item.balanceBefore ?? 0} → ${item.balanceAfter ?? 0}`];
|
const parts = [`余额 ${item.balanceBefore ?? 0} → ${item.balanceAfter ?? 0}`];
|
||||||
if (item.remark) {
|
if (item.remark) {
|
||||||
@@ -441,10 +431,35 @@ function getLedgerTheme(item: PointLedger): string {
|
|||||||
return item.pointDelta && 0 < item.pointDelta ? "increase" : "decrease";
|
return item.pointDelta && 0 < item.pointDelta ? "increase" : "decrease";
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toRecord(item: PointLedger): Promise<void> {
|
async function toDetail(item: PointLedger): Promise<void> {
|
||||||
if (item.eventRecordId) {
|
if (!item.id) {
|
||||||
await router.push(`/management/registration-event-records/${item.eventRecordId}`);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const snapshot: PointLedger = {
|
||||||
|
id: item.id,
|
||||||
|
accountId: item.accountId,
|
||||||
|
storeId: item.storeId,
|
||||||
|
customerId: item.customerId,
|
||||||
|
changeType: item.changeType,
|
||||||
|
direction: item.direction,
|
||||||
|
pointDelta: item.pointDelta,
|
||||||
|
balanceBefore: item.balanceBefore,
|
||||||
|
balanceAfter: item.balanceAfter,
|
||||||
|
ruleId: item.ruleId,
|
||||||
|
eventId: item.eventId,
|
||||||
|
eventRecordId: item.eventRecordId,
|
||||||
|
sourcePayload: item.sourcePayload,
|
||||||
|
idempotencyKey: item.idempotencyKey,
|
||||||
|
remark: item.remark,
|
||||||
|
operatorUserId: item.operatorUserId,
|
||||||
|
occurredAt: item.occurredAt
|
||||||
|
};
|
||||||
|
await router.push({
|
||||||
|
name: "PointLedgerDetail",
|
||||||
|
params: { id: item.id },
|
||||||
|
query: { snapshot: JSON.stringify(snapshot) }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toAdjust(): Promise<void> {
|
async function toAdjust(): Promise<void> {
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ onMounted(loadTags);
|
|||||||
.name {
|
.name {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
line-height: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { RouteRecordRaw } from "vue-router";
|
import type { RouteRecordRaw } from "vue-router";
|
||||||
import PointAccount from "@/pages/point/PointAccount.vue";
|
import PointAccount from "@/pages/point/PointAccount.vue";
|
||||||
import PointAdjust from "@/pages/point/PointAdjust.vue";
|
import PointAdjust from "@/pages/point/PointAdjust.vue";
|
||||||
|
import PointLedgerDetail from "@/pages/point/PointLedgerDetail.vue";
|
||||||
import PointLedgerList from "@/pages/point/PointLedgerList.vue";
|
import PointLedgerList from "@/pages/point/PointLedgerList.vue";
|
||||||
import PointRuleEdit from "@/pages/point/PointRuleEdit.vue";
|
import PointRuleEdit from "@/pages/point/PointRuleEdit.vue";
|
||||||
import PointRuleList from "@/pages/point/PointRuleList.vue";
|
import PointRuleList from "@/pages/point/PointRuleList.vue";
|
||||||
@@ -34,6 +35,20 @@ const pointRoutes: RouteRecordRaw[] = [
|
|||||||
darkBodyBackground: "#10161f"
|
darkBodyBackground: "#10161f"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/management/points/ledger/:id",
|
||||||
|
name: "PointLedgerDetail",
|
||||||
|
component: PointLedgerDetail,
|
||||||
|
meta: {
|
||||||
|
depth: 4,
|
||||||
|
navBarVisible: true,
|
||||||
|
navBarCanBack: true,
|
||||||
|
navBarTitle: "积分流水详情",
|
||||||
|
tabBarVisible: false,
|
||||||
|
bodyBackground: "#F5F5F8",
|
||||||
|
darkBodyBackground: "#10161f"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/management/points/adjust",
|
path: "/management/points/adjust",
|
||||||
name: "PointAdjust",
|
name: "PointAdjust",
|
||||||
|
|||||||
@@ -40,6 +40,16 @@ html.theme-dark body {
|
|||||||
|
|
||||||
.t-form__label {
|
.t-form__label {
|
||||||
color: #555;
|
color: #555;
|
||||||
|
flex: none;
|
||||||
|
min-width: unset;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-cell__title {
|
||||||
|
min-width: unset;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.load-state {
|
.load-state {
|
||||||
|
|||||||
+1
-1
@@ -246,7 +246,7 @@ function renderInvitePoster(options: InvitePosterOptions): HTMLCanvasElement {
|
|||||||
context.fillText("糕店客户管理系统", 600, 1550);
|
context.fillText("糕店客户管理系统", 600, 1550);
|
||||||
context.fillStyle = "#64748B";
|
context.fillStyle = "#64748B";
|
||||||
context.font = "400 40px Microsoft YaHei, sans-serif";
|
context.font = "400 40px Microsoft YaHei, sans-serif";
|
||||||
context.fillText("客户档案 | 事件登记 | 积分激励 | 门店协同 | AI 分析", 600, 1645);
|
context.fillText("客户档案 | 事件登记 | 积分激励 | 门店协同", 600, 1645);
|
||||||
context.fillStyle = "#94A3B8";
|
context.fillStyle = "#94A3B8";
|
||||||
context.font = "400 40px Microsoft YaHei, sans-serif";
|
context.font = "400 40px Microsoft YaHei, sans-serif";
|
||||||
context.fillText("本邀请仅限本人使用,请勿转发", 600, 1760);
|
context.fillText("本邀请仅限本人使用,请勿转发", 600, 1760);
|
||||||
|
|||||||
Reference in New Issue
Block a user