feat: 新增工单列表
This commit is contained in:
26
src/pages-service/order/components/OrderCard/InfoRow.vue
Normal file
26
src/pages-service/order/components/OrderCard/InfoRow.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<view class="info-row flex items-center mt-8">
|
||||
<text class="label font-size-12 color-99A0AE">{{ label }}:</text>
|
||||
<text class="value flex-full font-size-12 color-99A0AE">{{ 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"></style>
|
||||
@@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<view class="card-content border-box pt-12">
|
||||
<view class="flex items-center justify-between">
|
||||
<view
|
||||
class="left flex-full font-size-14 line-height-20 color-171717 mr-12"
|
||||
>
|
||||
{{ orderData.commodityName }}
|
||||
</view>
|
||||
<view class="right font-size-18 font-bold line-height-20 color-525866">
|
||||
{{ orderData.orderAmt }}
|
||||
</view>
|
||||
</view>
|
||||
<!-- 动态渲染信息行 -->
|
||||
<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 = {
|
||||
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.CHECK_IN_TIME,
|
||||
value:
|
||||
orderData.checkInData?.replace(
|
||||
/(\d{4})-(\d{1,2})-(\d{1,2})/,
|
||||
"$2月$3日"
|
||||
) +
|
||||
"-" +
|
||||
orderData.checkOutData?.replace(
|
||||
/(\d{4})-(\d{1,2})-(\d{1,2})/,
|
||||
"$2月$3日"
|
||||
),
|
||||
},
|
||||
{ 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.QUANTITY,
|
||||
value: formatQuantity(orderData.commodityAmount),
|
||||
},
|
||||
];
|
||||
|
||||
default:
|
||||
// 兜底情况,返回空数组
|
||||
return [];
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.right {
|
||||
&::before {
|
||||
content: "¥";
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,59 @@
|
||||
// 订单类型
|
||||
export const ORDER_TYPE_MAP = {
|
||||
0: [
|
||||
{
|
||||
label: '订单编号',
|
||||
key: 'orderId'
|
||||
},
|
||||
{
|
||||
label: '入住时间',
|
||||
key: 'checkInData'
|
||||
},
|
||||
{
|
||||
label: '游客姓名',
|
||||
key: 'visitorName'
|
||||
},
|
||||
{
|
||||
label: '联系电话',
|
||||
key: 'contactPhone'
|
||||
}
|
||||
],
|
||||
1: [
|
||||
{
|
||||
label: '订单编号',
|
||||
key: 'orderId'
|
||||
},
|
||||
{
|
||||
label: '份数',
|
||||
key: 'commodityAmount'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
label: '订单编号',
|
||||
key: 'orderId'
|
||||
},
|
||||
{
|
||||
label: '份数',
|
||||
key: 'commodityAmount'
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
// 工单类型
|
||||
export const SERVICE_TYPE_MAP = {
|
||||
0: [
|
||||
{
|
||||
label: '创建时间',
|
||||
key: 'createTime'
|
||||
},
|
||||
{
|
||||
label: '联系房客',
|
||||
key: 'userName'
|
||||
},
|
||||
{
|
||||
label: '联系电话',
|
||||
key: 'userPhone'
|
||||
}
|
||||
],
|
||||
}
|
||||
119
src/pages-service/order/components/OrderCard/index.vue
Normal file
119
src/pages-service/order/components/OrderCard/index.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<view
|
||||
class="order-card bg-white border-box p-12 rounded-12 m-12"
|
||||
@click="handleCardClick"
|
||||
>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header flex items-center">
|
||||
<view class="status-info flex items-center flex-full">
|
||||
<image class="status-icon mr-4" :src="getStatusIcon()" />
|
||||
<view class="order-title font-size-14 line-height-20 color-525866">
|
||||
{{ getOrderTypeName() }}
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
v-if="orderData.status !== 'pending'"
|
||||
:class="[
|
||||
'status-tag font-size-12',
|
||||
`tag-${orderData.orderStatus || orderData.workOrderStatus}`,
|
||||
]"
|
||||
>
|
||||
{{ getStatusText(orderData.orderStatus || orderData.workOrderStatus) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<OrderCardContent :order-data="orderData" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps } from "vue";
|
||||
import OrderCardContent from "./OrderCardContent.vue";
|
||||
|
||||
// Props
|
||||
const props = defineProps({
|
||||
orderData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({
|
||||
id: "",
|
||||
workOrderTypeName: "",
|
||||
createTime: "",
|
||||
contactName: "",
|
||||
contactPhone: "",
|
||||
orderStatus: "0", // pending-待处理, completed-已完成, cancelled-已取消
|
||||
orderType: undefined, // 0-酒店订单, 1-门票订单, 2-其他订单, undefined-工单
|
||||
orderNumber: "", // 订单编号
|
||||
checkInTime: "", // 入住时间
|
||||
visitorName: "", // 游客姓名
|
||||
commodityAmount: 0, // 份数
|
||||
workOrderStatus: 0, // 工单状态:0-待处理, 1-已完成
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits(["click", "call"]);
|
||||
|
||||
// 图标映射
|
||||
const ICON_MAP = {
|
||||
0: "https://oss.nianxx.cn/mp/static/version_101/order/room.png", // 酒店订单
|
||||
1: "https://oss.nianxx.cn/mp/static/version_101/order/ticket.png", // 门票订单
|
||||
2: "https://oss.nianxx.cn/mp/static/version_101/order/food.png", // 餐饮
|
||||
};
|
||||
|
||||
// 订单类型映射
|
||||
const ORDER_NAME_MAP = {
|
||||
0: "房间",
|
||||
1: "门票",
|
||||
2: "餐饮",
|
||||
};
|
||||
|
||||
// 获取状态图标
|
||||
const getStatusIcon = () => {
|
||||
// 订单情况:根据 orderType 返回对应图标
|
||||
return ICON_MAP[props.orderData.orderType];
|
||||
};
|
||||
|
||||
// 获取订单类型名称
|
||||
const getOrderTypeName = () => {
|
||||
return ORDER_NAME_MAP[props.orderData.orderType] || "其他订单";
|
||||
};
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (status) => {
|
||||
// 工单情况:orderType 为 undefined
|
||||
if (props.orderData.orderType === undefined) {
|
||||
const workOrderStatusMap = {
|
||||
0: "待接单",
|
||||
1: "处理中",
|
||||
2: "已完成",
|
||||
3: "已关闭",
|
||||
};
|
||||
return workOrderStatusMap[status] || "未知状态";
|
||||
}
|
||||
|
||||
// 订单情况:orderType 有值
|
||||
const orderStatusMap = {
|
||||
0: "待支付",
|
||||
1: "待确认",
|
||||
2: "待使用",
|
||||
3: "已取消",
|
||||
4: "退款中",
|
||||
5: "已退款",
|
||||
6: "已完成",
|
||||
};
|
||||
return orderStatusMap[status] || "未知状态";
|
||||
};
|
||||
|
||||
// 处理卡片点击
|
||||
const handleCardClick = () => {
|
||||
if (props.orderData.orderType === undefined) return;
|
||||
emit("click", props.orderData);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./styles/index.scss";
|
||||
</style>
|
||||
@@ -0,0 +1,43 @@
|
||||
.order-card {
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
&.tag-0 {
|
||||
color: #ff3d60;
|
||||
}
|
||||
|
||||
&.tag-1 {
|
||||
color: #f00044;
|
||||
}
|
||||
|
||||
&.tag-2 {
|
||||
color: #40ae36;
|
||||
}
|
||||
|
||||
&.tag-3 {
|
||||
color: #808389;
|
||||
}
|
||||
|
||||
&.tag-4 {
|
||||
color: #2d91ff;
|
||||
}
|
||||
|
||||
&.tag-5 {
|
||||
color: #808389;
|
||||
}
|
||||
|
||||
&.tag-6 {
|
||||
color: #fd8702;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user