add customer or operator info

This commit is contained in:
Timi
2026-09-17 01:23:17 +08:00
parent 3135c41b21
commit 47723c6403
2 changed files with 104 additions and 22 deletions
+98 -18
View File
@@ -20,24 +20,46 @@
@refresh="refresh"
@scrolltolower="loadMore"
>
<t-cell-group v-if="recordList.length" class="list" theme="card">
<t-cell-group v-if="recordList.length" class="list empty-cell-title-margin" theme="card">
<t-cell
v-for="(record, index) in recordList"
:key="record.id || `${record.occurredAt}-${record.requestNo}-${index}`"
class="record"
class="item"
:arrow="!!record.id"
:hover="!!record.id"
v-entrance-transition="index * 30"
@click="toDetail(record)"
>
<template #leftIcon>
<span class="icon" :class="getDeltaClass(record.onHandDelta)">
<t-image
v-if="getCustomerPhotoURL(record.customer, 64)"
:src="getCustomerPhotoURL(record.customer, 64)"
:alt="getCustomerText(record)"
fit="cover"
class="avatar"
/>
<div
v-else-if="record.customer"
class="avatar fallback"
v-text="getCustomerText(record).slice(0, 1)"
/>
<t-image
v-else-if="record.operator"
:src="getOperatorAvatar(record)"
:alt="getOperatorText(record)"
fit="cover"
class="avatar"
/>
<span v-else class="icon" :class="getDeltaClass(record.onHandDelta)">
<t-icon :name="getOperationIcon(record.operationType)" size="1.25rem" />
</span>
</template>
<template #title>
<div class="title">
<strong v-text="getStockOperationText(record.operationType)" />
<span v-if="record.customer" class="actor" v-text="getCustomerText(record)" />
<span v-else-if="record.operator" class="actor" v-text="getOperatorText(record)" />
<strong class="operation" v-text="getStockOperationText(record.operationType)" />
<strong class="product-name" v-text="record.productNameSnapshot || '未命名产品'" />
<span
v-if="record.quantity !== undefined && record.quantity !== null && record.quantity !== ''"
class="quantity"
@@ -45,18 +67,16 @@
/>
</div>
</template>
<template #note>
<template #description>
<div class="description">
<pass-time-label :timestamp="record.occurredAt" underline />
<div class="delta">
<span>库存变更:</span>
<span
class="delta"
class="value"
:class="getDeltaClass(record.onHandDelta)"
v-text="getDeltaText(record.onHandDelta)"
/>
</template>
<template #description>
<div class="description">
<strong v-text="record.productNameSnapshot || '未命名产品'" />
<div>
<pass-time-label :timestamp="record.occurredAt" underline />
</div>
</div>
</template>
@@ -71,6 +91,7 @@
<script setup lang="ts">
import { type DropdownValue } from "tdesign-mobile-vue";
import { PassTimeLabel } from "timi-web";
import { UserAPI } from "timi-web-api";
import ProductAPI from "@/api/ProductAPI";
import { useNavBarStore } from "@/store/navBarStore";
import type { StockOperationType, StockRecord, StockRecordDirection } from "@/types/Product";
@@ -78,6 +99,8 @@ import { getErrorMessage } from "@/utils/error";
import { getProductQuantityText, getStockOperationText } from "@/utils/product";
import { Message } from "@/utils/message";
import { permissionCodes } from "@/utils/permission";
import { getCustomerPhotoURL } from "@/utils/customer";
import { buildFallbackAvatar } from "@/utils/avatar";
defineOptions({ name: "ProductStockRecordList" });
@@ -159,6 +182,18 @@ function getStockQuantityText(record: StockRecord): string {
return `${getProductQuantityText(record.quantity)}${unitText}`;
}
function getCustomerText(record: StockRecord): string {
return record.customer?.name || record.customer?.code || "未知客户";
}
function getOperatorText(record: StockRecord): string {
return record.operator?.nick || record.operator?.name || "未知操作人";
}
function getOperatorAvatar(record: StockRecord): string {
return UserAPI.getAvatarURL(record.operator) || buildFallbackAvatar(getOperatorText(record), "#0f766e");
}
function getDeltaText(value?: number | string): string {
const amount = Number(value || 0);
const text = String(value || "0").replace(/^-/, "");
@@ -340,7 +375,24 @@ onUnmounted(() => {
.list {
margin: 0;
.record {
.item {
padding: 10px;
min-width: 0;
:deep(.t-cell__title) {
min-width: 0;
width: 0;
}
:deep(.t-cell__title-text) {
min-width: 0;
width: 100%;
}
.avatar {
width: 3.5rem;
height: 3.5rem;
}
.icon {
width: 2.25rem;
@@ -354,23 +406,51 @@ onUnmounted(() => {
.title {
gap: .5rem;
min-width: 0;
max-width: 100%;
flex: 1;
display: flex;
font-size: .75rem;
align-items: center;
white-space: nowrap;
.actor {
color: var(--td-text-color-secondary);
flex: 0 0 auto;
}
.operation {
flex: 0 0 auto;
}
.product-name {
min-width: 0;
flex: 0 1 auto;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.quantity {
color: var(--td-text-color-secondary);
font-size: .875rem;
flex: 0 0 auto;
font-weight: 400;
}
}
.description {
gap: .5rem;
display: flex;
font-size: .75rem;
align-items: center;
justify-content: space-between;
.delta {
.value {
font-size: 1.25rem;
}
.description {
gap: .125rem;
display: grid;
}
}
}
}
+2
View File
@@ -1,4 +1,5 @@
import type { Attachment, Model, PageResult, User } from "timi-web-api";
import type { Customer } from "@/types/Customer";
export type ProductType = "SERVICE" | "GOODS" | "CONSUMABLE";
export type ProductAttachmentType = "PHOTO" | "OTHER";
@@ -184,6 +185,7 @@ export type StockRecord = {
remark?: string | null;
operator?: Partial<User>;
attachmentList?: Partial<Attachment>[];
customer?: Customer;
} & Model;
export type StockRecordPage = {