fix OrderFulfillmentList.vue style
This commit is contained in:
@@ -2,30 +2,38 @@
|
|||||||
<div v-can="permissionCodes.orderFulfillment.read" class="fulfillment-list">
|
<div v-can="permissionCodes.orderFulfillment.read" class="fulfillment-list">
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<t-dropdown-menu>
|
<t-dropdown-menu>
|
||||||
<t-dropdown-item v-model="type" label="履约类型" :options="typeOptions" @change="selectType" />
|
<t-dropdown-item
|
||||||
<t-dropdown-item v-model="status" label="履约状态" :options="statusOptions" @change="selectStatus" />
|
v-model="type"
|
||||||
|
label="履约类型"
|
||||||
|
:options="typeOptions"
|
||||||
|
@change="selectType"
|
||||||
|
/>
|
||||||
|
<t-dropdown-item
|
||||||
|
v-model="status"
|
||||||
|
label="履约状态"
|
||||||
|
:options="statusOptions"
|
||||||
|
@change="selectStatus"
|
||||||
|
/>
|
||||||
</t-dropdown-menu>
|
</t-dropdown-menu>
|
||||||
</div>
|
</div>
|
||||||
<t-pull-down-refresh v-model="refreshing" :refresh-timeout="30000" @refresh="refresh" @scrolltolower="loadMore">
|
<t-pull-down-refresh
|
||||||
<t-cell-group v-if="list.length" theme="card">
|
class="list-wrap"
|
||||||
<t-cell v-for="(item, index) in list" :key="item.id" arrow hover v-entrance-transition="index * 30" @click="toDetail(item)">
|
v-model="refreshing"
|
||||||
<template #title>
|
:refresh-timeout="30000"
|
||||||
<div class="title">
|
@refresh="refresh"
|
||||||
<strong v-text="item.id || '履约单'" />
|
@scrolltolower="loadMore"
|
||||||
<t-tag :content="getFulfillmentStatusText(item.status)" variant="light-outline" :theme="getStatusTheme(item.status)" />
|
>
|
||||||
</div>
|
<div v-if="list.length" class="items">
|
||||||
</template>
|
<order-fulfillment-list-cell
|
||||||
<template #description>
|
v-for="(item, index) in list"
|
||||||
<div class="description">
|
:key="item.id"
|
||||||
<span v-text="getFulfillmentTypeText(item.fulfillmentType)" />
|
class="item"
|
||||||
<span v-text="`订单:${item.salesOrderId || '未知'}`" />
|
:fulfillment="item"
|
||||||
<span v-text="`${(item.itemList || []).length} 项`" />
|
v-entrance-transition="index * 30"
|
||||||
</div>
|
@detail="toDetail(item)"
|
||||||
</template>
|
/>
|
||||||
<template #note><span v-text="item.deliveredAt ? Time.toDateTime(item.deliveredAt) : '时间未知'" /></template>
|
</div>
|
||||||
</t-cell>
|
<div v-else class="center-tips" v-text="loading ? '正在加载履约单' : '暂无履约单'" />
|
||||||
</t-cell-group>
|
|
||||||
<div v-else class="empty" v-text="loading ? '正在加载履约单' : '暂无履约单'" />
|
|
||||||
<div class="center-tips" v-text="loading ? '正在加载' : noMore ? '已经到底了' : '上拉加载更多'" />
|
<div class="center-tips" v-text="loading ? '正在加载' : noMore ? '已经到底了' : '上拉加载更多'" />
|
||||||
</t-pull-down-refresh>
|
</t-pull-down-refresh>
|
||||||
</div>
|
</div>
|
||||||
@@ -34,26 +42,32 @@
|
|||||||
|
|
||||||
<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 { useUserStore } from "timi-web-api";
|
import { useUserStore } from "timi-web-api";
|
||||||
import FulfillmentAPI from "@/api/FulfillmentAPI";
|
import FulfillmentAPI from "@/api/FulfillmentAPI";
|
||||||
import NavBarActionMenu from "@/components/NavBarActionMenu.vue";
|
import NavBarActionMenu from "@/components/NavBarActionMenu.vue";
|
||||||
|
import OrderFulfillmentListCell from "@/pages/fulfillment/components/OrderFulfillmentListCell.vue";
|
||||||
import { useNavBarStore } from "@/store/navBarStore";
|
import { useNavBarStore } from "@/store/navBarStore";
|
||||||
import type { FulfillmentStatus, FulfillmentType, OrderFulfillment } from "@/types/Fulfillment";
|
import type { FulfillmentStatus, FulfillmentType, OrderFulfillment } from "@/types/Fulfillment";
|
||||||
import { getErrorMessage } from "@/utils/error";
|
import { getErrorMessage } from "@/utils/error";
|
||||||
import { getFulfillmentStatusText, getFulfillmentTypeText, getStatusTheme } from "@/utils/salesOrder";
|
|
||||||
import { Message } from "@/utils/message";
|
import { Message } from "@/utils/message";
|
||||||
import { permissionCodes } from "@/utils/permission";
|
import { permissionCodes } from "@/utils/permission";
|
||||||
|
|
||||||
defineOptions({ name: "OrderFulfillmentList" });
|
defineOptions({ name: "OrderFulfillmentList" });
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const navBarStore = useNavBarStore();
|
const navBarStore = useNavBarStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const canCreate = computed(() => userStore.hasPermissions(permissionCodes.orderFulfillment.create));
|
const canCreate = computed(() => userStore.hasPermissions(permissionCodes.orderFulfillment.create));
|
||||||
const actions = computed(() => canCreate.value ? [{ key: "create", text: "创建履约单", icon: "add", theme: "primary" as const, action: toCreate }] : []);
|
const actions = computed(() => canCreate.value ? [{
|
||||||
const type = ref("ALL");
|
key: "create",
|
||||||
const status = ref(String(route.query.status || "ALL"));
|
text: "创建履约单",
|
||||||
|
icon: "add",
|
||||||
|
theme: "primary" as const,
|
||||||
|
action: toCreate
|
||||||
|
}] : []);
|
||||||
|
const type = ref<"ALL" | FulfillmentType>("ALL");
|
||||||
|
const status = ref<"ALL" | FulfillmentStatus>(getInitialStatus(route.query.status));
|
||||||
const list = ref<OrderFulfillment[]>([]);
|
const list = ref<OrderFulfillment[]>([]);
|
||||||
const pageIndex = ref(0);
|
const pageIndex = ref(0);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
@@ -61,7 +75,11 @@ const loading = ref(false);
|
|||||||
const refreshing = ref(false);
|
const refreshing = ref(false);
|
||||||
const noMore = ref(false);
|
const noMore = ref(false);
|
||||||
const pageSize = 15;
|
const pageSize = 15;
|
||||||
const typeOptions = [{ label: "全部类型", value: "ALL" }, { label: "套餐权益", value: "PACKAGE_ENTITLEMENT" }, { label: "直接产品", value: "DIRECT_PRODUCT" }];
|
const typeOptions = [
|
||||||
|
{ label: "全部类型", value: "ALL" },
|
||||||
|
{ label: "套餐权益", value: "PACKAGE_ENTITLEMENT" },
|
||||||
|
{ label: "直接产品", value: "DIRECT_PRODUCT" }
|
||||||
|
];
|
||||||
const statusOptions = [
|
const statusOptions = [
|
||||||
{ label: "全部状态", value: "ALL" },
|
{ label: "全部状态", value: "ALL" },
|
||||||
{ label: "等待库存", value: "WAITING_STOCK" },
|
{ label: "等待库存", value: "WAITING_STOCK" },
|
||||||
@@ -71,36 +89,92 @@ const statusOptions = [
|
|||||||
{ label: "已撤销", value: "CANCELLED" },
|
{ label: "已撤销", value: "CANCELLED" },
|
||||||
{ label: "已冲正", value: "REVOKED" }
|
{ label: "已冲正", value: "REVOKED" }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function getQueryText(value: unknown): string {
|
||||||
|
return Array.isArray(value) ? "" : typeof value === "string" ? value : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInitialStatus(value: unknown): "ALL" | FulfillmentStatus {
|
||||||
|
const statusValue = getQueryText(value);
|
||||||
|
if (["WAITING_STOCK", "PENDING", "VERIFIED", "REJECTED", "CANCELLED", "REVOKED"].includes(statusValue)) {
|
||||||
|
return statusValue as FulfillmentStatus;
|
||||||
|
}
|
||||||
|
return "ALL";
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchList(reset: boolean): Promise<void> {
|
async function fetchList(reset: boolean): Promise<void> {
|
||||||
if (loading.value || (!reset && noMore.value)) return;
|
if (loading.value || (!reset && noMore.value)) {
|
||||||
if (reset) { pageIndex.value = 0; total.value = 0; noMore.value = false; list.value = []; }
|
return;
|
||||||
|
}
|
||||||
|
if (reset) {
|
||||||
|
pageIndex.value = 0;
|
||||||
|
total.value = 0;
|
||||||
|
noMore.value = false;
|
||||||
|
list.value = [];
|
||||||
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const result = await FulfillmentAPI.list({
|
const result = await FulfillmentAPI.list({
|
||||||
index: pageIndex.value,
|
index: pageIndex.value,
|
||||||
size: pageSize,
|
size: pageSize,
|
||||||
salesOrderId: String(route.query.salesOrderId || "") || undefined,
|
salesOrderId: getQueryText(route.query.salesOrderId) || undefined,
|
||||||
fulfillmentType: type.value === "ALL" ? undefined : type.value as FulfillmentType,
|
fulfillmentType: type.value === "ALL" ? undefined : type.value,
|
||||||
status: status.value === "ALL" ? undefined : status.value as FulfillmentStatus
|
status: status.value === "ALL" ? undefined : status.value
|
||||||
});
|
});
|
||||||
const rows = result.list || [];
|
const rows = result.list || [];
|
||||||
list.value = reset ? rows : list.value.concat(rows);
|
list.value = reset ? rows : list.value.concat(rows);
|
||||||
total.value = result.total || 0;
|
total.value = result.total || 0;
|
||||||
pageIndex.value += 1;
|
pageIndex.value += 1;
|
||||||
noMore.value = rows.length < pageSize || total.value <= list.value.length;
|
noMore.value = rows.length < pageSize || total.value <= list.value.length;
|
||||||
} finally { loading.value = false; }
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async function refresh(): Promise<void> { try { await fetchList(true); } catch (error) { Message.error(getErrorMessage(error, "履约单加载失败")); } finally { refreshing.value = false; } }
|
|
||||||
async function loadMore(): Promise<void> { try { await fetchList(false); } catch (error) { Message.error(getErrorMessage(error, "履约单加载失败")); } }
|
async function refresh(): Promise<void> {
|
||||||
async function selectType(value: DropdownValue): Promise<void> { if (!Array.isArray(value)) { type.value = String(value); await fetchList(true); } }
|
try {
|
||||||
async function selectStatus(value: DropdownValue): Promise<void> { if (!Array.isArray(value)) { status.value = String(value); await fetchList(true); } }
|
await fetchList(true);
|
||||||
|
} catch (error) {
|
||||||
|
Message.error(getErrorMessage(error, "履约单加载失败"));
|
||||||
|
} finally {
|
||||||
|
refreshing.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadMore(): Promise<void> {
|
||||||
|
try {
|
||||||
|
await fetchList(false);
|
||||||
|
} catch (error) {
|
||||||
|
Message.error(getErrorMessage(error, "履约单加载失败"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function selectType(value: DropdownValue): Promise<void> {
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
type.value = String(value) as "ALL" | FulfillmentType;
|
||||||
|
await fetchList(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function selectStatus(value: DropdownValue): Promise<void> {
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
status.value = String(value) as "ALL" | FulfillmentStatus;
|
||||||
|
await fetchList(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function toDetail(item: OrderFulfillment): Promise<void> {
|
async function toDetail(item: OrderFulfillment): Promise<void> {
|
||||||
if (item.id) await router.push({
|
if (item.id) {
|
||||||
path: `/management/order-fulfillments/${item.id}`,
|
await router.push({
|
||||||
query: { transitionDepth: String(getCurrentRouteDepth() + 1) }
|
path: `/management/order-fulfillments/${item.id}`,
|
||||||
});
|
query: { transitionDepth: String(getCurrentRouteDepth() + 1) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function toCreate(): Promise<void> {
|
||||||
|
await router.push("/management/order-fulfillments/create");
|
||||||
}
|
}
|
||||||
async function toCreate(): Promise<void> { await router.push("/management/order-fulfillments/create"); }
|
|
||||||
|
|
||||||
function getCurrentRouteDepth(): number {
|
function getCurrentRouteDepth(): number {
|
||||||
const transitionDepth = Array.isArray(route.query.transitionDepth)
|
const transitionDepth = Array.isArray(route.query.transitionDepth)
|
||||||
@@ -113,15 +187,52 @@ function getCurrentRouteDepth(): number {
|
|||||||
return Number(route.meta.depth ?? 0);
|
return Number(route.meta.depth ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async () => { navBarStore.clearRight(); navBarStore.setCustomRightVisible(canCreate.value); try { await fetchList(true); } catch (error) { Message.error(getErrorMessage(error, "履约单加载失败")); } });
|
onMounted(async () => {
|
||||||
|
navBarStore.clearRight();
|
||||||
|
navBarStore.setCustomRightVisible(canCreate.value);
|
||||||
|
try {
|
||||||
|
await fetchList(true);
|
||||||
|
} catch (error) {
|
||||||
|
Message.error(getErrorMessage(error, "履约单加载失败"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
onUnmounted(() => navBarStore.clearRight());
|
onUnmounted(() => navBarStore.clearRight());
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.fulfillment-list { padding: var(--app-nav-height) 0 1rem;
|
.fulfillment-list {
|
||||||
.filters { top: var(--app-nav-height); z-index: 10; padding: .75rem 1rem; position: sticky; background: #f5f5f8; box-shadow: var(--td-shadow-1); }
|
padding: var(--app-nav-height) 0 1rem;
|
||||||
.title, .description { gap: .5rem; display: flex; align-items: center; }
|
|
||||||
.description { color: var(--td-text-color-secondary); flex-wrap: wrap; }
|
.filters {
|
||||||
.empty { color: var(--td-text-color-secondary); padding: 3rem 1rem; text-align: center; }
|
top: var(--app-nav-height);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 10;
|
||||||
|
display: flex;
|
||||||
|
padding: .75rem 1rem;
|
||||||
|
position: sticky;
|
||||||
|
background: var(--td-bg-color-page);
|
||||||
|
box-shadow: var(--td-shadow-1);
|
||||||
|
|
||||||
|
:deep(.t-dropdown-menu) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-wrap {
|
||||||
|
padding-top: 1rem;
|
||||||
|
|
||||||
|
.items {
|
||||||
|
gap: 1rem;
|
||||||
|
display: flex;
|
||||||
|
padding: 0 1rem;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,250 @@
|
|||||||
|
<template>
|
||||||
|
<div class="fulfillment-cell">
|
||||||
|
<div class="header">
|
||||||
|
<div class="left">
|
||||||
|
<t-image
|
||||||
|
v-if="photoURL"
|
||||||
|
:src="photoURL"
|
||||||
|
:alt="customerName"
|
||||||
|
fit="cover"
|
||||||
|
class="avatar"
|
||||||
|
/>
|
||||||
|
<div v-else class="avatar fallback" v-text="avatarText" />
|
||||||
|
</div>
|
||||||
|
<div class="main">
|
||||||
|
<div class="customer-status">
|
||||||
|
<strong class="customer" v-text="customerName" />
|
||||||
|
<t-tag
|
||||||
|
:content="statusText"
|
||||||
|
size="small"
|
||||||
|
variant="light-outline"
|
||||||
|
:theme="statusTheme"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<pass-time-label class="time" :timestamp="fulfillment.deliveredAt" underline />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<t-divider />
|
||||||
|
<div class="product">
|
||||||
|
<div class="items">
|
||||||
|
<t-tag
|
||||||
|
v-for="(item, index) in itemList"
|
||||||
|
:key="item.id || `${item.productId}-${index}`"
|
||||||
|
:content="getProductText(item)"
|
||||||
|
theme="primary"
|
||||||
|
variant="light"
|
||||||
|
/>
|
||||||
|
<t-tag v-if="!itemList.length" content="暂无产品" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary" v-text="productSummaryText" />
|
||||||
|
<t-divider />
|
||||||
|
<div class="people-actions">
|
||||||
|
<div class="person">
|
||||||
|
<span class="label">操作人</span>
|
||||||
|
<strong v-text="operatorName" />
|
||||||
|
</div>
|
||||||
|
<div v-if="showVerifier" class="person">
|
||||||
|
<span class="label">核销人</span>
|
||||||
|
<strong v-text="verifierName" />
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<t-button
|
||||||
|
theme="primary"
|
||||||
|
size="extra-small"
|
||||||
|
content="详情"
|
||||||
|
@click.stop="emit('detail')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { PassTimeLabel } from "timi-web";
|
||||||
|
import type { OrderFulfillment, OrderFulfillmentItem } from "@/types/Fulfillment";
|
||||||
|
import { getCustomerPhotoURL } from "@/utils/customer";
|
||||||
|
import { getPackageQuantityText } from "@/utils/package";
|
||||||
|
import { getFulfillmentStatusText, getStatusTheme } from "@/utils/salesOrder";
|
||||||
|
|
||||||
|
defineOptions({ name: "OrderFulfillmentListCell" });
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
fulfillment: OrderFulfillment;
|
||||||
|
}>();
|
||||||
|
const emit = defineEmits<{
|
||||||
|
detail: [];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const itemList = computed(() => props.fulfillment.itemList || []);
|
||||||
|
const customerName = computed(() => props.fulfillment.customer?.name || props.fulfillment.customer?.code || props.fulfillment.customerId || "未知客户");
|
||||||
|
const avatarText = computed(() => customerName.value.slice(0, 1) || "客");
|
||||||
|
const photoURL = computed(() => getCustomerPhotoURL(props.fulfillment.customer, 64));
|
||||||
|
const statusText = computed(() => getFulfillmentStatusText(props.fulfillment.status));
|
||||||
|
const statusTheme = computed(() => getStatusTheme(props.fulfillment.status));
|
||||||
|
const operatorName = computed(() => getUserName(props.fulfillment.operator, props.fulfillment.operatorUserId, "未知操作人"));
|
||||||
|
const verifierName = computed(() => getUserName(props.fulfillment.verifier, props.fulfillment.verifierUserId, "未知核销人"));
|
||||||
|
const showVerifier = computed(() => ["VERIFIED", "REVOKED"].includes(props.fulfillment.status || ""));
|
||||||
|
const totalProductQuantity = computed(() => {
|
||||||
|
let total = 0;
|
||||||
|
for (const item of itemList.value) {
|
||||||
|
const quantity = Number(item.quantity || 0);
|
||||||
|
if (Number.isFinite(quantity)) {
|
||||||
|
total += quantity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getPackageQuantityText(total.toFixed(3));
|
||||||
|
});
|
||||||
|
const productSummaryText = computed(() => `共 ${itemList.value.length} 项 · 总数量 ${totalProductQuantity.value}`);
|
||||||
|
|
||||||
|
function getProductText(item: OrderFulfillmentItem): string {
|
||||||
|
const productName = item.productNameSnapshot || "未命名产品";
|
||||||
|
const quantity = getPackageQuantityText(item.quantity);
|
||||||
|
const unit = item.unitSnapshot ? ` ${item.unitSnapshot}` : "";
|
||||||
|
return `${productName} × ${quantity}${unit}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUserName(user: OrderFulfillment["operator"], userId: string | undefined, fallback: string): string {
|
||||||
|
return user?.nick || user?.name || userId || fallback;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.fulfillment-cell {
|
||||||
|
gap: .5rem;
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
background: var(--td-bg-color-container);
|
||||||
|
flex-direction: column;
|
||||||
|
border-radius: 1rem;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
gap: .5rem;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 3.5rem;
|
||||||
|
height: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
gap: .5rem;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.customer-status {
|
||||||
|
gap: .5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.customer {
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
color: var(--td-text-color-secondary);
|
||||||
|
font-size: .75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.product {
|
||||||
|
gap: .5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
.items {
|
||||||
|
flex: 1;
|
||||||
|
gap: .35rem;
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
scrollbar-width: none;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
|
:deep(.t-tag) {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary {
|
||||||
|
color: var(--td-text-color-secondary);
|
||||||
|
font-size: .75rem;
|
||||||
|
text-align: right;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.people-actions {
|
||||||
|
gap: .75rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.person {
|
||||||
|
gap: .25rem;
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
font-size: .75rem;
|
||||||
|
align-items: baseline;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: var(--td-text-color-secondary);
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
max-width: 10rem;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
--td-button-border-radius: .5rem;
|
||||||
|
|
||||||
|
gap: .5rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
|
|
||||||
|
.t-button {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.fulfillment-cell .avatar .t-image__img) {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html.theme-dark) .fulfillment-cell {
|
||||||
|
.fallback {
|
||||||
|
background: #115e59;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Attachment, Model, PageResult, User } from "timi-web-api";
|
import type { Attachment, Model, PageResult, User } from "timi-web-api";
|
||||||
|
import type { Customer } from "@/types/Customer";
|
||||||
|
|
||||||
export type FulfillmentType = "PACKAGE_ENTITLEMENT" | "DIRECT_PRODUCT";
|
export type FulfillmentType = "PACKAGE_ENTITLEMENT" | "DIRECT_PRODUCT";
|
||||||
export type FulfillmentStatus = "WAITING_STOCK" | "PENDING" | "VERIFIED" | "REJECTED" | "CANCELLED" | "REVOKED";
|
export type FulfillmentStatus = "WAITING_STOCK" | "PENDING" | "VERIFIED" | "REJECTED" | "CANCELLED" | "REVOKED";
|
||||||
@@ -28,6 +29,7 @@ export type OrderFulfillment = {
|
|||||||
status?: FulfillmentStatus;
|
status?: FulfillmentStatus;
|
||||||
requestNo?: string;
|
requestNo?: string;
|
||||||
operatorUserId?: string;
|
operatorUserId?: string;
|
||||||
|
customer?: Customer;
|
||||||
deliveredAt?: number;
|
deliveredAt?: number;
|
||||||
verifierUserId?: string;
|
verifierUserId?: string;
|
||||||
verifiedAt?: number;
|
verifiedAt?: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user