feat: 订单详情接口对接

This commit is contained in:
duanshuwen
2025-07-30 20:55:26 +08:00
parent 6831004189
commit b527e6d206
12 changed files with 1628 additions and 37 deletions

271
components/Qrcode/index.vue Normal file
View File

@@ -0,0 +1,271 @@
<template xlang="wxml" minapp="mpvue">
<view class="tki-qrcode">
<!-- #ifndef MP-ALIPAY -->
<canvas
class="tki-qrcode-canvas"
:canvas-id="cid"
:style="{ width: cpSize + 'px', height: cpSize + 'px' }"
/>
<!-- #endif -->
<!-- #ifdef MP-ALIPAY -->
<canvas
:id="cid"
:width="cpSize"
:height="cpSize"
class="tki-qrcode-canvas"
/>
<!-- #endif -->
<image
v-show="show"
:src="result"
:style="{ width: cpSize + 'px', height: cpSize + 'px' }"
/>
</view>
</template>
<script setup>
import { ref, computed, watch, onMounted, getCurrentInstance } from "vue";
import QRCode from "./qrcode.js";
let qrcode;
// 定义props
const props = defineProps({
cid: {
type: String,
default: "tki-qrcode-canvas",
},
size: {
type: Number,
default: 200,
},
unit: {
type: String,
default: "upx",
},
show: {
type: Boolean,
default: true,
},
val: {
type: String,
default: "",
},
background: {
type: String,
default: "#ffffff",
},
foreground: {
type: String,
default: "#000000",
},
pdground: {
type: String,
default: "#000000",
},
icon: {
type: String,
default: "",
},
iconSize: {
type: Number,
default: 40,
},
lv: {
type: Number,
default: 3,
},
onval: {
type: Boolean,
default: false,
},
loadMake: {
type: Boolean,
default: false,
},
usingComponents: {
type: Boolean,
default: true,
},
showLoading: {
type: Boolean,
default: true,
},
loadingText: {
type: String,
default: "二维码生成中",
},
});
// 定义emits
const emit = defineEmits(["result"]);
// 获取当前实例
const instance = getCurrentInstance()
// 创建一个安全的上下文对象
const getContext = () => {
return instance?.proxy || instance?.ctx || {}
};
// 响应式数据
const result = ref("");
// 计算属性
const cpSize = computed(() => {
if (props.unit === "upx") {
return uni.upx2px(props.size);
} else {
return props.size;
}
});
// 工具函数
const _empty = (v) => {
let tp = typeof v;
let rt = false;
if (tp === "number" && String(v) === "") {
rt = true;
} else if (tp === "undefined") {
rt = true;
} else if (tp === "object") {
if (JSON.stringify(v) === "{}" || JSON.stringify(v) === "[]" || v === null)
rt = true;
} else if (tp === "string") {
if (
v === "" ||
v === "undefined" ||
v === "null" ||
v === "{}" ||
v === "[]"
)
rt = true;
} else if (tp === "function") {
rt = false;
}
return rt;
};
// 方法定义
const _makeCode = () => {
console.log('开始生成二维码,内容:', props.val, '大小:', cpSize.value)
if (!_empty(props.val)) {
try {
qrcode = new QRCode({
context: getContext(), // 上下文环境
canvasId: props.cid, // canvas-id
usingComponents: props.usingComponents, // 是否是自定义组件
showLoading: props.showLoading, // 是否显示loading
loadingText: props.loadingText, // loading文字
text: props.val, // 生成内容
size: cpSize.value, // 二维码大小
background: props.background, // 背景色
foreground: props.foreground, // 前景色
pdground: props.pdground, // 定位角点颜色
correctLevel: props.lv, // 容错级别
image: props.icon, // 二维码图标
imageSize: props.iconSize, // 二维码图标大小
cbResult: function (res) {
// 生成二维码的回调
console.log('二维码生成完成:', res)
_result(res);
},
});
} catch (error) {
console.error('二维码生成失败:', error)
}
} else {
console.log('二维码内容为空')
uni.showToast({
title: "二维码内容不能为空",
icon: "none",
duration: 2000,
});
}
};
const _clearCode = () => {
_result("");
if (qrcode) {
qrcode.clear();
}
};
const _saveCode = () => {
if (result.value !== "") {
uni.saveImageToPhotosAlbum({
filePath: result.value,
success: function () {
uni.showToast({
title: "二维码保存成功",
icon: "success",
duration: 2000,
});
},
});
}
};
const _result = (res) => {
result.value = res;
emit("result", res);
};
// 监听器
watch(
() => props.size,
(newVal, oldVal) => {
if (newVal !== oldVal && !_empty(newVal)) {
if (!_empty(props.val)) {
setTimeout(() => {
_makeCode();
}, 100);
}
}
}
);
watch(
() => props.val,
(newVal, oldVal) => {
if (props.onval) {
if (newVal !== oldVal && !_empty(newVal)) {
setTimeout(() => {
_makeCode();
}, 0);
}
}
}
);
// 生命周期
onMounted(() => {
if (props.loadMake) {
if (!_empty(props.val)) {
setTimeout(() => {
_makeCode();
}, 0);
}
}
});
// 暴露方法给父组件
defineExpose({
_makeCode,
_clearCode,
_saveCode,
});
</script>
<style>
.tki-qrcode {
position: relative;
}
.tki-qrcode-canvas {
position: fixed;
top: -99999upx;
left: -99999upx;
z-index: -99999;
}
</style>

1201
components/Qrcode/qrcode.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,13 +2,13 @@
<view class="goods-info mb12"> <view class="goods-info mb12">
<view class="hotel-header"> <view class="hotel-header">
<image class="hotel-icon" src="./images/icon_house.png"></image> <image class="hotel-icon" src="./images/icon_house.png"></image>
<text class="hotel-name">天沐温泉酒店</text> <text class="hotel-name">{{ orderData.commodityName }}</text>
</view> </view>
<view class="goods-detail"> <view class="goods-detail">
<image class="goods-image" :src="goodsImage"></image> <image class="goods-image" :src="orderData.commodityCoverPhoto"></image>
<view class="goods-description"> <view class="goods-description">
<text class="goods-title">温泉早鸟票</text> <text class="goods-title">{{ orderData.commodityName }}</text>
<text class="goods-date">预定时间5月1日</text> <text class="goods-date">预定时间{{ orderData.checkInData }}</text>
</view> </view>
</view> </view>
<view class="included-services"> <view class="included-services">
@@ -26,9 +26,24 @@
</template> </template>
<script setup> <script setup>
const goodsImage = 'https://example.com/path/to/image.jpg'; // Replace with actual image URL import { defineProps } from "vue";
defineProps({
orderData: {
type: Object,
required: true,
default: () => ({
id: "",
createTime: "",
contactName: "",
contactPhone: "",
orderStatus: "0", // pending-待处理, completed-已完成, cancelled-已取消
orderType: undefined, // 0-酒店订单, 1-门票订单, 2-其他订单, undefined-工单
}),
},
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import './styles/index.scss'; @import "./styles/index.scss";
</style> </style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

View File

@@ -35,6 +35,7 @@ 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";
import foodIcon from "./images/food.png";
// Props // Props
const props = defineProps({ const props = defineProps({
@@ -65,7 +66,7 @@ const emit = defineEmits(["click", "call"]);
const ICON_MAP = { const ICON_MAP = {
0: hotelIcon, // 酒店订单 0: hotelIcon, // 酒店订单
1: ticketIcon, // 门票订单 1: ticketIcon, // 门票订单
2: hotelIcon, // 其他订单 2: foodIcon, // 其他订单
}; };
// 获取状态图标 // 获取状态图标
@@ -98,7 +99,7 @@ const getStatusText = (status) => {
2: "待使用", 2: "待使用",
3: "已取消", 3: "已取消",
4: "退款中", 4: "退款中",
5: "已推荐", 5: "已退款",
6: "已完成", 6: "已完成",
}; };
return orderStatusMap[status] || "未知状态"; return orderStatusMap[status] || "未知状态";

View File

@@ -2,19 +2,19 @@
<view class="order-info"> <view class="order-info">
<view class="order-item"> <view class="order-item">
<text class="label">订单号</text> <text class="label">订单号</text>
<text class="value">HUSUWF29387865</text> <text class="value">{{ orderData.orderId }}</text>
</view> </view>
<view class="order-item"> <view class="order-item">
<text class="label">流水号</text> <text class="label">流水号</text>
<text class="value">76487829387865</text> <text class="value">{{ orderData.paySerialNumber }}</text>
</view> </view>
<view class="order-item"> <view class="order-item">
<text class="label">支付方式</text> <text class="label">支付方式</text>
<text class="value">微信</text> <text class="value">{{ orderData.payWay }}</text>
</view> </view>
<view class="order-item amount"> <view class="order-item amount">
<text class="label">实际支付金额</text> <text class="label">实际支付金额</text>
<text class="value">¥31.8</text> <text class="value">¥{{ orderData.payAmt }}</text>
</view> </view>
<button class="reserve-button">再次预定</button> <button class="reserve-button">再次预定</button>
<text class="feedback">投诉反馈</text> <text class="feedback">投诉反馈</text>
@@ -22,9 +22,24 @@
</template> </template>
<script setup> <script setup>
// No dynamic data required for this static example import { defineProps } from "vue";
defineProps({
orderData: {
type: Object,
required: true,
default: () => ({
id: "",
createTime: "",
contactName: "",
contactPhone: "",
orderStatus: "0", // pending-待处理, completed-已完成, cancelled-已取消
orderType: undefined, // 0-酒店订单, 1-门票订单, 2-其他订单, undefined-工单
}),
},
});
</script> </script>
<style scoped> <style scoped>
@import './styles/index.scss'; @import "./styles/index.scss";
</style> </style>

View File

@@ -0,0 +1,35 @@
<template>
<view class="order-qrcode">
<Qrcode
:size="size"
:unit="unit"
:val="val"
:loadMake="true"
:onval="true"
/>
</view>
</template>
<script setup>
import { defineProps } from "vue";
import Qrcode from "@/components/Qrcode/index.vue";
const props = defineProps({
size: {
type: Number,
default: 132,
},
unit: {
type: String,
default: "px",
},
val: {
type: String,
default: "text",
},
});
</script>
<style scoped lang="scss">
@import "./styles/index.scss";
</style>

View File

@@ -0,0 +1,18 @@
.order-qrcode {
background: #ffffff;
border-radius: 10px;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 18px;
margin-bottom: 12px;
text {
font-size: 12px;
color: #666666;
line-height: 17px;
margin-top: 4px;
}
}

View File

@@ -3,20 +3,34 @@
<view class="user-info-title">游客信息</view> <view class="user-info-title">游客信息</view>
<view class="user-info-item"> <view class="user-info-item">
<text class="label">联系游客</text> <text class="label">联系游客</text>
<text class="value">{{ contactName }}</text> <text class="value">{{ orderData.visitorName }}</text>
</view> </view>
<view class="user-info-item"> <view class="user-info-item">
<text class="label">联系电话</text> <text class="label">联系电话</text>
<text class="value">{{ contactPhone }}</text> <text class="value">{{ orderData.contactPhone }}</text>
</view> </view>
</view> </view>
</template> </template>
<script setup> <script setup>
const contactName = '李元一'; import { defineProps } from "vue";
const contactPhone = '13172891829';
defineProps({
orderData: {
type: Object,
required: true,
default: () => ({
id: "",
createTime: "",
contactName: "",
contactPhone: "",
orderStatus: "0", // pending-待处理, completed-已完成, cancelled-已取消
orderType: undefined, // 0-酒店订单, 1-门票订单, 2-其他订单, undefined-工单
}),
},
});
</script> </script>
<style scoped> <style scoped>
@import './styles/index.scss'; @import "./styles/index.scss";
</style> </style>

View File

@@ -1,22 +1,37 @@
<template> <template>
<view class="order-detail-wrapper"> <view class="order-detail-wrapper">
<image class="icon-back" src="./images/back.png" /> <image class="icon-back" src="./images/back.png" />
<OrderStatusInfo />
<GoodsInfo /> <OrderStatusInfo :orderData="orderData" />
<UserInfo /> <OrderQrcode size="132" unit="px" :val="orderData.orderId" />
<NoticeInfo /> <GoodsInfo :orderData="orderData" />
<OrderInfo /> <UserInfo :orderData="orderData" />
<NoticeInfo :orderData="orderData" />
<OrderInfo :orderData="orderData" />
</view> </view>
</template> </template>
<script setup> <script setup>
import OrderStatusInfo from './components/OrderStatusInfo/index.vue' import { ref } from "vue";
import GoodsInfo from './components/GoodsInfo/index.vue' import { onLoad } from "@dcloudio/uni-app";
import UserInfo from './components/UserInfo/index.vue' import { userOrderDetail } from "@/request/api/OrderApi";
import NoticeInfo from './components/NoticeInfo/index.vue' import OrderQrcode from "./components/OrderQrcode/index.vue";
import OrderInfo from './components/OrderInfo/index.vue' import OrderStatusInfo from "./components/OrderStatusInfo/index.vue";
import GoodsInfo from "./components/GoodsInfo/index.vue";
import UserInfo from "./components/UserInfo/index.vue";
import NoticeInfo from "./components/NoticeInfo/index.vue";
import OrderInfo from "./components/OrderInfo/index.vue";
const orderData = ref({});
onLoad(async ({ orderId }) => {
console.log("onShow", orderId);
const res = await userOrderDetail({ orderId });
orderData.value = res.data;
console.log(res);
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import './styles/detail.scss'; @import "./styles/detail.scss";
</style> </style>

View File

@@ -93,11 +93,10 @@ const handleTabChange = ({ index }) => {
}; };
// 处理订单点击 // 处理订单点击
const handleOrderClick = (orderData) => { const handleOrderClick = ({ orderId }) => {
console.log("订单点击:", orderData);
// 这里可以添加订单详情跳转逻辑 // 这里可以添加订单详情跳转逻辑
uni.navigateTo({ uni.navigateTo({
url: `/pages/order/detail?id=${orderData.id}`, url: `/pages/order/detail?orderId=${orderId}`,
}); });
}; };
</script> </script>

View File

@@ -9,4 +9,11 @@ const userWorkOrderList = (args) => {
return request.post('/hotelBiz/workOrder/userWorkOrderList', args); return request.post('/hotelBiz/workOrder/userWorkOrderList', args);
} }
export { userOrderList, userWorkOrderList }
// 获取订单详情
const userOrderDetail = (args) => {
return request.post('/hotelBiz/order/userOrderDetail', args);
}
export { userOrderList, userWorkOrderList, userOrderDetail }