feat: 订单功能完善
This commit is contained in:
parent
8142e8b078
commit
b40d49998c
45
pages/order/components/OrderCard/InfoRow.vue
Normal file
45
pages/order/components/OrderCard/InfoRow.vue
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="label">{{ label }}:</text>
|
||||||
|
<text class="value">{{ value }}</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { defineProps } from "vue";
|
||||||
|
|
||||||
|
// Props
|
||||||
|
const props = defineProps({
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: [String, Number],
|
||||||
|
required: true,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.info-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666666;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
104
pages/order/components/OrderCard/OrderCardContent.vue
Normal file
104
pages/order/components/OrderCard/OrderCardContent.vue
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<template>
|
||||||
|
<view class="card-content">
|
||||||
|
<!-- 动态渲染信息行 -->
|
||||||
|
<InfoRow
|
||||||
|
v-for="item in displayItems"
|
||||||
|
:key="item.label"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { defineProps, computed } from "vue";
|
||||||
|
import InfoRow from "./InfoRow.vue";
|
||||||
|
|
||||||
|
// 订单类型常量
|
||||||
|
const ORDER_TYPES = {
|
||||||
|
HOTEL: "0", // 酒店订单
|
||||||
|
TICKET: "1", // 门票订单
|
||||||
|
OTHER: "2", // 其他订单
|
||||||
|
};
|
||||||
|
|
||||||
|
// 标签常量
|
||||||
|
const LABELS = {
|
||||||
|
ORDER_ID: "订单编号",
|
||||||
|
CHECK_IN_TIME: "入住时间",
|
||||||
|
VISITOR_NAME: "游客姓名",
|
||||||
|
CONTACT_PHONE: "联系电话",
|
||||||
|
QUANTITY: "份数",
|
||||||
|
CREATE_TIME: "创建时间",
|
||||||
|
CONTACT_GUEST: "联系房客",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Props
|
||||||
|
const props = defineProps({
|
||||||
|
orderData: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: () => ({
|
||||||
|
orderType: undefined,
|
||||||
|
orderId: "",
|
||||||
|
checkInTime: "",
|
||||||
|
visitorName: "",
|
||||||
|
contactPhone: "",
|
||||||
|
userName: "",
|
||||||
|
userPhone: "",
|
||||||
|
commodityAmount: 0,
|
||||||
|
createTime: "",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 格式化份数
|
||||||
|
const formatQuantity = (amount) => {
|
||||||
|
return `${Math.floor(amount || 0)}份`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 计算显示项目
|
||||||
|
const displayItems = computed(() => {
|
||||||
|
const { orderData } = props;
|
||||||
|
const { orderType } = orderData;
|
||||||
|
|
||||||
|
// 工单情况:orderType 为 undefined
|
||||||
|
if (orderType === undefined) {
|
||||||
|
return [
|
||||||
|
{ label: LABELS.CREATE_TIME, value: orderData.createTime },
|
||||||
|
{ label: LABELS.CONTACT_GUEST, value: orderData.userName },
|
||||||
|
{ label: LABELS.CONTACT_PHONE, value: orderData.userPhone },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订单情况:根据 orderType 返回不同的显示项
|
||||||
|
switch (orderType) {
|
||||||
|
case ORDER_TYPES.HOTEL:
|
||||||
|
return [
|
||||||
|
{ label: LABELS.ORDER_ID, value: orderData.orderId },
|
||||||
|
{ label: LABELS.CHECK_IN_TIME, value: orderData.checkInTime },
|
||||||
|
{ label: LABELS.VISITOR_NAME, value: orderData.visitorName },
|
||||||
|
{ label: LABELS.CONTACT_PHONE, value: orderData.contactPhone },
|
||||||
|
];
|
||||||
|
|
||||||
|
case ORDER_TYPES.TICKET:
|
||||||
|
case ORDER_TYPES.OTHER:
|
||||||
|
return [
|
||||||
|
{ label: LABELS.ORDER_ID, value: orderData.orderId },
|
||||||
|
{
|
||||||
|
label: LABELS.QUANTITY,
|
||||||
|
value: formatQuantity(orderData.commodityAmount),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
default:
|
||||||
|
// 兜底情况,返回空数组
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.card-content {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
109
pages/order/components/OrderCard/README.md
Normal file
109
pages/order/components/OrderCard/README.md
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# OrderCard 组件
|
||||||
|
|
||||||
|
订单卡片组件,用于显示订单和工单信息。
|
||||||
|
|
||||||
|
## 组件结构
|
||||||
|
|
||||||
|
```
|
||||||
|
OrderCard/
|
||||||
|
├── index.vue # 主组件
|
||||||
|
├── OrderCardContent.vue # 卡片内容组件
|
||||||
|
├── InfoRow.vue # 信息行组件
|
||||||
|
├── images/ # 图片资源
|
||||||
|
├── styles/ # 样式文件
|
||||||
|
└── README.md # 说明文档
|
||||||
|
```
|
||||||
|
|
||||||
|
## 组件说明
|
||||||
|
|
||||||
|
### OrderCard (主组件)
|
||||||
|
- 负责整体布局和事件处理
|
||||||
|
- 包含卡片头部、分割线、内容区域和操作区域
|
||||||
|
- 处理点击、呼叫等交互事件
|
||||||
|
|
||||||
|
### OrderCardContent (内容组件)
|
||||||
|
- 负责根据 `orderType` 动态渲染不同的内容
|
||||||
|
- 支持订单类型(0-酒店订单,1-门票订单,2-其他订单)和工单类型
|
||||||
|
- 使用条件渲染显示对应的信息字段
|
||||||
|
|
||||||
|
### InfoRow (信息行组件)
|
||||||
|
- 可复用的信息展示组件
|
||||||
|
- 统一的标签和值的显示格式
|
||||||
|
- 支持字符串和数字类型的值
|
||||||
|
|
||||||
|
## 使用方式
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<OrderCard
|
||||||
|
:order-data="orderData"
|
||||||
|
@click="handleCardClick"
|
||||||
|
@call="handleCall"
|
||||||
|
@complete="handleComplete"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import OrderCard from '@/pages/order/components/OrderCard/index.vue'
|
||||||
|
|
||||||
|
const orderData = {
|
||||||
|
id: '123',
|
||||||
|
commodityName: '订单名称',
|
||||||
|
orderType: 0, // 0-酒店订单, 1-门票订单, 2-其他订单, undefined-工单
|
||||||
|
orderNumber: 'ORD123456',
|
||||||
|
checkInTime: '2024-01-01',
|
||||||
|
visitorName: '张三',
|
||||||
|
contactPhone: '13800138000',
|
||||||
|
quantity: 2,
|
||||||
|
createTime: '2024-01-01 10:00:00',
|
||||||
|
orderStatus: '1',
|
||||||
|
status: 'pending'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
### orderData (Object)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 | 必填 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| id | String | 订单ID | 是 |
|
||||||
|
| commodityName | String | 商品名称 | 是 |
|
||||||
|
| orderType | Number/undefined | 订单类型:0-酒店订单,1-门票订单,2-其他订单,undefined-工单 | 否 |
|
||||||
|
| orderNumber | String | 订单编号 | 否 |
|
||||||
|
| checkInTime | String | 入住时间(orderType=0时使用) | 否 |
|
||||||
|
| visitorName | String | 游客姓名/联系房客 | 否 |
|
||||||
|
| contactPhone | String | 联系电话 | 否 |
|
||||||
|
| quantity | Number | 份数(orderType=1,2时使用) | 否 |
|
||||||
|
| createTime | String | 创建时间(工单时使用) | 否 |
|
||||||
|
| orderStatus | String | 订单状态 | 否 |
|
||||||
|
| status | String | 状态 | 否 |
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
| 事件名 | 说明 | 参数 |
|
||||||
|
|--------|------|------|
|
||||||
|
| click | 卡片点击事件 | orderData |
|
||||||
|
| call | 呼叫事件 | orderData |
|
||||||
|
| complete | 完成事件 | orderData |
|
||||||
|
|
||||||
|
## 显示逻辑
|
||||||
|
|
||||||
|
### 订单类型 (orderType !== undefined)
|
||||||
|
|
||||||
|
- **orderType = 0 (酒店订单)**:显示订单编号、入住时间、游客姓名、联系电话
|
||||||
|
- **orderType = 1 (门票订单)**:显示订单编号、份数
|
||||||
|
- **orderType = 2 (其他订单)**:显示订单编号、份数
|
||||||
|
|
||||||
|
### 工单类型 (orderType === undefined)
|
||||||
|
|
||||||
|
显示创建时间、联系房客、联系电话
|
||||||
|
|
||||||
|
## 优势
|
||||||
|
|
||||||
|
1. **可读性**:组件职责单一,代码结构清晰
|
||||||
|
2. **可维护性**:组件化拆分,便于独立维护和测试
|
||||||
|
3. **可复用性**:InfoRow 组件可在其他地方复用
|
||||||
|
4. **健壮性**:类型检查和默认值处理
|
||||||
|
5. **扩展性**:新增订单类型只需修改 OrderCardContent 组件
|
||||||
@ -3,15 +3,20 @@
|
|||||||
<!-- 卡片头部 -->
|
<!-- 卡片头部 -->
|
||||||
<view class="card-header">
|
<view class="card-header">
|
||||||
<view class="status-info">
|
<view class="status-info">
|
||||||
<image class="status-icon" :src="ICON_MAP[orderData.orderType]"></image>
|
<image class="status-icon" :src="getStatusIcon()"></image>
|
||||||
<view class="order-title">{{ orderData.commodityName }}</view>
|
<view class="order-title">
|
||||||
|
{{ orderData.workOrderTypeName || orderData.commodityName }}
|
||||||
|
</view>
|
||||||
<image class="arrow-icon" src="./images/arrow.png"></image>
|
<image class="arrow-icon" src="./images/arrow.png"></image>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
v-if="orderData.status !== 'pending'"
|
v-if="orderData.status !== 'pending'"
|
||||||
:class="['status-tag', `tag-${orderData.orderStatus}`]"
|
:class="[
|
||||||
|
'status-tag',
|
||||||
|
`tag-${orderData.orderStatus || orderData.workOrderStatus}`,
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
{{ getStatusText(orderData.orderStatus) }}
|
{{ getStatusText(orderData.orderStatus || orderData.workOrderStatus) }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -19,31 +24,19 @@
|
|||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<!-- 卡片内容 -->
|
<!-- 卡片内容 -->
|
||||||
<view class="card-content">
|
<OrderCardContent :order-data="orderData" />
|
||||||
<view class="info-row">
|
|
||||||
<text class="label">创建时间:</text>
|
|
||||||
<text class="value">{{ orderData.createTime }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="info-row">
|
|
||||||
<text class="label">联系房客:</text>
|
|
||||||
<text class="value">{{ orderData.visitorName }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="info-row">
|
|
||||||
<text class="label">联系电话:</text>
|
|
||||||
<text class="value">{{ orderData.contactPhone }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 操作区域 -->
|
<!-- 操作区域 -->
|
||||||
<view v-if="orderData.status === 'pending'" class="action-area">
|
<view v-if="shouldShowActionArea()" class="action-area">
|
||||||
<button class="action-btn" @click.stop="handleCall">立即呼叫</button>
|
<button class="action-btn" @click.stop="handleCall">立即呼叫</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineProps } from "vue";
|
import { defineProps, defineExpose } from "vue";
|
||||||
import Divider from "@/components/Divider/index.vue";
|
import Divider from "@/components/Divider/index.vue";
|
||||||
|
import OrderCardContent from "./OrderCardContent.vue";
|
||||||
import serviceIcon from "./images/service.png";
|
import serviceIcon from "./images/service.png";
|
||||||
import ticketIcon from "./images/ticket.png";
|
import ticketIcon from "./images/ticket.png";
|
||||||
import hotelIcon from "./images/hotel.png";
|
import hotelIcon from "./images/hotel.png";
|
||||||
@ -55,11 +48,17 @@ const props = defineProps({
|
|||||||
required: true,
|
required: true,
|
||||||
default: () => ({
|
default: () => ({
|
||||||
id: "",
|
id: "",
|
||||||
title: "",
|
workOrderTypeName: "",
|
||||||
createTime: "",
|
createTime: "",
|
||||||
contactName: "",
|
contactName: "",
|
||||||
contactPhone: "",
|
contactPhone: "",
|
||||||
orderStatus: "0", // pending-待处理, completed-已完成, cancelled-已取消
|
orderStatus: "0", // pending-待处理, completed-已完成, cancelled-已取消
|
||||||
|
orderType: undefined, // 0-酒店订单, 1-门票订单, 2-其他订单, undefined-工单
|
||||||
|
orderNumber: "", // 订单编号
|
||||||
|
checkInTime: "", // 入住时间
|
||||||
|
visitorName: "", // 游客姓名
|
||||||
|
commodityAmount: 0, // 份数
|
||||||
|
workOrderStatus: 0, // 工单状态:0-待处理, 1-已完成
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -69,23 +68,53 @@ const emit = defineEmits(["click", "call", "complete"]);
|
|||||||
|
|
||||||
// 图标映射
|
// 图标映射
|
||||||
const ICON_MAP = {
|
const ICON_MAP = {
|
||||||
0: serviceIcon,
|
0: hotelIcon, // 酒店订单
|
||||||
1: ticketIcon,
|
1: ticketIcon, // 门票订单
|
||||||
2: hotelIcon,
|
2: hotelIcon, // 其他订单
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取状态图标
|
||||||
|
const getStatusIcon = () => {
|
||||||
|
// 工单情况:orderType 为 undefined
|
||||||
|
if (props.orderData.orderType === undefined) {
|
||||||
|
return serviceIcon;
|
||||||
|
}
|
||||||
|
// 订单情况:根据 orderType 返回对应图标
|
||||||
|
return ICON_MAP[props.orderData.orderType] || serviceIcon;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 判断是否显示操作区域
|
||||||
|
const shouldShowActionArea = () => {
|
||||||
|
// 工单情况:orderType 为 undefined,且 workOrderStatus = 0 时显示
|
||||||
|
if (props.orderData.orderType === undefined) {
|
||||||
|
return props.orderData.workOrderStatus === "0";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取状态文本
|
// 获取状态文本
|
||||||
const getStatusText = (status) => {
|
const getStatusText = (status) => {
|
||||||
const statusMap = {
|
// 工单情况:orderType 为 undefined
|
||||||
|
if (props.orderData.orderType === undefined) {
|
||||||
|
const workOrderStatusMap = {
|
||||||
|
0: "待接单",
|
||||||
|
1: "处理中",
|
||||||
|
2: "已完成",
|
||||||
|
3: "已关闭",
|
||||||
|
};
|
||||||
|
return workOrderStatusMap[status] || "未知状态";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订单情况:orderType 有值
|
||||||
|
const orderStatusMap = {
|
||||||
0: "待支付",
|
0: "待支付",
|
||||||
1: "待确认",
|
1: "待确认",
|
||||||
2: "待使用",
|
2: "待使用",
|
||||||
3: "已取消",
|
3: "已取消",
|
||||||
4: "已退款",
|
4: "退款中",
|
||||||
5: "已退款",
|
5: "已推荐",
|
||||||
6: "已完成",
|
6: "已完成",
|
||||||
};
|
};
|
||||||
return statusMap[status] || "未知状态";
|
return orderStatusMap[status] || "未知状态";
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理卡片点击
|
// 处理卡片点击
|
||||||
@ -98,11 +127,6 @@ const handleCall = () => {
|
|||||||
emit("call", props.orderData);
|
emit("call", props.orderData);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理完成
|
|
||||||
const handleComplete = () => {
|
|
||||||
emit("complete", props.orderData);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 暴露方法
|
// 暴露方法
|
||||||
defineExpose({
|
defineExpose({
|
||||||
getStatusText,
|
getStatusText,
|
||||||
|
|||||||
@ -55,8 +55,8 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
||||||
&.tag-0 {
|
&.tag-0 {
|
||||||
color: #00A6FF;
|
color: #00a6ff;
|
||||||
border: 1px solid #00A6FF;
|
border: 1px solid #00a6ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.tag-1 {
|
&.tag-1 {
|
||||||
@ -65,8 +65,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.tag-2 {
|
&.tag-2 {
|
||||||
color: #40AE36;
|
color: #40ae36;
|
||||||
border: 1px solid #40AE36;
|
border: 1px solid #40ae36;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.tag-3 {
|
&.tag-3 {
|
||||||
@ -75,8 +75,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.tag-4 {
|
&.tag-4 {
|
||||||
color: #0256FF;
|
color: #0256ff;
|
||||||
border: 1px solid #0256FF;
|
border: 1px solid #0256ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.tag-5 {
|
&.tag-5 {
|
||||||
@ -85,38 +85,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.tag-6 {
|
&.tag-6 {
|
||||||
color: #FD8702;
|
color: #fd8702;
|
||||||
border: 1px solid #FD8702;
|
border: 1px solid #fd8702;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-content {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666666;
|
|
||||||
flex-shrink: 0;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #333333;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-area {
|
.action-area {
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,12 +98,18 @@ const handleTabChange = ({ index }) => {
|
|||||||
const handleOrderClick = (orderData) => {
|
const handleOrderClick = (orderData) => {
|
||||||
console.log("订单点击:", orderData);
|
console.log("订单点击:", orderData);
|
||||||
// 这里可以添加订单详情跳转逻辑
|
// 这里可以添加订单详情跳转逻辑
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/order/detail?id=${orderData.id}`,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理订单呼叫
|
// 处理订单呼叫
|
||||||
const handleOrderCall = (orderData) => {
|
const handleOrderCall = (orderData) => {
|
||||||
console.log("订单呼叫:", orderData);
|
console.log("订单呼叫:", orderData);
|
||||||
// 这里可以添加呼叫逻辑
|
// 这里可以添加呼叫逻辑
|
||||||
|
uni.makePhoneCall({
|
||||||
|
phoneNumber: orderData.contactPhone,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理订单完成
|
// 处理订单完成
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user