fix PointLedgerList.vue style

This commit is contained in:
Timi
2026-09-11 11:40:46 +08:00
parent 3500758c2f
commit 537eb5ac7a
+109 -77
View File
@@ -2,13 +2,14 @@
<div v-can="permissionCodes.point.ledgerRead" class="point-ledger-list"> <div v-can="permissionCodes.point.ledgerRead" class="point-ledger-list">
<div class="filters"> <div class="filters">
<t-input <t-input
v-model.trim="customerKeyword" v-model="customerKeyword"
class="customer" class="customer"
type="search"
borderless borderless
clearable
placeholder="输入客户编码或姓名" placeholder="输入客户编码或姓名"
@clear="applyCustomerSearch" @clear="searchCustomer"
@enter="applyCustomerSearch" @enter="searchCustomer"
@input="searchCustomer"
> >
<template #suffix-icon> <template #suffix-icon>
<t-button <t-button
@@ -34,31 +35,31 @@
@change="selectDateFilter" @change="selectDateFilter"
/> />
</t-dropdown-menu> </t-dropdown-menu>
<div v-if="isCustomDate" class="date-range">
<t-button
size="small"
variant="outline"
:content="dateRange[0] || '开始时间'"
@click="startDateVisible = true"
/>
<span>至</span>
<t-button
size="small"
variant="outline"
:content="dateRange[1] || '结束时间'"
@click="endDateVisible = true"
/>
</div> </div>
</div>
<card-container v-if="customer" class="customer">
<customer-profile-card :customer="customer" />
</card-container>
<t-pull-down-refresh <t-pull-down-refresh
v-model="isRefreshing" v-model="isRefreshing"
:refresh-timeout="30000" :refresh-timeout="30000"
@refresh="reload" @refresh="reload"
@scrolltolower="load" @scrolltolower="load"
> >
<div class="list-wrap">
<card-container v-if="customer" class="customer">
<customer-profile-card :customer="customer" />
</card-container>
<t-cell-group class="summary" theme="card">
<t-cell
title="开始时间"
:note="dateRange[0] || '-'"
arrow
@click="openStartDate"
/>
<t-cell
title="结束时间"
:note="dateRange[1] || '-'"
arrow
@click="openEndDate"
/>
</t-cell-group>
<t-cell-group v-if="pageResult.list.length" class="list" theme="card"> <t-cell-group v-if="pageResult.list.length" class="list" theme="card">
<t-cell <t-cell
v-entrance-transition="index * 30" v-entrance-transition="index * 30"
@@ -91,7 +92,10 @@
</template> </template>
<template #description> <template #description>
<div class="description"> <div class="description">
<div v-text="`时间:${Time.toPassedDateTime(item.occurredAt)}`" /> <div>
<span>时间:</span>
<pass-time-label :timestamp="item.occurredAt" underline />
</div>
<div v-text="`余额:${item.balanceBefore ?? 0} → ${item.balanceAfter ?? 0}`" /> <div v-text="`余额:${item.balanceBefore ?? 0} → ${item.balanceAfter ?? 0}`" />
<div v-text="item.remark" /> <div v-text="item.remark" />
</div> </div>
@@ -102,18 +106,9 @@
</t-cell> </t-cell>
</t-cell-group> </t-cell-group>
<div class="center-tips" v-text="loadStateText" /> <div class="center-tips" v-text="loadStateText" />
</div>
</t-pull-down-refresh> </t-pull-down-refresh>
</div>
<section v-if="customer" class="actions">
<t-button
v-can="permissionCodes.point.adjust"
theme="primary"
size="small"
@click="toAdjust"
>
人工调整
</t-button>
</section>
<customer-selector <customer-selector
v-model="selectedCustomerId" v-model="selectedCustomerId"
v-model:visible="selectorVisible" v-model:visible="selectorVisible"
@@ -121,30 +116,33 @@
/> />
<t-popup v-model="startDateVisible" placement="bottom"> <t-popup v-model="startDateVisible" placement="bottom">
<t-date-time-picker <t-date-time-picker
v-model="dateRange[0]" v-if="startDateVisible"
v-model="startDraft"
format="YYYY-MM-DD HH:mm" format="YYYY-MM-DD HH:mm"
:mode="['date', 'minute']" :mode="['date', 'minute']"
title="开始时间" title="开始时间"
@cancel="startDateVisible = false" :default-value="dateRange[0]"
@confirm="confirmDateRange" @cancel="cancelStartDate"
@confirm="confirmStartDate"
/> />
</t-popup> </t-popup>
<t-popup v-model="endDateVisible" placement="bottom"> <t-popup v-model="endDateVisible" placement="bottom">
<t-date-time-picker <t-date-time-picker
v-model="dateRange[1]" v-if="endDateVisible"
v-model="endDraft"
format="YYYY-MM-DD HH:mm" format="YYYY-MM-DD HH:mm"
:mode="['date', 'minute']" :mode="['date', 'minute']"
title="结束时间" title="结束时间"
@cancel="endDateVisible = false" :default-value="dateRange[1]"
@confirm="confirmDateRange" @cancel="cancelEndDate"
@confirm="confirmEndDate"
/> />
</t-popup> </t-popup>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { DropdownValue } from "tdesign-mobile-vue"; import type { DropdownValue } from "tdesign-mobile-vue";
import { Time } from "timi-web"; import { PassTimeLabel, Time, Toolkit } from "timi-web";
import { type PageResult, useUserStore } from "timi-web-api"; import { type PageResult, useUserStore } from "timi-web-api";
import CustomerAPI from "@/api/CustomerAPI"; import CustomerAPI from "@/api/CustomerAPI";
import PointAPI from "@/api/PointAPI"; import PointAPI from "@/api/PointAPI";
@@ -178,14 +176,16 @@ const selectorVisible = ref(false);
const changeTypeFilter = ref("ALL"); const changeTypeFilter = ref("ALL");
const dateFilter = ref<DateFilter>("last30"); const dateFilter = ref<DateFilter>("last30");
const dateRange = ref<[string, string]>(buildDateRange(dateFilter.value)); const dateRange = ref<[string, string]>(buildDateRange(dateFilter.value));
const startDraft = ref("");
const endDraft = ref("");
const startDateVisible = ref(false); const startDateVisible = ref(false);
const endDateVisible = ref(false); const endDateVisible = ref(false);
const changeTypeOptions = [ const changeTypeOptions = [
{ label: "全部类型", value: "ALL" }, { label: "全部类型", value: "ALL" },
{ label: "获得 EARN", value: "EARN" }, { label: "获得", value: "EARN" },
{ label: "消费 CONSUME", value: "CONSUME" }, { label: "消费", value: "CONSUME" },
{ label: "撤销 REVOKE", value: "REVOKE" }, { label: "撤销", value: "REVOKE" },
{ label: "调整 ADJUST", value: "ADJUST" } { label: "调整", value: "ADJUST" }
]; ];
const dateFilterOptions = [ const dateFilterOptions = [
{ label: "全部时间", value: "all" }, { label: "全部时间", value: "all" },
@@ -195,7 +195,6 @@ const dateFilterOptions = [
{ label: "自定义", value: "custom" } { label: "自定义", value: "custom" }
]; ];
const dateFilterLabel = computed(() => dateFilterOptions.find(item => item.value === dateFilter.value)?.label || "时间范围"); const dateFilterLabel = computed(() => dateFilterOptions.find(item => item.value === dateFilter.value)?.label || "时间范围");
const isCustomDate = computed(() => dateFilter.value === "custom");
async function handleCustomerChange(value: string | string[]): Promise<void> { async function handleCustomerChange(value: string | string[]): Promise<void> {
selectedCustomerId.value = Array.isArray(value) ? String(value[0] || "") : value; selectedCustomerId.value = Array.isArray(value) ? String(value[0] || "") : value;
@@ -209,7 +208,11 @@ async function handleCustomerChange(value: string | string[]): Promise<void> {
await reload(); await reload();
} }
async function applyCustomerSearch(): Promise<void> { function getCustomerSearchKeyword(value?: Customer): string {
return value?.name?.trim() || value?.code?.trim() || "";
}
const searchCustomer = Toolkit.debounce(async () => {
const keyword = customerKeyword.value.trim(); const keyword = customerKeyword.value.trim();
if (!keyword) { if (!keyword) {
selectedCustomerId.value = ""; selectedCustomerId.value = "";
@@ -220,7 +223,6 @@ async function applyCustomerSearch(): Promise<void> {
if (keyword === getCustomerSearchKeyword(customer.value)) { if (keyword === getCustomerSearchKeyword(customer.value)) {
return; return;
} }
try { try {
const matched = await CustomerAPI.findByCode(keyword, currentStoreStore.currentStoreId || undefined) const matched = await CustomerAPI.findByCode(keyword, currentStoreStore.currentStoreId || undefined)
|| await CustomerAPI.findByName(keyword); || await CustomerAPI.findByName(keyword);
@@ -235,11 +237,7 @@ async function applyCustomerSearch(): Promise<void> {
} catch { } catch {
Message.error("客户信息加载失败"); Message.error("客户信息加载失败");
} }
} }, false);
function getCustomerSearchKeyword(value?: Customer): string {
return value?.name?.trim() || value?.code?.trim() || "";
}
async function selectChangeType(value: DropdownValue): Promise<void> { async function selectChangeType(value: DropdownValue): Promise<void> {
if (Array.isArray(value)) { if (Array.isArray(value)) {
@@ -254,15 +252,48 @@ async function selectDateFilter(value: DropdownValue): Promise<void> {
return; return;
} }
dateFilter.value = String(value) as DateFilter; dateFilter.value = String(value) as DateFilter;
if (!isCustomDate.value) { if (dateFilter.value !== "custom") {
dateRange.value = buildDateRange(dateFilter.value); dateRange.value = buildDateRange(dateFilter.value);
await reload(); await reload();
} }
} }
function openStartDate(): void {
startDraft.value = dateRange.value[0];
startDateVisible.value = true;
}
function openEndDate(): void {
endDraft.value = dateRange.value[1];
endDateVisible.value = true;
}
function cancelStartDate(): void {
startDateVisible.value = false;
startDraft.value = dateRange.value[0];
}
function cancelEndDate(): void {
endDateVisible.value = false;
endDraft.value = dateRange.value[1];
}
async function confirmStartDate(value?: string | number): Promise<void> {
startDateVisible.value = false;
dateRange.value = [String(value || startDraft.value), dateRange.value[1]];
await confirmDateRange();
}
async function confirmEndDate(value?: string | number): Promise<void> {
endDateVisible.value = false;
dateRange.value = [dateRange.value[0], String(value || endDraft.value)];
await confirmDateRange();
}
async function confirmDateRange(): Promise<void> { async function confirmDateRange(): Promise<void> {
startDateVisible.value = false; startDateVisible.value = false;
endDateVisible.value = false; endDateVisible.value = false;
dateFilter.value = "custom";
if (dateRange.value[0] && dateRange.value[1] && dateRange.value[1] < dateRange.value[0]) { if (dateRange.value[0] && dateRange.value[1] && dateRange.value[1] < dateRange.value[0]) {
dateRange.value = [dateRange.value[1], dateRange.value[0]]; dateRange.value = [dateRange.value[1], dateRange.value[0]];
} }
@@ -405,15 +436,6 @@ async function toDetail(item: PointLedger): Promise<void> {
}); });
} }
async function toAdjust(): Promise<void> {
await router.push({
name: "PointAdjust",
query: {
customerId: selectedCustomerId.value
}
});
}
// ---------- 时间 ---------- // ---------- 时间 ----------
function buildDateRange(type: DateFilter): [string, string] { function buildDateRange(type: DateFilter): [string, string] {
@@ -471,6 +493,10 @@ onMounted(async () => {
Message.error("积分流水页面加载失败"); Message.error("积分流水页面加载失败");
} }
}); });
onUnmounted(() => {
searchCustomer.cancel();
});
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@@ -515,23 +541,29 @@ onMounted(async () => {
padding-top: .8rem; padding-top: .8rem;
border-radius: 0 0 1rem 1rem; border-radius: 0 0 1rem 1rem;
} }
}
.date-range { .summary {
gap: .5rem; overflow: hidden;
padding: .5rem 0 .75rem;
display: flex;
align-items: center;
.t-button { :deep(.t-cell__title) {
flex: 1; flex: 0 0 4.5rem;
}
:deep(.t-cell__note) {
flex: 1 1 0;
min-width: 0; min-width: 0;
overflow: hidden;
text-align: right;
text-overflow: ellipsis;
white-space: nowrap;
}
} }
span { .list-wrap {
color: #52607a; gap: 1rem;
} display: flex;
} flex-direction: column;
}
.list { .list {
@@ -569,6 +601,7 @@ onMounted(async () => {
} }
} }
} }
}
.actions { .actions {
left: 1rem; left: 1rem;
@@ -599,7 +632,6 @@ onMounted(async () => {
} }
} }
.filters .date-range span,
.customer-id, .customer-id,
.empty { .empty {
color: #94a3b8; color: #94a3b8;