feat(order&service): add order and service ticket management features

- Restructure page file structure for order and service modules
- Update router configurations to match new correct file paths
- Add complete reusable component set for order display, detail viewing, payment, voucher verification and status tracking
- Add necessary SCSS styles and image assets for the new pages
- Refactor legacy order and service page implementations to modern component-based architecture
This commit is contained in:
DEV_DSW
2026-06-01 15:05:41 +08:00
parent 1060ed67c3
commit 896cbec8d2
31 changed files with 201 additions and 128 deletions

View File

Before

Width:  |  Height:  |  Size: 782 B

After

Width:  |  Height:  |  Size: 782 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 689 B

After

Width:  |  Height:  |  Size: 689 B

View File

Before

Width:  |  Height:  |  Size: 978 B

After

Width:  |  Height:  |  Size: 978 B

View File

Before

Width:  |  Height:  |  Size: 816 B

After

Width:  |  Height:  |  Size: 816 B

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 713 B

After

Width:  |  Height:  |  Size: 713 B

103
src/pages/order/list.vue Normal file
View File

@@ -0,0 +1,103 @@
<template>
<div class="flex h-dvh flex-col overflow-hidden bg-linear-[180deg,#E8FFF1_0%,#F5F7FA_186px]">
<TopNavBar title="全部订单" />
<div class="min-h-0 flex-1 overflow-y-auto scrollbar-none [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden">
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
<CustomEmpty v-if="showEmpty" statusText="您暂无订单" />
<van-list v-else v-model:loading="loading" v-model:error="listError" :finished="finished"
:immediate-check="false" finished-text="没有更多了" error-text="加载失败点击重试" @load="onLoad">
<OrderCard v-for="(item, index) in dataList" :key="item.id || index" :orderData="item"
@click="handleOrderClick" />
</van-list>
</van-pull-refresh>
</div>
</div>
</template>
<script setup>
import { computed, onMounted, ref } from "vue";
import { useRouter } from 'vue-router'
import { userOrderList } from "@/api/order";
import TopNavBar from "@/components/TopNavBar/index.vue";
import CustomEmpty from "@/components/CustomEmpty/index.vue";
import OrderCard from "./components/OrderCard/index.vue";
const router = useRouter()
const PAGE_SIZE = 10;
const dataList = ref([]);
const currentPage = ref(1);
const loading = ref(false);
const finished = ref(false);
const refreshing = ref(false);
const listError = ref(false);
const showEmpty = computed(() => {
return !loading.value && !refreshing.value && finished.value && dataList.value.length === 0;
});
const finishLoading = () => {
loading.value = false;
refreshing.value = false;
};
const queryList = async (pageNum = currentPage.value, pageSize = PAGE_SIZE) => {
try {
const res = await userOrderList({ pageNum, pageSize });
console.log("API响应:", res);
const records = Array.isArray(res?.data?.records) ? res.data.records : [];
const total = Number(res?.data?.total ?? 0);
const hasTotal = Number.isFinite(total) && total > 0;
if (pageNum === 1) {
dataList.value = records;
} else {
dataList.value = [...dataList.value, ...records];
}
finished.value =
records.length < pageSize || (hasTotal && dataList.value.length >= total);
if (!finished.value) {
currentPage.value = pageNum + 1;
}
listError.value = false;
} catch (error) {
console.error("查询列表失败:", error);
listError.value = true;
} finally {
finishLoading();
}
};
const reloadList = () => {
currentPage.value = 1;
finished.value = false;
listError.value = false;
loading.value = true;
queryList(1);
};
const onLoad = () => {
queryList();
};
const onRefresh = () => {
reloadList();
};
// 处理订单点击
const handleOrderClick = ({ orderId }) => {
router.push({
name: "order_detail",
query: { orderId },
});
};
onMounted(() => {
reloadList();
});
</script>
<style scoped lang="scss"></style>

View File

@@ -1,69 +0,0 @@
<template>
<z-paging :bg-color="'linear-gradient(180deg, ' +
$theme -
color -
100 +
' 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 statusspan="您暂无订单" />
</template>
<OrderCard v-for="(item, index) in dataList" :key="item.id || index" :orderData="item" @click="handleOrderClick" />
</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 { userOrderList } from "@/api/order";
const dataList = ref([]);
const paging = ref(null);
const queryList = async (pageNum, pageSize) => {
try {
const res = await userOrderList({ 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);
}
};
// 处理订单点击
const handleOrderClick = ({ orderId }) => {
// 这里可以添加订单详情跳转逻辑
uni.navigateTo({
url: `/pages-order/order/detail?orderId=${orderId}`,
events: {
refreshOrderList: (event) => {
console.log("订单详情页面请求刷新订单列表", event);
if (event.success) {
queryList(1, 10);
}
},
},
});
};
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,93 @@
<template>
<div class="flex h-dvh flex-col overflow-hidden bg-linear-[180deg,#E8FFF1_0%,#F5F7FA_186px]">
<TopNavBar title="呼叫服务" />
<div class="min-h-0 flex-1 overflow-y-auto scrollbar-none [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden">
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
<CustomEmpty v-if="showEmpty" emptyIcon="https://oss.nianxx.cn/mp/static/version_101/order/service_empty.png"
statusText="您暂无呼叫服务" />
<van-list v-else v-model:loading="loading" v-model:error="listError" :finished="finished"
:immediate-check="false" finished-text="没有更多了" error-text="加载失败点击重试" @load="onLoad">
<OrderCard v-for="(item, index) in dataList" :key="item.id || index" :orderData="item" />
</van-list>
</van-pull-refresh>
</div>
</div>
</template>
<script setup>
import { computed, onMounted, ref } from "vue";
import { userWorkOrderList } from "@/api/workOrder";
import TopNavBar from "@/components/TopNavBar/index.vue";
import CustomEmpty from "@/components/CustomEmpty/index.vue";
import OrderCard from "./components/OrderCard/index.vue";
const PAGE_SIZE = 10;
const dataList = ref([]);
const currentPage = ref(1);
const loading = ref(false);
const finished = ref(false);
const refreshing = ref(false);
const listError = ref(false);
const showEmpty = computed(() => {
return !loading.value && !refreshing.value && finished.value && dataList.value.length === 0;
});
const finishLoading = () => {
loading.value = false;
refreshing.value = false;
};
const queryList = async (pageNum = currentPage.value, pageSize = PAGE_SIZE) => {
try {
const res = await userWorkOrderList({ pageNum, pageSize });
console.log("API响应:", res);
const records = Array.isArray(res?.data?.records) ? res.data.records : [];
const total = Number(res?.data?.total ?? 0);
const hasTotal = Number.isFinite(total) && total > 0;
if (pageNum === 1) {
dataList.value = records;
} else {
dataList.value = [...dataList.value, ...records];
}
finished.value =
records.length < pageSize || (hasTotal && dataList.value.length >= total);
if (!finished.value) {
currentPage.value = pageNum + 1;
}
listError.value = false;
} catch (error) {
console.error("查询列表失败:", error);
listError.value = true;
} finally {
finishLoading();
}
};
const reloadList = () => {
currentPage.value = 1;
finished.value = false;
listError.value = false;
loading.value = true;
queryList(1);
};
const onLoad = () => {
queryList();
};
const onRefresh = () => {
reloadList();
};
onMounted(() => {
reloadList();
});
</script>
<style scoped lang="scss"></style>

View File

@@ -1,54 +0,0 @@
<template>
<z-paging :bg-color="'linear-gradient(180deg, ' +
$theme -
color -
100 +
' 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 emptyIcon="https://oss.nianxx.cn/mp/static/version_101/order/service_empty.png"
statusspan="您暂无呼叫服务" />
</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 "@/api/workOrder";
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>

View File

@@ -40,17 +40,17 @@ export const routes = [
{
path: "/order",
name: "orderList",
component: () => import("@/pages/order/order/list.vue"),
component: () => import("@/pages/order/list.vue"),
},
{
path: "/order/detail",
name: "order_detail",
component: () => import("@/pages/order/order/detail.vue"),
component: () => import("@/pages/order/detail.vue"),
},
{
path: "/service/order",
name: "service_order",
component: () => import("@/pages/service/order/index.vue"),
path: "/service",
name: "service",
component: () => import("@/pages/service/index.vue"),
},
] satisfies RouteRecordRaw[];