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
|
Before Width: | Height: | Size: 782 B After Width: | Height: | Size: 782 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 689 B |
|
Before Width: | Height: | Size: 978 B After Width: | Height: | Size: 978 B |
|
Before Width: | Height: | Size: 816 B After Width: | Height: | Size: 816 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 713 B After Width: | Height: | Size: 713 B |
103
src/pages/order/list.vue
Normal 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>
|
||||
@@ -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>
|
||||
93
src/pages/service/index.vue
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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[];
|
||||
|
||||
|
||||