|
@@ -30,24 +30,18 @@
|
|
|
</view>
|
|
</view>
|
|
|
<view class="stat-item">
|
|
<view class="stat-item">
|
|
|
<text class="stat-value">{{ stats.wechatAmount || '0.00' }}</text>
|
|
<text class="stat-value">{{ stats.wechatAmount || '0.00' }}</text>
|
|
|
- <text class="stat-label">微信总金额</text>
|
|
|
|
|
|
|
+ <text class="stat-label">微信支付</text>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="stat-item">
|
|
<view class="stat-item">
|
|
|
<text class="stat-value">{{ stats.alipayAmount || '0.00' }}</text>
|
|
<text class="stat-value">{{ stats.alipayAmount || '0.00' }}</text>
|
|
|
- <text class="stat-label">支付宝总金额</text>
|
|
|
|
|
|
|
+ <text class="stat-label">支付宝</text>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="stat-item">
|
|
<view class="stat-item">
|
|
|
<text class="stat-value">{{ stats.otherAmount || '0.00' }}</text>
|
|
<text class="stat-value">{{ stats.otherAmount || '0.00' }}</text>
|
|
|
- <text class="stat-label">其他</text>
|
|
|
|
|
|
|
+ <text class="stat-label">其他支付</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
- <!-- 说明文字 -->
|
|
|
|
|
- <view class="tips-section">
|
|
|
|
|
- <text class="tips-text">已支付订单:消费者支付完成的订单;</text>
|
|
|
|
|
- <text class="tips-text">其他订单:包括未支付订单、刷脸支付、余额支付、扶贫、API商家、刷卡等订单;</text>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
<!-- 列表头部 -->
|
|
<!-- 列表头部 -->
|
|
|
<view class="list-header">
|
|
<view class="list-header">
|
|
|
<text class="list-info">{{ dateRangeShortText }} 共{{ total }}条</text>
|
|
<text class="list-info">{{ dateRangeShortText }} 共{{ total }}条</text>
|
|
@@ -68,14 +62,14 @@
|
|
|
<!-- 头部 -->
|
|
<!-- 头部 -->
|
|
|
<view class="card-header">
|
|
<view class="card-header">
|
|
|
<text class="order-time">{{ formatDateTime(order.createTime) }}</text>
|
|
<text class="order-time">{{ formatDateTime(order.createTime) }}</text>
|
|
|
- <text class="order-status" :style="{ color: getStatusColor(order.status) }">
|
|
|
|
|
|
|
+ <text class="order-status" :class="getStatusClass(order.status)">
|
|
|
{{ order.statusLabel || getStatusText(order.status) }}
|
|
{{ order.statusLabel || getStatusText(order.status) }}
|
|
|
</text>
|
|
</text>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 商品区域 -->
|
|
<!-- 商品区域 -->
|
|
|
<view class="card-product">
|
|
<view class="card-product">
|
|
|
- <image class="product-img" :src="getFirstProductPic(order)" mode="aspectFill" />
|
|
|
|
|
|
|
+ <image class="product-img" :src="getProductPic(order)" mode="aspectFill" />
|
|
|
<view class="product-right">
|
|
<view class="product-right">
|
|
|
<text class="product-amount">¥{{ formatMoney(order.paidAmount || order.totalAmount) }}</text>
|
|
<text class="product-amount">¥{{ formatMoney(order.paidAmount || order.totalAmount) }}</text>
|
|
|
<text class="product-count">共{{ getProductCount(order) }}件</text>
|
|
<text class="product-count">共{{ getProductCount(order) }}件</text>
|
|
@@ -85,19 +79,19 @@
|
|
|
<!-- 信息区域 -->
|
|
<!-- 信息区域 -->
|
|
|
<view class="card-info">
|
|
<view class="card-info">
|
|
|
<view class="info-line">
|
|
<view class="info-line">
|
|
|
- <text class="info-label">订单编号:</text>
|
|
|
|
|
|
|
+ <text class="info-label">订单编号</text>
|
|
|
<text class="info-value">{{ order.orderNo }}</text>
|
|
<text class="info-value">{{ order.orderNo }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="info-line">
|
|
<view class="info-line">
|
|
|
- <text class="info-label">设备信息:</text>
|
|
|
|
|
|
|
+ <text class="info-label">设备信息</text>
|
|
|
<text class="info-value">{{ order.deviceId }}</text>
|
|
<text class="info-value">{{ order.deviceId }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
- <view class="info-line">
|
|
|
|
|
- <text class="info-label">门店名称:</text>
|
|
|
|
|
- <text class="info-value">{{ order.shopName || '-' }}</text>
|
|
|
|
|
|
|
+ <view class="info-line" v-if="order.shopName">
|
|
|
|
|
+ <text class="info-label">门店名称</text>
|
|
|
|
|
+ <text class="info-value">{{ order.shopName }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="info-line">
|
|
<view class="info-line">
|
|
|
- <text class="info-label">支付方式:</text>
|
|
|
|
|
|
|
+ <text class="info-label">支付方式</text>
|
|
|
<text class="info-value">{{ order.payType || '-' }}</text>
|
|
<text class="info-value">{{ order.payType || '-' }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
@@ -105,7 +99,7 @@
|
|
|
<!-- 操作按钮 -->
|
|
<!-- 操作按钮 -->
|
|
|
<view class="card-action">
|
|
<view class="card-action">
|
|
|
<view class="view-btn" @click.stop="goDetail(order.id)">
|
|
<view class="view-btn" @click.stop="goDetail(order.id)">
|
|
|
- <text>查看</text>
|
|
|
|
|
|
|
+ <text>查看详情</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
@@ -157,12 +151,25 @@
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { ref, onMounted, computed } from 'vue';
|
|
import { ref, onMounted, computed } from 'vue';
|
|
|
-import { logger } from '@/utils/logger';
|
|
|
|
|
import NavBar from '@/components/NavBar.vue';
|
|
import NavBar from '@/components/NavBar.vue';
|
|
|
import CustomTabBar from '@/components/CustomTabBar.vue';
|
|
import CustomTabBar from '@/components/CustomTabBar.vue';
|
|
|
import { getOrderList, getOrderStats } from '@/api/order';
|
|
import { getOrderList, getOrderStats } from '@/api/order';
|
|
|
-import { OrderStatusText, OrderStatusColor } from '@/utils/constants';
|
|
|
|
|
-import { formatMoney as formatMoneyUtil, showToast } from '@/utils/common';
|
|
|
|
|
|
|
+import { OrderStatusText } from '@/utils/constants';
|
|
|
|
|
+import { formatMoney as formatMoneyUtil } from '@/utils/common';
|
|
|
|
|
+
|
|
|
|
|
+interface OrderItem {
|
|
|
|
|
+ id: string;
|
|
|
|
|
+ orderNo: string;
|
|
|
|
|
+ status: number;
|
|
|
|
|
+ statusLabel?: string;
|
|
|
|
|
+ paidAmount?: number;
|
|
|
|
|
+ totalAmount?: number;
|
|
|
|
|
+ createTime: string;
|
|
|
|
|
+ deviceId?: string;
|
|
|
|
|
+ shopName?: string;
|
|
|
|
|
+ payType?: string;
|
|
|
|
|
+ products?: { pic?: string; productNum?: number }[];
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
const tabs = [
|
|
const tabs = [
|
|
|
{ key: 'sales', label: '销售订单', params: { status: 2 } },
|
|
{ key: 'sales', label: '销售订单', params: { status: 2 } },
|
|
@@ -172,7 +179,7 @@ const tabs = [
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
const currentTab = ref('sales');
|
|
const currentTab = ref('sales');
|
|
|
-const orderList = ref<any[]>([]);
|
|
|
|
|
|
|
+const orderList = ref<OrderItem[]>([]);
|
|
|
const loading = ref(false);
|
|
const loading = ref(false);
|
|
|
const hasMore = ref(true);
|
|
const hasMore = ref(true);
|
|
|
const page = ref(1);
|
|
const page = ref(1);
|
|
@@ -192,8 +199,7 @@ const startDate = ref(formatDateStr(thirtyDaysAgo));
|
|
|
const endDate = ref(formatDateStr(today));
|
|
const endDate = ref(formatDateStr(today));
|
|
|
const showDatePicker = ref(false);
|
|
const showDatePicker = ref(false);
|
|
|
|
|
|
|
|
-// 统计
|
|
|
|
|
-const stats = ref<any>({});
|
|
|
|
|
|
|
+const stats = ref<Record<string, string | number>>({});
|
|
|
|
|
|
|
|
const dateRangeFullText = computed(() => {
|
|
const dateRangeFullText = computed(() => {
|
|
|
return `${startDate.value} 00:00:00 - ${endDate.value} 23:59:59`;
|
|
return `${startDate.value} 00:00:00 - ${endDate.value} 23:59:59`;
|
|
@@ -205,11 +211,16 @@ const dateRangeShortText = computed(() => {
|
|
|
|
|
|
|
|
const formatMoney = formatMoneyUtil;
|
|
const formatMoney = formatMoneyUtil;
|
|
|
|
|
|
|
|
-const getStatusText = (status: number) => OrderStatusText[status] || '未知';
|
|
|
|
|
|
|
+const getStatusText = (status: number): string => OrderStatusText[status] || '未知';
|
|
|
|
|
|
|
|
-const getStatusColor = (status: number) => OrderStatusColor[status] || '$text-color-muted';
|
|
|
|
|
|
|
+const getStatusClass = (status: number): string => {
|
|
|
|
|
+ if (status === 2) return 'completed';
|
|
|
|
|
+ if (status === 1) return 'pending';
|
|
|
|
|
+ if (status === 0) return 'cancelled';
|
|
|
|
|
+ return 'closed';
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
-const formatDateTime = (datetime: string) => {
|
|
|
|
|
|
|
+const formatDateTime = (datetime: string): string => {
|
|
|
if (!datetime) return '-';
|
|
if (!datetime) return '-';
|
|
|
if (datetime.length > 16) {
|
|
if (datetime.length > 16) {
|
|
|
return datetime.substring(0, 16);
|
|
return datetime.substring(0, 16);
|
|
@@ -217,20 +228,22 @@ const formatDateTime = (datetime: string) => {
|
|
|
return datetime;
|
|
return datetime;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const getFirstProductPic = (_order?: any) => {
|
|
|
|
|
- return '/static/images/default-product.png';
|
|
|
|
|
|
|
+const getProductPic = (order: OrderItem): string => {
|
|
|
|
|
+ const first = order.products?.[0];
|
|
|
|
|
+ return first?.pic || '/static/images/default-product.png';
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const getProductCount = (_order?: any) => {
|
|
|
|
|
- return 1;
|
|
|
|
|
|
|
+const getProductCount = (order: OrderItem): number => {
|
|
|
|
|
+ if (!order.products || order.products.length === 0) return 0;
|
|
|
|
|
+ return order.products.reduce((sum, p) => sum + (p.productNum || 0), 0);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const loadStats = async () => {
|
|
const loadStats = async () => {
|
|
|
try {
|
|
try {
|
|
|
const res = await getOrderStats({ startDate: startDate.value, endDate: endDate.value });
|
|
const res = await getOrderStats({ startDate: startDate.value, endDate: endDate.value });
|
|
|
stats.value = res || {};
|
|
stats.value = res || {};
|
|
|
- } catch (error) {
|
|
|
|
|
- logger.warn('加载统计失败', error);
|
|
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ // stats are non-critical
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -238,7 +251,7 @@ const loadOrders = async () => {
|
|
|
loading.value = true;
|
|
loading.value = true;
|
|
|
try {
|
|
try {
|
|
|
const tab = tabs.find(t => t.key === currentTab.value);
|
|
const tab = tabs.find(t => t.key === currentTab.value);
|
|
|
- const params: any = {
|
|
|
|
|
|
|
+ const params: Record<string, unknown> = {
|
|
|
page: page.value,
|
|
page: page.value,
|
|
|
pageSize,
|
|
pageSize,
|
|
|
startDate: startDate.value,
|
|
startDate: startDate.value,
|
|
@@ -260,8 +273,8 @@ const loadOrders = async () => {
|
|
|
|
|
|
|
|
total.value = res.total || 0;
|
|
total.value = res.total || 0;
|
|
|
hasMore.value = orderList.value.length < total.value;
|
|
hasMore.value = orderList.value.length < total.value;
|
|
|
- } catch (error) {
|
|
|
|
|
- logger.warn('加载订单失败', error);
|
|
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ // fail silently, list remains as-is
|
|
|
} finally {
|
|
} finally {
|
|
|
loading.value = false;
|
|
loading.value = false;
|
|
|
}
|
|
}
|
|
@@ -285,11 +298,11 @@ const goDetail = (orderId: string) => {
|
|
|
uni.navigateTo({ url: `/pages/orders/detail?id=${orderId}` });
|
|
uni.navigateTo({ url: `/pages/orders/detail?id=${orderId}` });
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const onStartDateChange = (e: any) => {
|
|
|
|
|
|
|
+const onStartDateChange = (e: { detail: { value: string } }) => {
|
|
|
startDate.value = e.detail.value;
|
|
startDate.value = e.detail.value;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const onEndDateChange = (e: any) => {
|
|
|
|
|
|
|
+const onEndDateChange = (e: { detail: { value: string } }) => {
|
|
|
endDate.value = e.detail.value;
|
|
endDate.value = e.detail.value;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -308,19 +321,23 @@ onMounted(() => {
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
|
|
|
+$font-stack: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', system-ui, sans-serif;
|
|
|
|
|
+
|
|
|
.page {
|
|
.page {
|
|
|
- min-height: 100vh;
|
|
|
|
|
|
|
+ height: 100vh;
|
|
|
background: $bg-color-page;
|
|
background: $bg-color-page;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
- padding-bottom: 200rpx;
|
|
|
|
|
|
|
+ overflow-x: hidden;
|
|
|
|
|
+ padding-bottom: env(safe-area-inset-bottom);
|
|
|
|
|
+ font-family: $font-stack;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* Tab 栏 */
|
|
|
|
|
|
|
+// ====== Tab bar ======
|
|
|
.tab-bar {
|
|
.tab-bar {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
background: $bg-color-card;
|
|
background: $bg-color-card;
|
|
|
- border-bottom: 1rpx solid $border-color;
|
|
|
|
|
|
|
+ border-bottom: 1rpx solid $border-color-light;
|
|
|
|
|
|
|
|
.tab-item {
|
|
.tab-item {
|
|
|
flex: 1;
|
|
flex: 1;
|
|
@@ -328,11 +345,11 @@ onMounted(() => {
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
- padding: 24rpx 0 16rpx;
|
|
|
|
|
|
|
+ padding: $spacing-3 0 $spacing-2;
|
|
|
position: relative;
|
|
position: relative;
|
|
|
|
|
|
|
|
text {
|
|
text {
|
|
|
- font-size: 28rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-base;
|
|
|
color: $text-color-secondary;
|
|
color: $text-color-secondary;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -356,22 +373,22 @@ onMounted(() => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 时间筛选 */
|
|
|
|
|
|
|
+// ====== Time filter ======
|
|
|
.time-filter {
|
|
.time-filter {
|
|
|
- padding: 16rpx 24rpx;
|
|
|
|
|
|
|
+ padding: $spacing-2 $spacing-3;
|
|
|
background: $bg-color-card;
|
|
background: $bg-color-card;
|
|
|
|
|
|
|
|
.time-label {
|
|
.time-label {
|
|
|
- font-size: 24rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
color: $text-color-muted;
|
|
color: $text-color-muted;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 统计卡片 */
|
|
|
|
|
|
|
+// ====== Stats bar ======
|
|
|
.stats-bar {
|
|
.stats-bar {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
background: $bg-color-card;
|
|
background: $bg-color-card;
|
|
|
- padding: 20rpx 0;
|
|
|
|
|
|
|
+ padding: $spacing-2 0;
|
|
|
|
|
|
|
|
.stat-item {
|
|
.stat-item {
|
|
|
flex: 1;
|
|
flex: 1;
|
|
@@ -380,98 +397,94 @@ onMounted(() => {
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
|
|
|
|
|
.stat-value {
|
|
.stat-value {
|
|
|
- font-size: 36rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-xl;
|
|
|
font-weight: 700;
|
|
font-weight: 700;
|
|
|
- color: $error-color;
|
|
|
|
|
- margin-bottom: 8rpx;
|
|
|
|
|
|
|
+ color: $text-color-primary;
|
|
|
|
|
+ margin-bottom: $spacing-1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.stat-label {
|
|
.stat-label {
|
|
|
- font-size: 24rpx;
|
|
|
|
|
- color: $text-color-primary;
|
|
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
|
|
+ color: $text-color-muted;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 说明文字 */
|
|
|
|
|
-.tips-section {
|
|
|
|
|
- background: $bg-color-card;
|
|
|
|
|
- padding: 16rpx 24rpx;
|
|
|
|
|
- margin-bottom: 16rpx;
|
|
|
|
|
-
|
|
|
|
|
- .tips-text {
|
|
|
|
|
- display: block;
|
|
|
|
|
- font-size: 22rpx;
|
|
|
|
|
- color: $text-color-muted;
|
|
|
|
|
- line-height: 1.6;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/* 列表头部 */
|
|
|
|
|
|
|
+// ====== List header ======
|
|
|
.list-header {
|
|
.list-header {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
justify-content: space-between;
|
|
justify-content: space-between;
|
|
|
- padding: 16rpx 24rpx;
|
|
|
|
|
|
|
+ padding: $spacing-2 $spacing-3;
|
|
|
|
|
|
|
|
.list-info {
|
|
.list-info {
|
|
|
- font-size: 26rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
color: $text-color-muted;
|
|
color: $text-color-muted;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.filter-btn {
|
|
.filter-btn {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
- padding: 8rpx 16rpx;
|
|
|
|
|
|
|
+ padding: $spacing-1 $spacing-2;
|
|
|
background: $bg-color-card;
|
|
background: $bg-color-card;
|
|
|
- border-radius: 8rpx;
|
|
|
|
|
- font-size: 26rpx;
|
|
|
|
|
|
|
+ border-radius: $radius-sm;
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
color: $text-color-secondary;
|
|
color: $text-color-secondary;
|
|
|
|
|
+
|
|
|
|
|
+ &:active { opacity: 0.7; }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 订单列表 */
|
|
|
|
|
|
|
+// ====== Order list ======
|
|
|
.order-scroll {
|
|
.order-scroll {
|
|
|
flex: 1;
|
|
flex: 1;
|
|
|
height: 0;
|
|
height: 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.order-list {
|
|
.order-list {
|
|
|
- padding: 0 24rpx;
|
|
|
|
|
|
|
+ padding: $spacing-2 $spacing-3;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.order-card {
|
|
.order-card {
|
|
|
background: $bg-color-card;
|
|
background: $bg-color-card;
|
|
|
- border-radius: 12rpx;
|
|
|
|
|
- margin-bottom: 16rpx;
|
|
|
|
|
- padding: 20rpx;
|
|
|
|
|
|
|
+ border-radius: $radius-md;
|
|
|
|
|
+ margin-bottom: $spacing-2;
|
|
|
|
|
+ padding: $spacing-2;
|
|
|
|
|
+ box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
|
|
|
|
+
|
|
|
|
|
+ &:active { opacity: 0.7; }
|
|
|
|
|
|
|
|
.card-header {
|
|
.card-header {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
- margin-bottom: 16rpx;
|
|
|
|
|
|
|
+ margin-bottom: $spacing-2;
|
|
|
|
|
|
|
|
.order-time {
|
|
.order-time {
|
|
|
- font-size: 28rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-base;
|
|
|
color: $text-color-primary;
|
|
color: $text-color-primary;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.order-status {
|
|
.order-status {
|
|
|
- font-size: 28rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
|
|
+
|
|
|
|
|
+ &.completed { color: $success-color; }
|
|
|
|
|
+ &.pending { color: $warning-color; }
|
|
|
|
|
+ &.cancelled { color: $text-color-muted; }
|
|
|
|
|
+ &.closed { color: $text-color-tertiary; }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.card-product {
|
|
.card-product {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
- margin-bottom: 16rpx;
|
|
|
|
|
|
|
+ margin-bottom: $spacing-2;
|
|
|
|
|
|
|
|
.product-img {
|
|
.product-img {
|
|
|
width: 120rpx;
|
|
width: 120rpx;
|
|
|
height: 120rpx;
|
|
height: 120rpx;
|
|
|
- border-radius: 8rpx;
|
|
|
|
|
|
|
+ border-radius: $radius-sm;
|
|
|
background: $bg-color-page;
|
|
background: $bg-color-page;
|
|
|
margin-right: 20rpx;
|
|
margin-right: 20rpx;
|
|
|
}
|
|
}
|
|
@@ -483,34 +496,38 @@ onMounted(() => {
|
|
|
align-items: flex-end;
|
|
align-items: flex-end;
|
|
|
|
|
|
|
|
.product-amount {
|
|
.product-amount {
|
|
|
- font-size: 32rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-lg;
|
|
|
font-weight: 600;
|
|
font-weight: 600;
|
|
|
color: $text-color-primary;
|
|
color: $text-color-primary;
|
|
|
- margin-bottom: 8rpx;
|
|
|
|
|
|
|
+ margin-bottom: $spacing-1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.product-count {
|
|
.product-count {
|
|
|
- font-size: 24rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
color: $text-color-muted;
|
|
color: $text-color-muted;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.card-info {
|
|
.card-info {
|
|
|
- margin-bottom: 16rpx;
|
|
|
|
|
|
|
+ margin-bottom: $spacing-2;
|
|
|
|
|
|
|
|
.info-line {
|
|
.info-line {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
- margin-bottom: 8rpx;
|
|
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: $spacing-1;
|
|
|
|
|
+
|
|
|
|
|
+ &:last-child { margin-bottom: 0; }
|
|
|
|
|
|
|
|
.info-label {
|
|
.info-label {
|
|
|
- font-size: 26rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
color: $text-color-secondary;
|
|
color: $text-color-secondary;
|
|
|
- margin-right: 8rpx;
|
|
|
|
|
|
|
+ margin-right: $spacing-1;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.info-value {
|
|
.info-value {
|
|
|
- font-size: 26rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
color: $text-color-primary;
|
|
color: $text-color-primary;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -521,27 +538,30 @@ onMounted(() => {
|
|
|
justify-content: flex-end;
|
|
justify-content: flex-end;
|
|
|
|
|
|
|
|
.view-btn {
|
|
.view-btn {
|
|
|
- padding: 10rpx 32rpx;
|
|
|
|
|
- border: 1rpx solid $text-color-placeholder;
|
|
|
|
|
- border-radius: 8rpx;
|
|
|
|
|
|
|
+ padding: $spacing-1 $spacing-4;
|
|
|
|
|
+ background: $bg-color-page;
|
|
|
|
|
+ border-radius: $radius-sm;
|
|
|
|
|
+
|
|
|
|
|
+ &:active { opacity: 0.7; }
|
|
|
|
|
|
|
|
text {
|
|
text {
|
|
|
- font-size: 26rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
color: $text-color-secondary;
|
|
color: $text-color-secondary;
|
|
|
|
|
+ font-weight: 500;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 加载状态 */
|
|
|
|
|
|
|
+// ====== Loading ======
|
|
|
.loading-more {
|
|
.loading-more {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
- gap: 12rpx;
|
|
|
|
|
- padding: 32rpx;
|
|
|
|
|
|
|
+ gap: $spacing-1;
|
|
|
|
|
+ padding: $spacing-4;
|
|
|
color: $text-color-muted;
|
|
color: $text-color-muted;
|
|
|
- font-size: 24rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
|
|
|
|
|
.loading-spinner {
|
|
.loading-spinner {
|
|
|
width: 32rpx;
|
|
width: 32rpx;
|
|
@@ -559,8 +579,8 @@ onMounted(() => {
|
|
|
|
|
|
|
|
.no-more {
|
|
.no-more {
|
|
|
text-align: center;
|
|
text-align: center;
|
|
|
- padding: 32rpx;
|
|
|
|
|
- font-size: 24rpx;
|
|
|
|
|
|
|
+ padding: $spacing-4;
|
|
|
|
|
+ font-size: $font-size-sm;
|
|
|
color: $text-color-placeholder;
|
|
color: $text-color-placeholder;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -571,84 +591,83 @@ onMounted(() => {
|
|
|
padding: 100rpx 0;
|
|
padding: 100rpx 0;
|
|
|
|
|
|
|
|
.empty-text {
|
|
.empty-text {
|
|
|
- font-size: 28rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-base;
|
|
|
color: $text-color-muted;
|
|
color: $text-color-muted;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 日期弹窗 */
|
|
|
|
|
|
|
+// ====== Date modal ======
|
|
|
.date-modal {
|
|
.date-modal {
|
|
|
position: fixed;
|
|
position: fixed;
|
|
|
- top: 0;
|
|
|
|
|
- left: 0;
|
|
|
|
|
- right: 0;
|
|
|
|
|
- bottom: 0;
|
|
|
|
|
- background: rgba(0, 0, 0, 0.5);
|
|
|
|
|
|
|
+ inset: 0;
|
|
|
|
|
+ background: rgba(0, 0, 0, 0.45);
|
|
|
z-index: 100;
|
|
z-index: 100;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
- padding: 0 48rpx;
|
|
|
|
|
|
|
+ padding: 0 $spacing-6;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.modal-content {
|
|
.modal-content {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
background: $bg-color-card;
|
|
background: $bg-color-card;
|
|
|
- border-radius: 20rpx;
|
|
|
|
|
|
|
+ border-radius: $radius-xl;
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
.modal-header {
|
|
.modal-header {
|
|
|
- padding: 24rpx;
|
|
|
|
|
- border-bottom: 1rpx solid $bg-color-page;
|
|
|
|
|
|
|
+ padding: $spacing-3;
|
|
|
|
|
+ border-bottom: 1rpx solid $border-color-light;
|
|
|
|
|
|
|
|
.modal-title {
|
|
.modal-title {
|
|
|
- font-size: 32rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-lg;
|
|
|
font-weight: 600;
|
|
font-weight: 600;
|
|
|
color: $text-color-primary;
|
|
color: $text-color-primary;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.modal-body {
|
|
.modal-body {
|
|
|
- padding: 24rpx;
|
|
|
|
|
|
|
+ padding: $spacing-3;
|
|
|
|
|
|
|
|
.date-row {
|
|
.date-row {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
justify-content: space-between;
|
|
justify-content: space-between;
|
|
|
- padding: 20rpx 0;
|
|
|
|
|
- border-bottom: 1rpx solid $bg-color-page;
|
|
|
|
|
|
|
+ padding: $spacing-2 0;
|
|
|
|
|
+ border-bottom: 1rpx solid $border-color-light;
|
|
|
|
|
+
|
|
|
|
|
+ &:last-child { border-bottom: none; }
|
|
|
|
|
|
|
|
text {
|
|
text {
|
|
|
- font-size: 28rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-base;
|
|
|
color: $text-color-primary;
|
|
color: $text-color-primary;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.picker-value {
|
|
.picker-value {
|
|
|
- font-size: 28rpx;
|
|
|
|
|
|
|
+ font-size: $font-size-base;
|
|
|
color: $text-color-primary;
|
|
color: $text-color-primary;
|
|
|
- padding: 8rpx 16rpx;
|
|
|
|
|
|
|
+ padding: $spacing-1 $spacing-2;
|
|
|
background: $bg-color-page;
|
|
background: $bg-color-page;
|
|
|
- border-radius: 8rpx;
|
|
|
|
|
|
|
+ border-radius: $radius-sm;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.modal-footer {
|
|
.modal-footer {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
- padding: 16rpx 24rpx 24rpx;
|
|
|
|
|
- gap: 12rpx;
|
|
|
|
|
|
|
+ padding: $spacing-2 $spacing-3 $spacing-3;
|
|
|
|
|
+ gap: $spacing-1;
|
|
|
|
|
|
|
|
button {
|
|
button {
|
|
|
flex: 1;
|
|
flex: 1;
|
|
|
height: 80rpx;
|
|
height: 80rpx;
|
|
|
- border-radius: 12rpx;
|
|
|
|
|
- font-size: 28rpx;
|
|
|
|
|
|
|
+ line-height: 80rpx;
|
|
|
|
|
+ border-radius: $radius-base;
|
|
|
|
|
+ font-size: $font-size-base;
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
border: none;
|
|
border: none;
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
|
|
|
- &::after {
|
|
|
|
|
- border: none;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ &::after { border: none; }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.btn-cancel {
|
|
.btn-cancel {
|