# Conflicts:
#	src/pages/index/components/module/MoreService/index.vue
This commit is contained in:
2025-10-16 20:40:30 +08:00
14 changed files with 150 additions and 266 deletions

View File

@@ -23,7 +23,7 @@ page,
body, body,
#app { #app {
font-family: PingFang SC, PingFang SC; font-family: PingFang SC, PingFang SC;
background-color: #e9f3f7; background-color: #f5f7fa;
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
} }

View File

@@ -7,18 +7,33 @@
></view> ></view>
<!-- 导航栏内容 --> <!-- 导航栏内容 -->
<view class="nav-bar-content" :style="{ height: navBarHeight + 'px' }"> <view
class="flex flex-items-center flex-justify-between border-box pl-8 pr-8"
:style="{ height: navBarHeight + 'px' }"
>
<!-- 左侧返回按钮 --> <!-- 左侧返回按钮 -->
<view class="nav-bar-left" @click="handleBack" v-if="showBack"> <view
class="nav-bar-left flex flex-items-center flex-justify-center"
v-if="showBack"
@click="handleBack"
>
<uni-icons type="left" size="20" :color="backIconColor" /> <uni-icons type="left" size="20" :color="backIconColor" />
</view> </view>
<!-- 中间标题区域 --> <!-- 中间标题区域 -->
<view :class="['nav-bar-center', `nav-bar-center--${titleAlign}`]"> <view
:class="[
'nav-bar-center flex flex-items-center flex-justify-center',
`nav-bar-center--${titleAlign}`,
]"
>
<slot name="title"> <slot name="title">
<text class="nav-bar-title" :style="{ color: titleColor }">{{ <text
title class="font-size-17 font-500 color-000"
}}</text> :style="{ color: titleColor }"
>
{{ title }}
</text>
</slot> </slot>
</view> </view>
@@ -45,11 +60,6 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
// 是否添加阴影
shadow: {
type: Boolean,
default: true,
},
// 是否显示返回按钮 // 是否显示返回按钮
showBack: { showBack: {
type: Boolean, type: Boolean,
@@ -58,17 +68,17 @@ const props = defineProps({
// 背景颜色 // 背景颜色
backgroundColor: { backgroundColor: {
type: String, type: String,
default: "#ffffff", default: "#d9eeff",
}, },
// 标题颜色 // 标题颜色
titleColor: { titleColor: {
type: String, type: String,
default: "#333333", default: "#000",
}, },
// 返回按钮图标颜色 // 返回按钮图标颜色
backIconColor: { backIconColor: {
type: String, type: String,
default: "#333333", default: "#000",
}, },
// 是否隐藏状态栏占位 // 是否隐藏状态栏占位
hideStatusBar: { hideStatusBar: {
@@ -114,7 +124,6 @@ const navBarClass = computed(() => {
"top-nav-bar", "top-nav-bar",
{ {
"top-nav-bar--fixed": props.fixed, "top-nav-bar--fixed": props.fixed,
"has-shadow": props.shadow,
}, },
]; ];
}); });

View File

@@ -1,11 +1,7 @@
// TopNavBar 组件样式 // TopNavBar 组件样式
.top-nav-bar { .top-nav-bar {
width: 100%; width: 100%;
background-color: $uni-bg-color; background-color: #d9eeff;
&.has-shadow {
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.1);
}
&--fixed { &--fixed {
position: fixed; position: fixed;
@@ -14,86 +10,35 @@
right: 0; right: 0;
z-index: 999; z-index: 999;
} }
}
.nav-bar-content { .nav-bar-left,
display: flex; .nav-bar-right {
align-items: center; width: 30px;
justify-content: space-between; height: 30px;
padding: 0 16px; }
position: relative;
.nav-bar-left { .nav-bar-center {
display: flex; flex: 1;
align-items: center; height: 30px;
justify-content: center; padding: 0 20px; // 为左右按钮留出空间
width: 30px;
height: 30px;
position: absolute;
left: 8px;
top: 50%;
transform: translateY(-50%);
z-index: 2;
cursor: pointer;
transition: opacity 0.2s ease;
&:hover { // 居中对齐(默认)
opacity: 0.7; &--center {
} justify-content: center;
&:active { .nav-bar-title {
opacity: 0.5; text-align: center;
}
} }
}
.nav-bar-center { // 左对齐
flex: 1; &--left {
height: 30px; justify-content: flex-start;
display: flex; padding-left: 20px; // 为返回按钮留出更多空间
align-items: center;
justify-content: center;
padding: 0 20px; // 为左右按钮留出空间
// 居中对齐(默认) .nav-bar-title {
&--center { text-align: left;
justify-content: center;
.nav-bar-title {
text-align: center;
}
}
// 左对齐
&--left {
justify-content: flex-start;
padding-left: 20px; // 为返回按钮留出更多空间
.nav-bar-title {
text-align: left;
}
}
.nav-bar-title {
font-size: 18px;
font-weight: 500;
color: $uni-text-color;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 1.4;
}
}
.nav-bar-right {
display: flex;
align-items: center;
justify-content: center;
min-width: 30px;
height: 30px;
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
z-index: 2;
} }
} }
} }
@@ -102,11 +47,3 @@
.page-with-fixed-navbar { .page-with-fixed-navbar {
padding-top: calc(var(--status-bar-height, 44px) + 44px); padding-top: calc(var(--status-bar-height, 44px) + 44px);
} }
// 安全区域适配
.top-nav-bar {
padding-left: constant(safe-area-inset-left);
padding-left: env(safe-area-inset-left);
padding-right: constant(safe-area-inset-right);
padding-right: env(safe-area-inset-right);
}

View File

@@ -1,7 +1,7 @@
<template> <template>
<view class="info-row"> <view class="info-row flex items-center mt-8">
<text class="label">{{ label }}</text> <text class="label font-size-12 color-99A0AE">{{ label }}</text>
<text class="value">{{ value }}</text> <text class="value flex-full font-size-12 color-99A0AE">{{ value }}</text>
</view> </view>
</template> </template>
@@ -23,23 +23,4 @@ const props = defineProps({
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss"></style>
.info-row {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.label {
font-size: $uni-font-size-sm;
color: #666666;
flex-shrink: 0;
margin-right: 8px;
}
.value {
font-size: $uni-font-size-base;
color: $uni-text-color;
flex: 1;
}
</style>

View File

@@ -1,5 +1,15 @@
<template> <template>
<view class="card-content"> <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 <InfoRow
v-for="item in displayItems" v-for="item in displayItems"
@@ -23,7 +33,6 @@ const ORDER_TYPES = {
// 标签常量 // 标签常量
const LABELS = { const LABELS = {
ORDER_ID: "订单编号",
CHECK_IN_TIME: "入住时间", CHECK_IN_TIME: "入住时间",
VISITOR_NAME: "游客姓名", VISITOR_NAME: "游客姓名",
CONTACT_PHONE: "联系电话", CONTACT_PHONE: "联系电话",
@@ -74,7 +83,6 @@ const displayItems = computed(() => {
switch (orderType) { switch (orderType) {
case ORDER_TYPES.HOTEL: case ORDER_TYPES.HOTEL:
return [ return [
{ label: LABELS.ORDER_ID, value: orderData.orderId },
{ {
label: LABELS.CHECK_IN_TIME, label: LABELS.CHECK_IN_TIME,
value: value:
@@ -95,7 +103,6 @@ const displayItems = computed(() => {
case ORDER_TYPES.TICKET: case ORDER_TYPES.TICKET:
case ORDER_TYPES.OTHER: case ORDER_TYPES.OTHER:
return [ return [
{ label: LABELS.ORDER_ID, value: orderData.orderId },
{ {
label: LABELS.QUANTITY, label: LABELS.QUANTITY,
value: formatQuantity(orderData.commodityAmount), value: formatQuantity(orderData.commodityAmount),
@@ -110,7 +117,11 @@ const displayItems = computed(() => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.card-content { .right {
padding: 16px; &::before {
content: "¥";
font-weight: 500;
font-size: 16px;
}
} }
</style> </style>

View File

@@ -1,25 +1,20 @@
<template> <template>
<view class="order-card" @click="handleCardClick"> <view
class="order-card bg-white border-box p-12 rounded-12 m-12"
@click="handleCardClick"
>
<!-- 卡片头部 --> <!-- 卡片头部 -->
<view class="card-header"> <view class="card-header flex items-center">
<view class="status-info"> <view class="status-info flex items-center flex-full">
<image class="status-icon" :src="getStatusIcon()"></image> <image class="status-icon mr-4" :src="getStatusIcon()" />
<view class="order-title"> <view class="order-title font-size-14 line-height-20 color-525866">
{{ orderData.workOrderTypeName || orderData.commodityName }} {{ getOrderTypeName() }}
</view> </view>
<uni-icons
class="arrow-icon"
v-if="props.orderData.orderType !== undefined"
type="right"
color="#999"
size="16"
/>
</view> </view>
<view <view
v-if="orderData.status !== 'pending'" v-if="orderData.status !== 'pending'"
:class="[ :class="[
'status-tag', 'status-tag font-size-12',
`tag-${orderData.orderStatus || orderData.workOrderStatus}`, `tag-${orderData.orderStatus || orderData.workOrderStatus}`,
]" ]"
> >
@@ -27,9 +22,6 @@
</view> </view>
</view> </view>
<!-- 分割线 -->
<Divider />
<!-- 卡片内容 --> <!-- 卡片内容 -->
<OrderCardContent :order-data="orderData" /> <OrderCardContent :order-data="orderData" />
</view> </view>
@@ -37,12 +29,8 @@
<script setup> <script setup>
import { defineProps } from "vue"; import { defineProps } from "vue";
import Divider from "@/components/Divider/index.vue";
import OrderCardContent from "./OrderCardContent.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 hotelIcon from "./images/hotel.png";
import foodIcon from "./images/food.png";
// Props // Props
const props = defineProps({ const props = defineProps({
@@ -71,9 +59,16 @@ const emit = defineEmits(["click", "call"]);
// 图标映射 // 图标映射
const ICON_MAP = { const ICON_MAP = {
0: hotelIcon, // 酒店订单 0: "https://oss.nianxx.cn/mp/static/version_101/order/room.png", // 酒店订单
1: ticketIcon, // 门票订单 1: "https://oss.nianxx.cn/mp/static/version_101/order/ticket.png", // 门票订单
2: foodIcon, // 其他订单 2: "https://oss.nianxx.cn/mp/static/version_101/order/food.png", // 餐饮
};
// 订单类型映射
const ORDER_NAME_MAP = {
0: "房间",
1: "门票",
2: "餐饮",
}; };
// 获取状态图标 // 获取状态图标
@@ -86,6 +81,11 @@ const getStatusIcon = () => {
return ICON_MAP[props.orderData.orderType] || serviceIcon; return ICON_MAP[props.orderData.orderType] || serviceIcon;
}; };
// 获取订单类型名称
const getOrderTypeName = () => {
return ORDER_NAME_MAP[props.orderData.orderType] || "其他订单";
};
// 获取状态文本 // 获取状态文本
const getStatusText = (status) => { const getStatusText = (status) => {
// 工单情况orderType 为 undefined // 工单情况orderType 为 undefined

View File

@@ -1,91 +1,43 @@
.order-card { .order-card {
background-color: #fff;
border-radius: 6px 6px 12px 12px;
box-shadow: 0px 3px 8px 0 rgba(0, 0, 0, 0.12);
margin: 12px;
transition: all 0.3s ease; transition: all 0.3s ease;
mask: radial-gradient(circle at 0 54px, #0000 6px, red 0),
radial-gradient(circle at right 54px, #0000 6px, red 0);
mask-size: 50%;
mask-position: 0, 100%;
mask-repeat: no-repeat;
&:active { &:active {
transform: scale(0.98); transform: scale(0.98);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
} }
&.expired {
filter: grayscale(100%);
}
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 14px 14px 12px 16px;
}
.status-info {
display: flex;
align-items: center;
flex: 1;
} }
.status-icon { .status-icon {
width: 20px; width: 20px;
height: 20px; height: 20px;
margin-right: 8px;
flex-shrink: 0;
}
.order-title {
font-size: $uni-font-size-base;
font-weight: 500;
color: $uni-text-color;
line-height: 1.4;
} }
.status-tag { .status-tag {
box-sizing: border-box;
padding: 6px 16px;
border-radius: 20px;
font-size: $uni-font-size-sm;
font-weight: 500;
&.tag-0 { &.tag-0 {
color: #00a6ff; color: #ff3d60;
border: 1px solid #00a6ff;
} }
&.tag-1 { &.tag-1 {
color: #f00044; color: #f00044;
border: 1px solid #f00044;
} }
&.tag-2 { &.tag-2 {
color: #40ae36; color: #40ae36;
border: 1px solid #40ae36;
} }
&.tag-3 { &.tag-3 {
color: #808389; color: #808389;
border: 1px solid #808389;
} }
&.tag-4 { &.tag-4 {
color: #0256ff; color: #2d91ff;
border: 1px solid #0256ff;
} }
&.tag-5 { &.tag-5 {
color: #808389; color: #808389;
border: 1px solid #808389;
} }
&.tag-6 { &.tag-6 {
color: #fd8702; color: #fd8702;
border: 1px solid #fd8702;
} }
} }

View File

@@ -1,5 +1,6 @@
<template> <template>
<z-paging <z-paging
bg-color="linear-gradient(180deg, #D9EEFF 0%, #F5F7FA 100%) 0 86px / 100% 100px no-repeat"
ref="paging" ref="paging"
v-model="dataList" v-model="dataList"
use-virtual-list use-virtual-list
@@ -9,15 +10,7 @@
@query="queryList" @query="queryList"
> >
<template #top> <template #top>
<TopNavBar titleAlign="left"> <TopNavBar title="全部订单" />
<template #title>
<Tabs
:tabs="tabList"
:defaultActive="currentTabIndex"
@change="handleTabChange"
/>
</template>
</TopNavBar>
</template> </template>
<template #empty> <template #empty>
@@ -36,35 +29,16 @@
<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 Tabs from "./components/Tabs/index.vue";
import OrderCard from "./components/OrderCard/index.vue"; import OrderCard from "./components/OrderCard/index.vue";
import CustomEmpty from "./components/CustomEmpty/index.vue"; import CustomEmpty from "./components/CustomEmpty/index.vue";
import { userOrderList, userWorkOrderList } from "@/request/api/OrderApi"; import { userOrderList } from "@/request/api/OrderApi";
// Tab配置
const tabList = ref([
{ label: "全部订单", value: "all" },
{ label: "服务工单", value: "service" },
]);
// 当前状态
const currentTabIndex = ref(0);
const dataList = ref([]); const dataList = ref([]);
const paging = ref(null); const paging = ref(null);
const queryList = async (pageNum, pageSize) => { const queryList = async (pageNum, pageSize) => {
try { try {
let apiCall; const res = await userOrderList({ pageNum, pageSize });
// 根据当前Tab选择不同的API
if (currentTabIndex.value === 0) {
// 全部订单
apiCall = userOrderList({ pageNum, pageSize });
} else {
// 服务工单
apiCall = userWorkOrderList({ pageNum, pageSize });
}
const res = await apiCall;
console.log("API响应:", res); console.log("API响应:", res);
if (res && res.data && res.data.records) { if (res && res.data && res.data.records) {
@@ -83,15 +57,6 @@ const queryList = async (pageNum, pageSize) => {
} }
}; };
// Tab切换处理
const handleTabChange = ({ index }) => {
console.log("Tab切换到:", index);
currentTabIndex.value = index;
// 清空当前数据并重新加载
dataList.value = [];
paging.value.reload();
};
// 处理订单点击 // 处理订单点击
const handleOrderClick = ({ orderId }) => { const handleOrderClick = ({ orderId }) => {
// 这里可以添加订单详情跳转逻辑 // 这里可以添加订单详情跳转逻辑

View File

@@ -273,19 +273,7 @@ const handleReplyText = (text) => {
// 是发送指令消息 // 是发送指令消息
const handleReplyInstruct = async (item) => { const handleReplyInstruct = async (item) => {
await checkToken(); await checkToken();
// 更多服务
if (item.type === "Command.more") {
uni.$emit("SHOW_MORE_POPUP");
return;
}
if (item.type === "Command.myOrder") {
// 订单
uni.navigateTo({
url: "/pages-order/order/list",
});
return;
}
commonType = item.type; commonType = item.type;
// 重置消息状态准备接收新的AI回复 // 重置消息状态准备接收新的AI回复
resetMessageState(); resetMessageState();

View File

@@ -47,6 +47,11 @@ const itemList = ref([
]); ]);
const sendReply = (item) => { const sendReply = (item) => {
// 更多服务
if (item.type === Command.more) {
uni.$emit("SHOW_MORE_POPUP");
return;
}
uni.$emit(SEND_MESSAGE_COMMAND_TYPE, item); uni.$emit(SEND_MESSAGE_COMMAND_TYPE, item);
}; };
</script> </script>

View File

@@ -25,6 +25,4 @@ const props = defineProps({
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss"></style>
@import "./styles/index.scss";
</style>

View File

@@ -5,7 +5,7 @@
<view class="title flex-full font-size-17 color-000 font-500" <view class="title flex-full font-size-17 color-000 font-500"
>更多服务</view >更多服务</view
> >
<uni-icons type="close" size="20" color="#CACFD8" @click="close" /> <uni-icons type="close" size="24" color="#CACFD8" @click="close" />
</view> </view>
<view class="list bg-white border-box pl-20 pr-20"> <view class="list bg-white border-box pl-20 pr-20">
@@ -27,6 +27,7 @@
</view> </view>
<view <view
class="right border-box font-size-12 color-white line-height-16" class="right border-box font-size-12 color-white line-height-16"
@click="handleClick(item)"
> >
{{ item.btnText }} {{ item.btnText }}
</view> </view>
@@ -51,6 +52,7 @@ const list = ref([
content: "预定门票、房间、餐食", content: "预定门票、房间、餐食",
btnText: "去预定", btnText: "去预定",
type: Command.quickBooking, type: Command.quickBooking,
path: "",
}, },
{ {
icon: "https://oss.nianxx.cn/mp/static/version_101/home/tsfx.png", icon: "https://oss.nianxx.cn/mp/static/version_101/home/tsfx.png",
@@ -58,6 +60,7 @@ const list = ref([
content: "发现景点、活动、特色内容", content: "发现景点、活动、特色内容",
btnText: "去探索", btnText: "去探索",
type: Command.discovery, type: Command.discovery,
path: "",
}, },
{ {
icon: "https://oss.nianxx.cn/mp/static/version_101/home/mddd.png", icon: "https://oss.nianxx.cn/mp/static/version_101/home/mddd.png",
@@ -65,6 +68,7 @@ const list = ref([
content: "查看门票、住宿、餐饮等订单", content: "查看门票、住宿、餐饮等订单",
btnText: "去查看", btnText: "去查看",
type: Command.myOrder, type: Command.myOrder,
path: "/pages-order/order/list",
}, },
{ {
icon: "https://oss.nianxx.cn/mp/static/version_101/home/wdgd.png", icon: "https://oss.nianxx.cn/mp/static/version_101/home/wdgd.png",
@@ -72,6 +76,7 @@ const list = ref([
content: "查看服务工单、进度与处理情况", content: "查看服务工单、进度与处理情况",
btnText: "去查看", btnText: "去查看",
type: Command.myWorkOrder, type: Command.myWorkOrder,
path: "/pages/myWorkOrder/index",
}, },
{ {
icon: "https://oss.nianxx.cn/mp/static/version_101/home/fkyj.png", icon: "https://oss.nianxx.cn/mp/static/version_101/home/fkyj.png",
@@ -79,6 +84,7 @@ const list = ref([
content: "提交使用问题、建议与需求", content: "提交使用问题、建议与需求",
btnText: "去反馈", btnText: "去反馈",
type: Command.feedbackCard, type: Command.feedbackCard,
path: "",
}, },
]); ]);
@@ -86,15 +92,19 @@ const open = () => {
popup.value && popup.value.open(); popup.value && popup.value.open();
}; };
const handleClick = (item) => {
uni.$emit(SEND_MESSAGE_COMMAND_TYPE, item);
close();
};
const close = () => { const close = () => {
popup.value && popup.value.close(); popup.value && popup.value.close();
}; };
const handleClick = (item) => {
close();
if (item.path) {
uni.navigateTo({ url: item.path });
return;
}
uni.$emit(SEND_MESSAGE_COMMAND_TYPE, item);
};
// 接收更多服务 // 接收更多服务
uni.$on("SHOW_MORE_POPUP", () => { uni.$on("SHOW_MORE_POPUP", () => {
open(); open();

View File

@@ -3,6 +3,18 @@
margin: 4px; margin: 4px;
} }
.mr-4 {
margin-right: 4px;
}
.m-8 {
margin: 8px;
}
.mt-8 {
margin-top: 8px;
}
.mr-8 { .mr-8 {
margin-right: 8px; margin-right: 8px;
} }
@@ -11,10 +23,18 @@
margin-bottom: 8px; margin-bottom: 8px;
} }
.mt-10 {
margin-top: 10px;
}
.mb-10 { .mb-10 {
margin-bottom: 10px; margin-bottom: 10px;
} }
.m-12 {
margin: 12px;
}
.mb-12 { .mb-12 {
margin-bottom: 12px; margin-bottom: 12px;
} }

View File

@@ -27,6 +27,14 @@
padding-top: 8px; padding-top: 8px;
} }
.pl-8 {
padding-left: 8px;
}
.pr-8 {
padding-right: 8px;
}
.pb-8 { .pb-8 {
padding-bottom: 8px; padding-bottom: 8px;
} }