| | |
| | | <text |
| | | v-for="(type, index) in transportTypes" |
| | | :key="index" |
| | | :class="{ active: currentType === type.value }" |
| | | :class="{ active: currentType == type.value }" |
| | | @tap="selectType(type.value)" |
| | | >{{ type.label }}</text |
| | | > |
| | |
| | | </button> |
| | | <button |
| | | class="action-btn secondary" |
| | | v-if="item.transitStatus === 1 || item.transitStatus === 5" |
| | | v-if="item.transitStatus != 3" |
| | | @tap.stop="editTransport(item)" |
| | | > |
| | | 编辑 |
| | |
| | | </view> |
| | | |
| | | <!-- 加载更多 --> |
| | | <view class="load-more" v-if="loading"> |
| | | <view class="load-more" v-if="loadingMore"> |
| | | <u-loading-icon text="加载中..."></u-loading-icon> |
| | | </view> |
| | | |
| | | <!-- 无更多数据 --> |
| | | <view class="no-more" v-if="!hasMore && filteredTransports.length > 0"> |
| | | <text>已加载全部数据</text> |
| | | </view> |
| | | |
| | | <!-- 空状态 --> |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 加载状态 --> |
| | | <u-loading-page v-if="initLoading" :loading="true" text="数据加载中..." /> |
| | | |
| | | <!-- 浮动按钮 --> |
| | | <!-- <view class="float-button" @tap="createTransport"> |
| | | <u-icon name="plus" color="#fff" size="24"></u-icon> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted } from "vue"; |
| | | import { onLoad, onShow } from "@dcloudio/uni-app"; |
| | | import { onLoad, onShow, onReachBottom } from "@dcloudio/uni-app"; |
| | | import { useDict } from "@/utils/dict"; |
| | | |
| | | // 字典数据 |
| | |
| | | // 转运单数据 |
| | | const transports = ref([]); |
| | | const loading = ref(false); |
| | | const initLoading = ref(false); |
| | | const loadingMore = ref(false); |
| | | const refreshing = ref(false); |
| | | const hasMore = ref(true); |
| | | const pageNum = ref(1); |
| | |
| | | // 获取字典数据 |
| | | dict.value = await useDict("sys_user_sex"); |
| | | // 初始化数据 |
| | | loadTransports(); |
| | | // 加载统计数据 |
| | | loadStats(); |
| | | await loadInitialData(); |
| | | }); |
| | | |
| | | onReachBottom(() => { |
| | | if (hasMore.value && !loading.value && !loadingMore.value) { |
| | | onLoadMore(); |
| | | } |
| | | }); |
| | | |
| | | onShow(() => { |
| | |
| | | }; |
| | | }; |
| | | |
| | | // 筛选记录 |
| | | // 计算属性:筛选记录 |
| | | const filteredTransports = computed(() => { |
| | | let result = transports.value; |
| | | |
| | | // 状态筛选 |
| | | |
| | | // 前端状态筛选 |
| | | if (currentType.value !== "") { |
| | | result = result.filter((item) => item.transitStatus === currentType.value); |
| | | } |
| | | |
| | | // 日期筛选 |
| | | if (startDate.value && endDate.value) { |
| | | result = result.filter((item) => { |
| | | const transportDate = item.createTime |
| | | ? item.createTime.split(" ")[0] |
| | | : ""; |
| | | return transportDate >= startDate.value && transportDate <= endDate.value; |
| | | }); |
| | | } |
| | | |
| | | |
| | | return result; |
| | | }); |
| | | |
| | |
| | | // 选择类型 |
| | | const selectType = (type) => { |
| | | currentType.value = type; |
| | | // 重置分页,重新加载数据 |
| | | pageNum.value = 1; |
| | | loadTransports(true); |
| | | }; |
| | | |
| | | // 日期选择 |
| | | const onStartDateChange = (e) => { |
| | | startDate.value = e.detail.value; |
| | | // 如果结束日期已选择,立即触发筛选 |
| | | if (endDate.value) { |
| | | pageNum.value = 1; |
| | | loadTransports(true); |
| | | } |
| | | }; |
| | | |
| | | const onEndDateChange = (e) => { |
| | | endDate.value = e.detail.value; |
| | | // 如果开始日期已选择,立即触发筛选 |
| | | if (startDate.value) { |
| | | pageNum.value = 1; |
| | | loadTransports(true); |
| | | } |
| | | }; |
| | | |
| | | // 查看详情 |
| | |
| | | // 查看详情 |
| | | const viewDetails = (item) => { |
| | | uni.navigateTo({ |
| | | url: `/pages/transport/detail?id=${item.id}`, |
| | | url: `/pages/case/transferinfo?id=${item.id}`, |
| | | }); |
| | | }; |
| | | |
| | | // 编辑转运单 |
| | | const editTransport = (item) => { |
| | | uni.navigateTo({ |
| | | url: `/pages/transport/detail?id=${item.id}&edit=true`, |
| | | url: `/pages/case/transferinfo?id=${item.id}&edit=true`, |
| | | }); |
| | | }; |
| | | |
| | | // 创建转运单 |
| | | const createTransport = () => { |
| | | uni.navigateTo({ |
| | | url: '/pages/transport/create' |
| | | }); |
| | | }; |
| | | |
| | |
| | | showActionModal.value = false; |
| | | }; |
| | | |
| | | // 数据加载函数 |
| | | const loadInitialData = async () => { |
| | | initLoading.value = true; |
| | | try { |
| | | await Promise.all([loadTransports(true), loadStats()]); |
| | | } catch (error) { |
| | | console.error("初始化数据失败:", error); |
| | | } finally { |
| | | initLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // 下拉刷新 |
| | | const onRefresh = () => { |
| | | const onRefresh = async () => { |
| | | refreshing.value = true; |
| | | pageNum.value = 1; |
| | | loadTransports(); |
| | | loadStats(); |
| | | await loadTransports(true); |
| | | await loadStats(); |
| | | setTimeout(() => { |
| | | refreshing.value = false; |
| | | }, 1000); |
| | | }; |
| | | |
| | | // 加载更多 |
| | | const onLoadMore = () => { |
| | | if (!hasMore.value || loading.value) return; |
| | | pageNum.value++; |
| | | loadTransports(); |
| | | const onLoadMore = async () => { |
| | | if (!hasMore.value || loading.value || loadingMore.value) return; |
| | | await loadTransports(); |
| | | }; |
| | | |
| | | // 加载记录 |
| | | const loadTransports = async () => { |
| | | if (loading.value) return; |
| | | |
| | | loading.value = true; |
| | | // 加载转运单列表 |
| | | const loadTransports = async (reset = false) => { |
| | | if (reset) { |
| | | pageNum.value = 1; |
| | | hasMore.value = true; |
| | | } |
| | | |
| | | if (loading.value || loadingMore.value || !hasMore.value) return; |
| | | |
| | | if (reset) { |
| | | loading.value = true; |
| | | } else { |
| | | loadingMore.value = true; |
| | | } |
| | | |
| | | try { |
| | | const params = { |
| | | pageNum: pageNum.value, |
| | | pageSize: pageSize.value, |
| | | }; |
| | | |
| | | if (currentType.value) { |
| | | |
| | | // 筛选条件 |
| | | if (currentType.value !== "") { |
| | | params.transitStatus = currentType.value; |
| | | } |
| | | |
| | | |
| | | // 时间筛选条件 |
| | | if (startDate.value && endDate.value) { |
| | | params.startDate = startDate.value; |
| | | params.endDate = endDate.value; |
| | | } |
| | | |
| | | |
| | | console.log("请求参数:", params); |
| | | |
| | | const res = await uni.$uapi.post("/project/transport/list", params); |
| | | |
| | | if (res) { |
| | | const data = res || []; |
| | | |
| | | console.log("接口返回数据:", res); |
| | | |
| | | if (res && res.code === 200) { |
| | | // 处理不同的数据结构 |
| | | let data = []; |
| | | |
| | | if (res.rows && Array.isArray(res.rows)) { |
| | | data = res.rows; |
| | | } else if (res.data && Array.isArray(res.data)) { |
| | | data = res.data; |
| | | } else if (Array.isArray(res)) { |
| | | data = res; |
| | | } else { |
| | | console.error("接口返回格式不正确:", res); |
| | | throw new Error("接口返回格式不正确"); |
| | | } |
| | | |
| | | const mappedData = data.map((item) => mapApiDataToTransportItem(item)); |
| | | |
| | | if (pageNum.value === 1) { |
| | | |
| | | if (reset || pageNum.value === 1) { |
| | | transports.value = mappedData; |
| | | } else { |
| | | transports.value = [...transports.value, ...mappedData]; |
| | | } |
| | | |
| | | hasMore.value = (res.rows || []).length >= pageSize.value; |
| | | |
| | | // 判断是否还有更多数据 |
| | | hasMore.value = data.length >= pageSize.value; |
| | | |
| | | // 如果有数据加载成功,增加页码 |
| | | if (data.length > 0) { |
| | | pageNum.value++; |
| | | } |
| | | } else { |
| | | throw new Error(res.msg || "加载失败"); |
| | | throw new Error(res?.msg || "加载失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("加载转运单列表失败:", error); |
| | |
| | | }); |
| | | } finally { |
| | | loading.value = false; |
| | | loadingMore.value = false; |
| | | } |
| | | }; |
| | | |
| | |
| | | const loadStats = async () => { |
| | | try { |
| | | const res = await uni.$uapi.post("/api/totalServiceTransportState"); |
| | | if (res) { |
| | | if (res.data) { |
| | | stats.value = { |
| | | totalTransports: res.reduce((sum, item) => sum + item.count, 0) || 0, |
| | | pendingTransports: res[0].count || 0, |
| | | completedTransports: res[3].count || 0, |
| | | totalTransports: |
| | | res.data.reduce((sum, item) => sum + item.count, 0) || 0, |
| | | pendingTransports: res.data[0].count || 0, |
| | | completedTransports: res.data[3].count || 0, |
| | | }; |
| | | } |
| | | } catch (error) { |
| | |
| | | id: currentTransport.value.id, |
| | | transitStatus: newStatus, |
| | | }; |
| | | |
| | | |
| | | const res = await uni.$uapi.post("/project/transport/edit", updateData); |
| | | |
| | | if (res.code === 200) { |
| | | |
| | | if (res && res.code === 200) { |
| | | // 更新本地数据 |
| | | const index = transports.value.findIndex( |
| | | (item) => item.id === currentTransport.value.id, |
| | |
| | | if (index !== -1) { |
| | | transports.value[index].transitStatus = newStatus; |
| | | } |
| | | |
| | | |
| | | // 更新统计数据 |
| | | await loadStats(); |
| | | |
| | | |
| | | // 存储状态更新 |
| | | uni.setStorageSync("transportStatusUpdate", { |
| | | orderId: currentTransport.value.id, |
| | | status: newStatus, |
| | | }); |
| | | |
| | | |
| | | return true; |
| | | } else { |
| | | throw new Error(res.msg || `${actionName}失败`); |
| | | throw new Error(res?.msg || `${actionName}失败`); |
| | | } |
| | | } catch (error) { |
| | | console.error(`${actionName}失败:`, error); |
| | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | /* 保持原有样式完全不变 */ |
| | | .transport-record { |
| | | min-height: 100vh; |
| | | background: linear-gradient(135deg, #fafdff 0%, #e3f0ff 100%); |
| | | padding-bottom: 100rpx; |
| | | |
| | | .stats-card { |
| | | margin: 20rpx; |
| | |
| | | } |
| | | } |
| | | |
| | | .load-more, .no-more { |
| | | text-align: center; |
| | | padding: 40rpx 0; |
| | | color: #86868b; |
| | | font-size: 28rpx; |
| | | } |
| | | |
| | | .empty-state { |
| | | padding: 120rpx 0; |
| | | text-align: center; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* 浮动按钮 */ |
| | | .float-button { |
| | | position: fixed; |
| | | bottom: 100rpx; |
| | | right: 40rpx; |
| | | width: 100rpx; |
| | | height: 100rpx; |
| | | background: #0071e3; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 8rpx 20rpx rgba(0, 113, 227, 0.3); |
| | | z-index: 100; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:active { |
| | | opacity: 0.8; |
| | | transform: scale(0.95); |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | </style> |