feat: 新增工单列表
This commit is contained in:
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -29,8 +29,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import TopNavBar from "@/components/TopNavBar/index.vue";
|
import TopNavBar from "@/components/TopNavBar/index.vue";
|
||||||
|
import CustomEmpty from "@/components/CustomEmpty/index.vue";
|
||||||
import OrderCard from "./components/OrderCard/index.vue";
|
import OrderCard from "./components/OrderCard/index.vue";
|
||||||
import CustomEmpty from "./components/CustomEmpty/index.vue";
|
|
||||||
import { userOrderList } from "@/request/api/OrderApi";
|
import { userOrderList } from "@/request/api/OrderApi";
|
||||||
|
|
||||||
const dataList = ref([]);
|
const dataList = ref([]);
|
||||||
|
|||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
208
src/pages-service/order/components/OrderInfo/index.vue
Normal file
208
src/pages-service/order/components/OrderInfo/index.vue
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
<template>
|
||||||
|
<view class="order-info">
|
||||||
|
<view class="order-item">
|
||||||
|
<text class="label">订单号</text>
|
||||||
|
<text class="value">{{ orderData.orderId }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="order-item">
|
||||||
|
<text class="label">流水号</text>
|
||||||
|
<text class="value">{{ orderData.paySerialNumber }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="order-item">
|
||||||
|
<text class="label">支付方式</text>
|
||||||
|
<text class="value">{{ payWayText }}</text>
|
||||||
|
</view>
|
||||||
|
<!-- 在已退款状态显示 -->
|
||||||
|
<view v-if="orderData.orderStatus === '4'" class="order-item">
|
||||||
|
<text class="label">退款单号</text>
|
||||||
|
<text class="value">{{ orderData.refundOrderNo }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="line"></view>
|
||||||
|
<view class="order-item amount">
|
||||||
|
<text class="label">实际支付金额</text>
|
||||||
|
<text class="value">{{ formattedAmount }}</text>
|
||||||
|
</view>
|
||||||
|
<!-- 根据订单状态动态显示按钮 -->
|
||||||
|
<button
|
||||||
|
v-if="shouldShowButton"
|
||||||
|
:class="['reserve-button', { loading: isLoading }]"
|
||||||
|
:disabled="isLoading"
|
||||||
|
@click="handleButtonClick(orderData)"
|
||||||
|
>
|
||||||
|
{{ isLoading ? "处理中..." : buttonText }}
|
||||||
|
</button>
|
||||||
|
<view class="feedback">
|
||||||
|
<text @click="openFeedback">投诉反馈</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { defineProps, computed, ref, defineEmits } from "vue";
|
||||||
|
import { orderPayNow } from "@/request/api/OrderApi";
|
||||||
|
|
||||||
|
// 支付方式映射常量
|
||||||
|
const PAY_WAY_MAP = {
|
||||||
|
0: "微信",
|
||||||
|
1: "支付宝",
|
||||||
|
2: "云闪付",
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载状态
|
||||||
|
const isLoading = ref(false);
|
||||||
|
|
||||||
|
// 定义事件发射器
|
||||||
|
const emit = defineEmits(["show-refund-popup", "pay-success"]);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
orderData: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: () => ({
|
||||||
|
orderId: "",
|
||||||
|
paySerialNumber: "",
|
||||||
|
payWay: "", // 支付方式 0-微信 1-支付宝 2-云闪付
|
||||||
|
payAmt: "",
|
||||||
|
orderStatus: "0", // 订单状态 0-待支付 1-待确认 2-待使用 3-已取消 4-退款中 5-已关闭 6-已完成
|
||||||
|
orderType: "0", // 0-酒店订单, 1-门票订单, 2-餐饮
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 使用计算属性缓存支付方式文本
|
||||||
|
const payWayText = computed(() => {
|
||||||
|
return PAY_WAY_MAP[props.orderData.payWay] || "未知支付方式";
|
||||||
|
});
|
||||||
|
|
||||||
|
// 格式化金额显示
|
||||||
|
const formattedAmount = computed(() => {
|
||||||
|
const amount = props.orderData.payAmt;
|
||||||
|
return amount ? `${parseFloat(amount).toFixed(2)}` : "0.00";
|
||||||
|
});
|
||||||
|
|
||||||
|
// 按钮文案逻辑,订单状态 0-待支付 1-待确认 2-待使用 3-已取消 4-退款中 5-已关闭 6-已完成
|
||||||
|
const buttonText = computed(() => {
|
||||||
|
const status = props.orderData.orderStatus;
|
||||||
|
switch (status) {
|
||||||
|
case "0": // 待支付状态
|
||||||
|
return "立即支付";
|
||||||
|
case "2": // 待使用状态
|
||||||
|
return "申请退款";
|
||||||
|
case "3": // 已取消状态
|
||||||
|
case "5": // 已关闭状态
|
||||||
|
case "6": // 已完成状态
|
||||||
|
return "再次预定";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 是否显示按钮(待支付、待使用、已取消、已关闭、已完成)
|
||||||
|
const shouldShowButton = computed(() => {
|
||||||
|
const status = props.orderData.orderStatus;
|
||||||
|
return ["0", "2", "3", "5", "6"].includes(status);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 处理按钮点击事件
|
||||||
|
const handleButtonClick = async (orderData) => {
|
||||||
|
if (isLoading.value) return; // 防止重复点击
|
||||||
|
|
||||||
|
try {
|
||||||
|
isLoading.value = true;
|
||||||
|
|
||||||
|
const status = orderData.orderStatus;
|
||||||
|
|
||||||
|
if (status === "2") {
|
||||||
|
// 情况2:待使用状态,显示退款弹窗
|
||||||
|
emit("show-refund-popup");
|
||||||
|
return; // 直接返回,不执行后续代码
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再次预定跳转商品详情
|
||||||
|
if (["3", "5", "6"].includes(status)) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/goods/index?commodityId=${orderData.commodityId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 待支付状态,调用支付接口
|
||||||
|
if (status === "0") {
|
||||||
|
const orderId = orderData.orderId;
|
||||||
|
const payWay = orderData.payWay;
|
||||||
|
const paySource = orderData.paySource;
|
||||||
|
|
||||||
|
const res = await orderPayNow({ orderId, payWay, paySource });
|
||||||
|
console.log("确认订单---2:", res);
|
||||||
|
|
||||||
|
// 检查接口返回数据
|
||||||
|
if (!res || !res.data) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "订单创建失败,请重试",
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = res;
|
||||||
|
const { nonceStr, packageVal, paySign, signType, timeStamp } = data;
|
||||||
|
|
||||||
|
// 验证支付参数是否完整
|
||||||
|
if (!nonceStr || !packageVal || !paySign || !signType || !timeStamp) {
|
||||||
|
console.error("支付参数不完整:", {
|
||||||
|
nonceStr: !!nonceStr,
|
||||||
|
packageVal: !!packageVal,
|
||||||
|
paySign: !!paySign,
|
||||||
|
signType: !!signType,
|
||||||
|
timeStamp: !!timeStamp,
|
||||||
|
});
|
||||||
|
uni.showToast({
|
||||||
|
title: "支付参数错误,请重试",
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用微信支付
|
||||||
|
uni.requestPayment({
|
||||||
|
provider: "wxpay",
|
||||||
|
timeStamp: String(timeStamp), // 确保为字符串类型
|
||||||
|
nonceStr: String(nonceStr),
|
||||||
|
package: String(packageVal), // 确保为字符串类型
|
||||||
|
signType: String(signType),
|
||||||
|
paySign: String(paySign),
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "支付成功",
|
||||||
|
icon: "success",
|
||||||
|
duration: 2000,
|
||||||
|
success: () => {
|
||||||
|
emit("pay-success");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "支付失败,请重试",
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("操作失败:", error);
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 投诉电话
|
||||||
|
const openFeedback = () => {
|
||||||
|
const phoneNumber = props.orderData.complaintHotline;
|
||||||
|
uni.makePhoneCall({ phoneNumber });
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import "./styles/index.scss";
|
||||||
|
</style>
|
||||||
156
src/pages-service/order/components/OrderInfo/styles/index.scss
Normal file
156
src/pages-service/order/components/OrderInfo/styles/index.scss
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// 颜色系统
|
||||||
|
$order-bg-color: #fff;
|
||||||
|
$text-color-primary: #333;
|
||||||
|
$text-color-secondary: #666;
|
||||||
|
$text-color-accent: #ff5722;
|
||||||
|
$button-color: #00a6ff;
|
||||||
|
$button-disabled-color: #ccc;
|
||||||
|
$border-color: #ececec;
|
||||||
|
$shadow-color: rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
|
// 尺寸和间距
|
||||||
|
$order-border-radius: 10px;
|
||||||
|
$order-padding: 16px 18px;
|
||||||
|
$spacing-small: 8px;
|
||||||
|
$spacing-medium: 10px;
|
||||||
|
$spacing-large: 20px;
|
||||||
|
$button-height: 42px;
|
||||||
|
|
||||||
|
// 字体系统
|
||||||
|
$font-size-small: 12px;
|
||||||
|
$font-size-medium: 14px;
|
||||||
|
$font-size-large: 18px;
|
||||||
|
$font-weight-normal: 400;
|
||||||
|
$font-weight-medium: 500;
|
||||||
|
$font-weight-semibold: 600;
|
||||||
|
|
||||||
|
// 过渡动画
|
||||||
|
$transition-fast: 0.2s ease;
|
||||||
|
$transition-normal: 0.3s ease;
|
||||||
|
|
||||||
|
.order-info {
|
||||||
|
background-color: $order-bg-color;
|
||||||
|
border-radius: $order-border-radius;
|
||||||
|
padding: $order-padding;
|
||||||
|
box-shadow: 0 2px 8px $shadow-color;
|
||||||
|
transition: box-shadow $transition-normal;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订单项样式,优化布局和视觉层次
|
||||||
|
.order-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: $spacing-small;
|
||||||
|
padding: 4px 0;
|
||||||
|
transition: background-color $transition-fast;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: $font-size-small;
|
||||||
|
color: $text-color-secondary;
|
||||||
|
font-weight: $font-weight-normal;
|
||||||
|
flex-shrink: 0;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: $font-size-small;
|
||||||
|
color: $text-color-primary;
|
||||||
|
font-weight: $font-weight-normal;
|
||||||
|
text-align: right;
|
||||||
|
word-break: break-word;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
line-height: 1.4;
|
||||||
|
max-width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 金额特殊样式,增强视觉重点
|
||||||
|
&.amount {
|
||||||
|
.label {
|
||||||
|
color: $text-color-primary;
|
||||||
|
font-weight: $font-weight-medium;
|
||||||
|
font-size: $font-size-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
color: $text-color-accent;
|
||||||
|
font-size: $font-size-large;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
max-width: none;
|
||||||
|
|
||||||
|
// 货币符号样式
|
||||||
|
&::before {
|
||||||
|
content: "¥";
|
||||||
|
margin-right: 2px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
border-bottom: 1px solid $border-color;
|
||||||
|
margin: $spacing-medium 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: 0.6;
|
||||||
|
transition: opacity $transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.reserve-button {
|
||||||
|
width: 100%;
|
||||||
|
background: linear-gradient(179deg, #00a6ff 0%, #0256ff 100%);
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: $uni-border-radius-50px;
|
||||||
|
height: $button-height;
|
||||||
|
font-size: $font-size-medium;
|
||||||
|
font-weight: $font-weight-medium;
|
||||||
|
margin-top: $spacing-large;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background: $button-disabled-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
transform: none;
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载状态样式
|
||||||
|
&.loading {
|
||||||
|
background: $button-disabled-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
transform: none;
|
||||||
|
box-shadow: none;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback {
|
||||||
|
text-align: center;
|
||||||
|
font-size: $font-size-medium;
|
||||||
|
color: $text-color-primary;
|
||||||
|
font-weight: $font-weight-normal;
|
||||||
|
margin-top: $spacing-medium;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
src/pages-service/order/list.vue
Normal file
60
src/pages-service/order/list.vue
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<z-paging
|
||||||
|
bg-color="linear-gradient(180deg, #D9EEFF 0%, #F5F7FA 100%) 0 86px / 100% 100px no-repeat"
|
||||||
|
ref="paging"
|
||||||
|
v-model="dataList"
|
||||||
|
use-virtual-list
|
||||||
|
:force-close-inner-list="true"
|
||||||
|
cell-height-mode="dynamic"
|
||||||
|
safe-area-inset-bottom
|
||||||
|
@query="queryList"
|
||||||
|
>
|
||||||
|
<template #top>
|
||||||
|
<TopNavBar title="全部服务工单" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #empty>
|
||||||
|
<CustomEmpty statusText="您暂无服务工单" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<OrderCard
|
||||||
|
v-for="(item, index) in dataList"
|
||||||
|
:key="item.id || index"
|
||||||
|
:orderData="item"
|
||||||
|
/>
|
||||||
|
</z-paging>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import TopNavBar from "@/components/TopNavBar/index.vue";
|
||||||
|
import CustomEmpty from "@/components/CustomEmpty/index.vue";
|
||||||
|
import OrderCard from "./components/OrderCard/index.vue";
|
||||||
|
import { userWorkOrderList } from "@/request/api/OrderApi";
|
||||||
|
|
||||||
|
const dataList = ref([]);
|
||||||
|
const paging = ref(null);
|
||||||
|
|
||||||
|
const queryList = async (pageNum, pageSize) => {
|
||||||
|
try {
|
||||||
|
const res = await userWorkOrderList({ pageNum, pageSize });
|
||||||
|
console.log("API响应:", res);
|
||||||
|
|
||||||
|
if (res && res.data && res.data.records) {
|
||||||
|
const records = res.data.records;
|
||||||
|
|
||||||
|
// 完成数据加载,第二个参数表示是否还有更多数据
|
||||||
|
paging.value.complete(records);
|
||||||
|
} else {
|
||||||
|
// 没有数据
|
||||||
|
paging.value.complete([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("查询列表失败:", error);
|
||||||
|
// 加载失败
|
||||||
|
paging.value.complete(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@@ -36,6 +36,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"root": "pages-service",
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"path": "order/list",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ const list = ref([
|
|||||||
content: "查看服务工单、进度与处理情况",
|
content: "查看服务工单、进度与处理情况",
|
||||||
btnText: "去查看",
|
btnText: "去查看",
|
||||||
type: Command.myWorkOrder,
|
type: Command.myWorkOrder,
|
||||||
path: "/pages/myWorkOrder/index",
|
path: "/pages-service/order/list",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "https://oss.nianxx.cn/mp/static/version_101/home/fkyj.png",
|
icon: "https://oss.nianxx.cn/mp/static/version_101/home/fkyj.png",
|
||||||
|
|||||||
Reference in New Issue
Block a user