| | |
| | | </view> |
| | | <text |
| | | class="status" |
| | | :class="caseItem.reportStatus.replace('ed', '')" |
| | | :class="getStatusClass(caseItem.reportStatus)" |
| | | >{{ caseItem.statusText }}</text |
| | | > |
| | | </view> |
| | |
| | | 创建转运单 |
| | | </button> |
| | | |
| | | <!-- 需转运但未同意 --> |
| | | <!-- <button |
| | | v-if="caseItem.isTransport == '2' && !hasTransport(caseItem)" |
| | | class="transport-btn disabled" |
| | | disabled |
| | | > |
| | | 需先同意案例 |
| | | </button> --> |
| | | |
| | | <!-- 有转运单可查看 --> |
| | | <button |
| | | v-if="hasTransport(caseItem)" |
| | |
| | | <view class="actions"> |
| | | <button |
| | | class="action-btn" |
| | | v-if="caseItem.reportStatus != '1'" |
| | | v-if="caseItem.reportStatus == '1' || caseItem.reportStatus == '2'" |
| | | @tap.stop="withdrawCase(caseItem)" |
| | | > |
| | | 撤回 |
| | |
| | | </button> |
| | | <button |
| | | class="action-btn secondary" |
| | | v-if="caseItem.reportStatus != '1'" |
| | | v-if="caseItem.reportStatus == '1' || caseItem.reportStatus == '2'" |
| | | @tap.stop="editCase(caseItem)" |
| | | > |
| | | 编辑 |
| | |
| | | </view> |
| | | |
| | | <!-- 加载更多 --> |
| | | <view class="load-more" v-if="hasMore"> |
| | | <text>加载中...</text> |
| | | <view class="load-more" v-if="loadingMore"> |
| | | <u-loading-icon text="加载中..."></u-loading-icon> |
| | | </view> |
| | | |
| | | <!-- 无更多数据 --> |
| | | <view class="no-more" v-if="!hasMore && filteredCases.length > 0"> |
| | | <text>已加载全部数据</text> |
| | | </view> |
| | | |
| | | <!-- 空状态 --> |
| | | <view class="empty-state" v-if="!loading && filteredCases.length == 0"> |
| | | <image src="/static/empty/no-case.png" mode="aspectFit" /> |
| | | <text>暂无器官捐献案例记录</text> |
| | | </view> |
| | | |
| | | <!-- 加载状态 --> |
| | | <view class="empty-state" v-if="loading"> |
| | | <text>数据加载中...</text> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 加载状态 --> |
| | | <u-loading-page v-if="initLoading" :loading="true" text="数据加载中..." /> |
| | | </view> |
| | | <view class="float-button" @tap="createNewCase"> |
| | | <u-icon name="plus" color="#fff" size="24"></u-icon> |
| | | </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 dict = ref({}); |
| | | const loading = ref(false); |
| | | const initLoading = ref(false); |
| | | const loadingMore = ref(false); |
| | | const cases = ref([]); |
| | | const total = ref(0); |
| | | const pageNum = ref(1); |
| | |
| | | }; |
| | | |
| | | const statusInfo = statusMap[apiData.reportStatus] || statusMap["1"]; |
| | | |
| | | // 转运状态映射 |
| | | const getTransportStatusClass = (caseData) => { |
| | | if (!hasTransport(caseData)) { |
| | | return "not-transported"; |
| | | } |
| | | const status = getTransportStatus(caseData); |
| | | const map = { |
| | | 1: "pending", |
| | | 2: "transporting", |
| | | 3: "completed", |
| | | 4: "cancelled", |
| | | 5: "draft", |
| | | }; |
| | | return map[status] || "pending"; |
| | | }; |
| | | |
| | | return { |
| | | id: apiData.id || apiData.donatebaseinfoReportId, |
| | |
| | | }; |
| | | // 转运判断方法 - 与PC端保持一致 |
| | | const hasTransport = (caseData) => { |
| | | console.log(caseData.serviceTransport); |
| | | return caseData.serviceTransport && caseData.serviceTransport.length > 0; |
| | | }; |
| | | |
| | | const createNewCase = () => { |
| | | uni.navigateTo({ |
| | | url: '/pages/case/CaseDetails' |
| | | }); |
| | | }; |
| | | const canCreateTransport = (caseData) => { |
| | | return ( |
| | | (caseData.isTransport != "4" || caseData.isTransport == 2) && // 需要转运 |
| | | (caseData.isTransport == "2" || caseData.isTransport == 2) && // 需要转运 |
| | | !hasTransport(caseData) |
| | | ); // 无转运单 |
| | | }; |
| | |
| | | url: `/pages/case/transferinfo?caseId=${caseItem.id}&caseNo=${caseItem.donorNo}`, |
| | | }); |
| | | }; |
| | | |
| | | const getStatusClass = (status) => { |
| | | const map = { |
| | | '1': 'reported', // 已上报 |
| | | '2': 'read', // 已阅读 |
| | | '3': 'agreed', // 已同意 |
| | | '4': 'rejected' // 已驳回 |
| | | }; |
| | | return map[status] || 'reported'; |
| | | } |
| | | const viewTransportDetail = (caseItem) => { |
| | | if (hasTransport(caseItem)) { |
| | | const transport = caseItem.serviceTransport[0]; |
| | |
| | | |
| | | // 筛选相关 |
| | | const caseTypes = [ |
| | | { label: "全部", value: "" }, |
| | | { label: "全部", value: "all" }, |
| | | { label: "已上报", value: "1" }, |
| | | { label: "已阅读", value: "2" }, |
| | | { label: "已同意", value: "3" }, |
| | |
| | | const currentType = ref("all"); |
| | | const startDate = ref(""); |
| | | const endDate = ref(""); |
| | | |
| | | // 转运状态映射 |
| | | const transportStatusMap = { |
| | | not_transported: { |
| | | text: "未转运", |
| | | color: "warning", |
| | | class: "not-transported", |
| | | }, |
| | | transporting: { text: "转运中", color: "primary", class: "transporting" }, |
| | | completed: { text: "已完成", color: "success", class: "completed" }, |
| | | }; |
| | | |
| | | // 生命周期 |
| | | onLoad(async (options) => { |
| | |
| | | await loadInitialData(); |
| | | }); |
| | | |
| | | onReachBottom(() => { |
| | | if (hasMore.value && !loading.value && !loadingMore.value) { |
| | | onLoadMore(); |
| | | } |
| | | }); |
| | | |
| | | onShow(() => { |
| | | const transportUpdate = uni.getStorageSync("transportStatusUpdate"); |
| | | if (transportUpdate) { |
| | |
| | | |
| | | // 数据加载函数 |
| | | const loadInitialData = async () => { |
| | | loading.value = true; |
| | | initLoading.value = true; |
| | | try { |
| | | await Promise.all([donatebaseinforeportList(), donateTotal()]); |
| | | await Promise.all([donatebaseinforeportList(true), donateTotal()]); |
| | | } catch (error) { |
| | | console.error("初始化数据失败:", error); |
| | | } finally { |
| | | loading.value = false; |
| | | initLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // 获取案例列表 |
| | | const donatebaseinforeportList = async () => { |
| | | const donatebaseinforeportList = 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, |
| | | }; |
| | | |
| | | |
| | | // 筛选条件 - 如果选择了"全部",不传reportStatus参数 |
| | | if (currentType.value !== "all") { |
| | | params.reportStatus = 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/donatebaseinforeport/list", |
| | | params, |
| | | ); |
| | | console.log(res, "res"); |
| | | |
| | | const mappedData = res.map((item) => mapApiDataToCaseItem(item)); |
| | | |
| | | if (pageNum.value == 1) { |
| | | cases.value = mappedData; |
| | | |
| | | console.log("接口返回数据:", res); |
| | | |
| | | if (res.code == 200) { |
| | | const data =res.data || []; |
| | | const mappedData = data.map((item) => mapApiDataToCaseItem(item)); |
| | | |
| | | if (reset || pageNum.value == 1) { |
| | | console.log(mappedData,'mappedData'); |
| | | |
| | | cases.value = mappedData; |
| | | } else { |
| | | cases.value = [...cases.value, ...mappedData]; |
| | | } |
| | | |
| | | // 判断是否还有更多数据 |
| | | hasMore.value = data.length >= pageSize.value; |
| | | total.value = res.total || 0; |
| | | |
| | | // 如果有数据加载成功,增加页码 |
| | | if (data.length > 0) { |
| | | pageNum.value++; |
| | | } |
| | | } else { |
| | | cases.value = [...cases.value, ...mappedData]; |
| | | throw new Error(res.msg || "加载失败"); |
| | | } |
| | | |
| | | hasMore.value = pageNum.value * pageSize.value < res.total; |
| | | total.value = res.total; |
| | | } catch (error) { |
| | | console.error("获取案例列表失败:", error); |
| | | uni.showToast({ |
| | | title: "网络请求失败", |
| | | icon: "none", |
| | | }); |
| | | } finally { |
| | | loading.value = false; |
| | | loadingMore.value = false; |
| | | } |
| | | }; |
| | | |
| | |
| | | const donateTotal = async () => { |
| | | try { |
| | | const res = await uni.$uapi.post("/project/donatebaseinforeport/getTotal"); |
| | | stats.value = { |
| | | totalCases: res["all"] || 0, |
| | | readCases: res["2"] || 0, |
| | | agreedCases: res["3"] || 0, |
| | | }; |
| | | if (res.code === 200) { |
| | | stats.value = { |
| | | totalCases: res.data["all"] || 0, |
| | | readCases: res.data["2"] || 0, |
| | | agreedCases: res.data["3"] || 0, |
| | | }; |
| | | } else { |
| | | throw new Error(res.msg || "获取统计失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("获取统计数据失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // 计算属性:筛选记录 |
| | | // 计算属性:筛选记录 - 现在只做前端状态筛选 |
| | | const filteredCases = computed(() => { |
| | | let result = cases.value; |
| | | |
| | | if (currentType.value !== "all") { |
| | | result = result.filter( |
| | | (caseItem) => caseItem.reportStatus == currentType.value, |
| | | ); |
| | | } |
| | | |
| | | if (startDate.value && endDate.value) { |
| | | result = result.filter((caseItem) => { |
| | | const caseDate = caseItem.reportTime.split(" ")[0]; |
| | | return caseDate >= startDate.value && caseDate <= endDate.value; |
| | | }); |
| | | } |
| | | |
| | | |
| | | // 只做前端状态筛选,时间筛选已经通过接口实现 |
| | | // if (currentType.value !== "all") { |
| | | // result = result.filter( |
| | | // (caseItem) => caseItem.reportStatus == currentType.value, |
| | | // ); |
| | | // } |
| | | |
| | | return result; |
| | | }); |
| | | |
| | | // 事件处理函数 |
| | | const selectType = (type) => { |
| | | currentType.value = type; |
| | | // 重置分页,重新加载数据 |
| | | pageNum.value = 1; |
| | | donatebaseinforeportList(true); |
| | | }; |
| | | |
| | | const onStartDateChange = (e) => { |
| | | startDate.value = e.detail.value; |
| | | // 如果结束日期已选择,立即触发筛选 |
| | | if (endDate.value) { |
| | | pageNum.value = 1; |
| | | donatebaseinforeportList(true); |
| | | } |
| | | }; |
| | | |
| | | const onEndDateChange = (e) => { |
| | | endDate.value = e.detail.value; |
| | | // 如果开始日期已选择,立即触发筛选 |
| | | if (startDate.value) { |
| | | pageNum.value = 1; |
| | | donatebaseinforeportList(true); |
| | | } |
| | | }; |
| | | |
| | | // 刷新和加载更多 |
| | | const onRefresh = async () => { |
| | | refreshing.value = true; |
| | | pageNum.value = 1; |
| | | await donatebaseinforeportList(); |
| | | await donatebaseinforeportList(true); |
| | | await donateTotal(); |
| | | setTimeout(() => { |
| | | refreshing.value = false; |
| | | }, 1000); |
| | | }; |
| | | |
| | | const onLoadMore = async () => { |
| | | if (!hasMore.value || loading.value) return; |
| | | pageNum.value += 1; |
| | | if (!hasMore.value || loading.value || loadingMore.value) return; |
| | | await donatebaseinforeportList(); |
| | | }; |
| | | |
| | |
| | | showWithdrawModal.value = true; |
| | | }; |
| | | |
| | | const confirmWithdraw = () => { |
| | | const index = cases.value.findIndex( |
| | | (item) => item.id == currentCase.value.id, |
| | | ); |
| | | if (index !== -1) { |
| | | cases.value.splice(index, 1); |
| | | stats.value.totalCases -= 1; |
| | | const confirmWithdraw = async () => { |
| | | try { |
| | | const res = await uni.$uapi.delete(`/project/donatebaseinforeport/${currentCase.value.id}`); |
| | | |
| | | if (res.code === 200) { |
| | | // 从列表中移除 |
| | | const index = cases.value.findIndex( |
| | | (item) => item.id == currentCase.value.id |
| | | ); |
| | | if (index !== -1) { |
| | | cases.value.splice(index, 1); |
| | | stats.value.totalCases -= 1; |
| | | } |
| | | |
| | | uni.showToast({ |
| | | title: "撤回成功", |
| | | icon: "success", |
| | | }); |
| | | } else { |
| | | throw new Error(res.msg || "撤回失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("撤回失败:", error); |
| | | uni.showToast({ |
| | | title: "撤回成功", |
| | | icon: "success", |
| | | title: "撤回失败,请重试", |
| | | icon: "none", |
| | | }); |
| | | } finally { |
| | | showWithdrawModal.value = false; |
| | | } |
| | | showWithdrawModal.value = false; |
| | | }; |
| | | |
| | | const cancelWithdraw = () => { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | .load-more, .no-more { |
| | | text-align: center; |
| | | padding: 40rpx 0; |
| | | color: $text-secondary; |
| | | font-size: 28rpx; |
| | | } |
| | | |
| | | .empty-state { |
| | | padding: 120rpx 0; |
| | | text-align: center; |
| | |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | /* 浮动按钮样式 */ |
| | | .float-button { |
| | | position: fixed; |
| | | bottom: 120rpx; |
| | | right: 40rpx; |
| | | width: 100rpx; |
| | | height: 100rpx; |
| | | background: $primary-color; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 8rpx 20rpx rgba($primary-color, 0.3); |
| | | z-index: 100; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:active { |
| | | opacity: 0.8; |
| | | transform: scale(0.95); |
| | | } |
| | | } |
| | | </style> |