feat(order): add order detail and list pages with components for order management

- Implemented order detail page with components for displaying order status, user info, and refund options.
- Created order list page with pagination and order cards for displaying all orders.
- Added styles for order detail and list pages.
- Developed a prompt document outlining component requirements for the order management system.
- Introduced a new Card component for quick booking with a responsive design.
- Enhanced Tabs component for better navigation between different categories.
- Integrated z-paging for efficient data loading and management in order and quick booking lists.
- Added service order card component for displaying service requests with call functionality.
- Updated main CSS for improved viewport handling.
This commit is contained in:
duanshuwen
2026-05-26 15:38:33 +08:00
parent fa76435e38
commit ad93ca5e8e
194 changed files with 17069 additions and 2 deletions

View File

@@ -0,0 +1,287 @@
<template>
<div class="create-service-order">
<div
class="w-full bg-white border-box border-ff overflow-hidden rounded-20"
>
<div
class="border-box order-header w-vw flex flex-items-center flex-justify-between bg-theme-color-50"
>
<spanclass="font-size-18 font-500 color-171717 text-left ml-12">
{{ isCallSuccess ? "服务已创建" : "呼叫服务" }}
</text>
<img
class="header-icon"
src="https://oss.nianxx.cn/mp/static/version_101/home/feedback.png"
/>
</div>
<div v-if="!isCallSuccess" class="border-box p-12">
<div
class="bg-F5F7FA border-box flex flex-items-center p-12 rounded-10 font-size-14 color-171717 mb-12"
>
<spanclass="font-500 line-height-22 mr-20">所在位置</text>
<input placeholder="请填写所在位置" v-model="roomId" />
</div>
<div
class="bg-F5F7FA border-box flex flex-items-center p-12 rounded-10 font-size-14 color-171717 mb-12"
>
<spanclass="font-500 line-height-22 mr-20">联系电话</text>
<input
placeholder="请填写联系电话"
v-model="contactPhone"
@input="handleContactPhoneInput"
/>
</div>
<div
class="bg-F5F7FA border-box p-12 rounded-10 font-size-14 font-500 color-171717 mb-12"
>
<div class="font-500 line-height-22 mb-12">需求信息描述</div>
<textarea
class="h-80"
placeholder="请输入需求信息描述"
placeholder-class="font-size-14 font-400"
maxlength="100"
v-model="contactText"
/>
</div>
<div
class="bg-F5F7FA border-box p-12 rounded-10 font-size-14 font-500 color-171717 mb-12"
>
<div class="font-500 line-height-22 mb-12">照片上传</div>
<div
class="w-80 h-80 bg-white rounded-8 overflow-hidden flex flex-items-center flex-justify-center"
>
<div
v-if="contentImgUrl"
class="w-full h-full relative inline-block"
>
<img
class="w-full h-full block"
:src="contentImgUrl"
mode="aspectFill"
/>
<uni-icons
class="close-btn absolute z-10"
type="close"
size="20"
color="#6A717F"
@click="handleDeleteImage"
>
</uni-icons>
</div>
<div
v-else
class="w-full h-full flex flex-items-center flex-justify-center"
@click="handleChooseImage"
>
<uni-icons fontFamily="znicons" size="24" color="#6A717F">
{{ zniconsMap["zn-camera"] }}
</uni-icons>
</div>
</div>
</div>
</div>
<div v-else class="border-box card-content flex flex-items-center p-12">
<div class="border-box left flex-full pr-20">
<div class="font-size-12 color-525866 line-height-20 mb-4">
所在位置{{ roomId }}
</div>
<div class="font-size-12 color-525866 line-height-20 mb-4">
联系方式: {{ contactPhone }}
</div>
<div class="font-size-12 color-525866 line-height-20 ellipsis-2">
需求描述: {{ contactspan}}
</div>
</div>
<img
v-if="contentImgUrl"
class="right rounded-6"
:src="contentImgUrl"
mode="aspectFill"
/>
</div>
<div
class="btn rounded-50 color-white bg-button flex flex-items-center flex-justify-center ml-12 mr-12 mb-12"
@click="handleCall"
>
{{ isCallSuccess ? "查看服务" : "立即呼叫" }}
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted, nextTick, defineProps, watch } from "vue";
import { SCROLL_TO_BOTTOM } from "@/constant/constant";
import { createWorkOrder } from "@/request/api/WorkOrderApi";
import { updateImageFile } from "@/request/api/UpdateFile";
import { zniconsMap } from "@/static/fonts/znicons.js";
const props = defineProps({
toolCall: {
type: Object,
default: () => ({}),
},
});
const workOrderTypeId = ref("");
const roomId = ref("");
const contentImgUrl = ref("");
const isCallSuccess = ref(false); // 呼叫成功状态
const workOrderId = ref(0); // 工单ID
const toolResult = computed(() => {
if (props.toolCall?.toolResult) {
return JSON.parse(props.toolCall?.toolResult);
} else {
return {};
}
});
// 原始手机号(未脱敏)
const originalPhone = ref("");
// 展示与输入绑定的手机号(初始为脱敏)
const contactPhone = ref("");
// 是否用户已编辑过手机号(一旦编辑则不再脱敏)
const hasEditedPhone = ref(false);
// 需求信息描述:使用可写的 ref并从工具结果初始化
const contactspan= ref("");
// 手机号脱敏138****1234仅对11位数字进行处理
const maskPhone = (phone) => {
if (!phone) return "";
return String(phone).replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
};
// 监听工具返回结果,初始化原始与脱敏显示
watch(
toolResult,
(val) => {
originalPhone.value = val?.userPhone || "";
hasEditedPhone.value = false;
contactPhone.value = maskPhone(originalPhone.value);
contactText.value = val?.callServiceContent || "";
},
{ immediate: true },
);
// 处理图片上传
const handleChooseImage = () => {
uni.chooseImage({
count: 1,
success: (res) => {
const file = res.tempFilePaths[0];
updateImagehandle(file);
},
fail: () => {
uni.showToast({ title: "选择图片失败", icon: "none" });
},
});
};
// 标记用户已编辑手机号
const handleContactPhoneInput = () => {
hasEditedPhone.value = true;
};
const handleDeleteImage = () => {
contentImgUrl.value = "";
};
const updateImagehandle = (file) => {
if (!file) {
return;
}
updateImageFile(file).then((res) => {
contentImgUrl.value = res.data;
});
};
const handleCall = async () => {
if (isCallSuccess.value) {
// 查看工单
divWorkOrder();
return;
}
if (!roomId.value.trim()) {
uni.showToast({ title: "请填写所在位置", icon: "none" });
return;
}
const phoneToSubmit = hasEditedPhone.value
? contactPhone.value
: originalPhone.value;
if (!phoneToSubmit.trim()) {
uni.showToast({ title: "请填写联系电话", icon: "none" });
return;
}
if (!contactText.value.trim()) {
uni.showToast({ title: "请填写需求信息描述内容", icon: "none" });
return;
}
sendCreateWorkOrder(phoneToSubmit);
};
/// 创建工单
const sendCreateWorkOrder = async (phoneToSubmit) => {
try {
const params = {
workOrderTypeId: workOrderTypeId.value,
roomNo: roomId.value,
userPhone: phoneToSubmit,
content: contactText.value,
contentImgUrl: contentImgUrl.value,
};
console.log("🚀 ~ sendCreateWorkOrder ~ params:", params);
const res = await createWorkOrder(params);
if (res.code === 0) {
// 保存工单ID
workOrderId.value = res.data?.id || "";
// 设置成功状态
isCallSuccess.value = true;
uni.showToast({ title: "呼叫成功", icon: "success" });
} else {
uni.showToast({ title: res.message || "呼叫失败", icon: "none" });
}
} catch (error) {
uni.showToast({ title: "网络错误,请重试", icon: "none" });
}
};
// 查看工单
const divWorkOrder = () => {
// 这里可以跳转到工单详情页面
uni.navigateTo({
url: `/pages-service/order/list`,
});
};
onMounted(() => {
nextTick(() => {
setTimeout(() => {
uni.$emit(SCROLL_TO_BOTTOM, true);
}, 200);
});
});
</script>
<style scoped lang="scss">
@import "./styles/index.scss";
.close-btn {
top: 0;
right: 0;
}
</style>