<template>
|
<view class="ethics-review-list">
|
<!-- 统计卡片 -->
|
<view class="stats-card">
|
<view class="stat-item">
|
<text class="count">{{ stats.count }}</text>
|
<text class="label">总审查量</text>
|
</view>
|
<view class="divider"></view>
|
<view class="stat-item">
|
<text class="count">{{ stats.throughCount }}</text>
|
<text class="label">审查通过</text>
|
</view>
|
<view class="divider"></view>
|
<view class="stat-item">
|
<text class="count">{{ stats.rejectCount }}</text>
|
<text class="label">审查驳回</text>
|
</view>
|
<view class="divider"></view>
|
<view class="stat-item">
|
<text class="count">{{ stats.waiveCount }}</text>
|
<text class="label">已放弃</text>
|
</view>
|
</view>
|
|
<!-- 筛选栏 -->
|
<view class="filter-bar">
|
<view class="status-filter">
|
<text
|
v-for="status in statusOptions"
|
:key="status.value"
|
:class="{ active: currentStatus == status.value }"
|
@tap="selectStatus(status.value)"
|
>
|
{{ status.label }}
|
</text>
|
</view>
|
|
<view class="search-filter">
|
<u-input
|
v-model="searchKeyword"
|
placeholder="搜索捐献者姓名或住院号"
|
prefix-icon="search"
|
clearable
|
@confirm="handleSearch"
|
></u-input>
|
</view>
|
</view>
|
|
<!-- 审查记录列表 -->
|
<scroll-view
|
scroll-y
|
class="review-list"
|
refresher-enabled
|
:refresher-triggered="refreshing"
|
@refresherrefresh="onRefresh"
|
@scrolltolower="onLoadMore"
|
>
|
<view
|
v-for="(review, index) in reviewList"
|
:key="review.id || index"
|
class="review-item card"
|
@tap="viewDetail(review)"
|
>
|
<!-- 头部信息 -->
|
<view class="review-header">
|
<view class="case-info">
|
<view class="hospital-badge">
|
<u-icon name="order" size="16" color="#fff" />
|
</view>
|
<view class="info-content">
|
<text class="donor-name">{{ review.name || "未填写姓名" }}</text>
|
<text class="hospital-no">{{
|
review.inpatientno || "无住院号"
|
}}</text>
|
<text class="expert-type" v-if="review.expertname">
|
专家: {{ review.expertname }}
|
</text>
|
</view>
|
</view>
|
<view class="status-tag" :class="getReviewStatusClass(review)">
|
{{ getReviewStatusText(review) }}
|
</view>
|
</view>
|
|
<!-- 基本信息 -->
|
<view class="basic-info">
|
<view class="info-row">
|
<view class="info-col">
|
<text class="info-label">性别/年龄</text>
|
<text class="info-value"
|
>{{ review.sex == 1 ? "男" : "女" }}/{{
|
getAgeWithUnit(review)
|
}}</text
|
>
|
</view>
|
<view class="info-col">
|
<text class="info-label">血型</text>
|
<text class="info-value">{{
|
getDictLabel("sys_BloodType", review.bloodtype) || "未知"
|
}}</text>
|
</view>
|
<view class="info-col">
|
<text class="info-label">疾病诊断</text>
|
<text class="info-value">{{
|
review.diagnosisname || "未填写"
|
}}</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 审查详情 -->
|
<view class="review-details">
|
<view class="detail-item" v-if="review.createTime">
|
<u-icon name="clock" size="14" color="#909399" />
|
<text class="detail-text"
|
>创建时间:{{ formatDate(review.createTime) }}</text
|
>
|
</view>
|
<view class="detail-item" v-if="review.conclusiontime">
|
<u-icon name="checkmark-circle" size="14" color="#909399" />
|
<text class="detail-text"
|
>审查时间:{{ formatDate(review.conclusiontime) }}</text
|
>
|
</view>
|
<view class="detail-item" v-if="review.expertname">
|
<u-icon name="account" size="14" color="#909399" />
|
<text class="detail-text">审查人:{{ review.expertname }}</text>
|
</view>
|
</view>
|
|
<!-- 审查结论 -->
|
<view
|
class="conclusion-section"
|
v-if="review.expertconclusion && review.expertconclusion !== 2"
|
>
|
<text class="conclusion-label">审查结论:</text>
|
<text class="conclusion-content">{{
|
getConclusionText(review.expertconclusion)
|
}}</text>
|
</view>
|
|
<!-- 专家意见 -->
|
<view class="opinion-section" v-if="review.expertopinion">
|
<text class="opinion-label">专家意见:</text>
|
<text class="opinion-content">{{ review.expertopinion }}</text>
|
</view>
|
|
<!-- 操作按钮 -->
|
<view class="action-buttons">
|
<button class="action-btn detail-btn" @tap.stop="viewDetail(review)">
|
<u-icon name="eye" size="14" color="#747CF9" />
|
<text>查看详情</text>
|
</button>
|
|
<button
|
v-if="review.expertconclusion == 1"
|
class="action-btn download-btn"
|
@tap.stop="downloadReport(review)"
|
>
|
<u-icon name="download" size="14" color="#52c41a" />
|
<text>下载报告</text>
|
</button>
|
|
<button
|
v-if="review.expertconclusion == 2"
|
class="action-btn appeal-btn"
|
@tap.stop="submitAppeal(review)"
|
>
|
<u-icon name="arrow-up" size="14" color="#fa8c16" />
|
<text>提起申诉</text>
|
</button>
|
|
<button
|
v-if="review.expertconclusion == 2 || review.expertconclusion == 3"
|
class="action-btn restart-btn"
|
@tap.stop="restartReview(review)"
|
>
|
<u-icon name="play-circle" size="14" color="#747CF9" />
|
<text>重新开始</text>
|
</button>
|
</view>
|
</view>
|
|
<!-- 加载状态 -->
|
<u-loading-icon :show="loading" text="加载中..."></u-loading-icon>
|
|
<!-- 空状态 -->
|
<view class="empty-state" v-if="!loading && reviewList.length == 0">
|
<view> {{ loading }}-{{ reviewList.length }} </view>
|
<u-icon name="file-remove" size="80" color="#C0C4CC" />
|
<text class="empty-text">暂无审查记录</text>
|
<text class="empty-desc">当前筛选条件下没有找到相关记录</text>
|
<button class="empty-action" @tap="resetFilters">
|
<text>重置筛选条件</text>
|
</button>
|
</view>
|
|
<!-- 加载完成提示 -->
|
<view class="load-complete" v-if="!hasMore && reviewList.length > 0">
|
<text>已加载全部数据</text>
|
</view>
|
</scroll-view>
|
</view>
|
</template>
|
|
<script setup>
|
import { ref, computed, onMounted, watch } from "vue";
|
import {
|
onLoad,
|
onShow,
|
onPullDownRefresh,
|
onReachBottom,
|
} from "@dcloudio/uni-app";
|
import { useDict } from "@/utils/dict";
|
|
// 响应式数据
|
const loading = ref(false);
|
const refreshing = ref(false);
|
const hasMore = ref(true);
|
const pageNum = ref(1);
|
const pageSize = ref(10);
|
const dict = ref({});
|
|
// 筛选条件
|
const currentStatus = ref("all");
|
const searchKeyword = ref("");
|
|
// 统计数据
|
const stats = ref({
|
count: 0,
|
throughCount: 0,
|
rejectCount: 0,
|
waiveCount: 0,
|
});
|
|
// 审查列表数据
|
const reviewList = ref([]);
|
const total = ref(0);
|
|
// 状态选项
|
const statusOptions = ref([
|
{ label: "全部", value: "all" },
|
{ label: "待审查", value: "pending" },
|
{ label: "审查通过", value: "approved" },
|
{ label: "审查驳回", value: "rejected" },
|
{ label: "已放弃", value: "abandoned" },
|
]);
|
|
// 字典映射
|
const statusDict = {
|
pending: "待审查",
|
approved: "审查通过",
|
rejected: "审查驳回",
|
abandoned: "已放弃",
|
};
|
|
// 结论映射
|
const conclusionDict = {
|
0: "未审核",
|
1: "审查通过",
|
2: "审查驳回",
|
3: "放弃",
|
4: "修改后同意",
|
};
|
|
// 获取字典标签
|
const getDictLabel = (dictType, dictValue) => {
|
if (!dict.value[dictType] || !dictValue) return "";
|
const dictItem = dict.value[dictType].find(
|
(item) => item.dictValue == String(dictValue),
|
);
|
return dictItem ? dictItem.dictLabel : dictValue;
|
};
|
|
// 获取年龄和单位
|
const getAgeWithUnit = (review) => {
|
if (!review.age) return "未知";
|
const unit = getDictLabel("sys_AgeUnit", review.ageunit) || "岁";
|
return `${review.age}${unit}`;
|
};
|
|
// 格式化日期
|
const formatDate = (dateString) => {
|
if (!dateString) return "";
|
const date = new Date(dateString);
|
return `${date.getFullYear()}-${(date.getMonth() + 1)
|
.toString()
|
.padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")} ${date
|
.getHours()
|
.toString()
|
.padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
|
};
|
|
// 获取审查状态文本
|
const getReviewStatusText = (review) => {
|
if (review.receiveStatus == 0) return "待推送";
|
if (review.receiveStatus == 1) return "未阅读";
|
if (review.receiveStatus == 2) return "已阅读";
|
if (review.receiveStatus == 3) return "超时";
|
if (review.receiveStatus == 4) return "中止";
|
if (review.receiveStatus == 5) return "完成";
|
if (!review.receiveStatus && review.receiveStatus !== 0) return "待推送";
|
return "待推送";
|
};
|
|
// 获取审查状态类名
|
const getReviewStatusClass = (review) => {
|
if (review.receiveStatus == 0) return "abandoned";
|
if (review.receiveStatus == 1) return "abandoned";
|
if (review.receiveStatus == 2) return "pending";
|
if (review.receiveStatus == 3) return "unknown";
|
if (review.receiveStatus == 4) return "unknown";
|
if (review.receiveStatus == 5) return "approved";
|
if (!review.receiveStatus && review.receiveStatus !== 0) return "pending";
|
return "unknown";
|
};
|
|
// 获取结论文本
|
const getConclusionText = (conclusion) => {
|
return conclusionDict[conclusion] || "未知结论";
|
};
|
|
// 方法
|
const selectStatus = (status) => {
|
currentStatus.value = status;
|
resetAndLoad();
|
};
|
|
const handleSearch = () => {
|
resetAndLoad();
|
};
|
|
const resetFilters = () => {
|
currentStatus.value = "all";
|
searchKeyword.value = "";
|
resetAndLoad();
|
};
|
|
// 构建查询参数
|
const buildQueryParams = () => {
|
const params = {
|
pageNum: pageNum.value,
|
pageSize: pageSize.value,
|
// receiveStatus: "1,2,3,4,5",
|
};
|
|
// 添加搜索关键词
|
if (searchKeyword.value) {
|
params.name = searchKeyword.value;
|
}
|
|
// 添加状态筛选
|
if (currentStatus.value !== "all") {
|
switch (currentStatus.value) {
|
case "pending":
|
// 待审查:expertconclusion为空
|
params.expertconclusion = null;
|
break;
|
case "approved":
|
params.expertconclusion = 1; // 同意
|
break;
|
case "rejected":
|
params.expertconclusion = 2; // 不同意
|
break;
|
case "abandoned":
|
params.expertconclusion = 3; // 放弃
|
break;
|
}
|
}
|
|
return params;
|
};
|
|
// 重置并加载
|
const resetAndLoad = () => {
|
pageNum.value = 1;
|
hasMore.value = true;
|
loadCaseData();
|
};
|
|
// 下拉刷新
|
const onRefresh = async () => {
|
refreshing.value = true;
|
await resetAndLoad();
|
refreshing.value = false;
|
};
|
|
// 上拉加载更多
|
const onLoadMore = async () => {
|
if (!hasMore.value || loading.value) return;
|
pageNum.value++;
|
await loadCaseData(true);
|
};
|
|
// 统计
|
const stateTotal = async () => {
|
const resTotal = await uni.$uapi.get(
|
`/project/ethicalreviewopinions/stateTotal`,
|
);
|
if (resTotal.code == 200)
|
// 更新统计数据
|
stats.value = resTotal.data[0];
|
};
|
// 加载案例数据
|
const loadCaseData = async (isLoadMore = false) => {
|
if (loading.value) return;
|
|
loading.value = true;
|
|
try {
|
const params = buildQueryParams();
|
|
const res = await uni.$uapi.get(
|
`/project/ethicalreviewopinions/listnew`,
|
params,
|
);
|
|
console.log(res, "11");
|
|
if (res.code == 200) {
|
const list = res.rows || [];
|
const totalCount = res.total || 0;
|
|
if (isLoadMore) {
|
reviewList.value = [...reviewList.value, ...list];
|
} else {
|
reviewList.value = list;
|
}
|
console.log(reviewList.value, "reviewList.value");
|
|
total.value = totalCount;
|
hasMore.value = reviewList.value.length < totalCount;
|
} else {
|
uni.showToast({
|
title: res.msg || "加载失败",
|
icon: "none",
|
});
|
}
|
} catch (error) {
|
console.error("加载案例数据失败:", error);
|
uni.showToast({
|
title: "数据加载失败,请重试",
|
icon: "none",
|
});
|
} finally {
|
loading.value = false;
|
uni.stopPullDownRefresh();
|
}
|
};
|
|
// 查看详情
|
const viewDetail = (review) => {
|
uni.navigateTo({
|
url: `/pages/ethicalReview/ethicalInfo?fcid=${
|
review.fcid
|
}&type=review&status=${review.expertconclusion || "pending"}&id=${
|
review.id
|
}`,
|
});
|
};
|
|
// 下载报告
|
const downloadReport = async (review) => {
|
if (!review.conclusionannex) {
|
uni.showToast({
|
title: "暂无报告可下载",
|
icon: "none",
|
});
|
return;
|
}
|
|
try {
|
const annexes = review.conclusionannex
|
.split(";")
|
.filter((item) => item.trim());
|
|
if (annexes.length == 0) {
|
uni.showToast({
|
title: "暂无报告可下载",
|
icon: "none",
|
});
|
return;
|
}
|
|
uni.showLoading({
|
title: "下载中...",
|
mask: true,
|
});
|
|
// 下载第一个附件
|
const fileUrl = annexes[0];
|
const downloadTask = uni.downloadFile({
|
url: fileUrl,
|
success: (downloadRes) => {
|
if (downloadRes.statusCode == 200) {
|
const tempFilePath = downloadRes.tempFilePath;
|
|
// 保存到本地
|
uni.saveFile({
|
tempFilePath: tempFilePath,
|
success: (saveRes) => {
|
uni.hideLoading();
|
uni.showToast({
|
title: "下载成功",
|
icon: "success",
|
duration: 2000,
|
});
|
|
// 在微信小程序中可以打开文件
|
if (uni.getSystemInfoSync().platform == "weixin") {
|
uni.openDocument({
|
filePath: saveRes.savedFilePath,
|
showMenu: true,
|
success: () => {
|
console.log("打开文档成功");
|
},
|
fail: (err) => {
|
console.error("打开文档失败", err);
|
},
|
});
|
}
|
},
|
fail: (saveErr) => {
|
uni.hideLoading();
|
uni.showToast({
|
title: "保存文件失败",
|
icon: "error",
|
duration: 2000,
|
});
|
},
|
});
|
} else {
|
uni.hideLoading();
|
uni.showToast({
|
title: "下载失败",
|
icon: "error",
|
duration: 2000,
|
});
|
}
|
},
|
fail: (err) => {
|
uni.hideLoading();
|
uni.showToast({
|
title: "下载失败",
|
icon: "error",
|
duration: 2000,
|
});
|
console.error("下载文件失败:", err);
|
},
|
});
|
|
// 监听下载进度
|
downloadTask.onProgressUpdate((res) => {
|
console.log("下载进度:", res.progress);
|
});
|
} catch (error) {
|
uni.hideLoading();
|
console.error("下载报告失败:", error);
|
uni.showToast({
|
title: "下载失败",
|
icon: "error",
|
duration: 2000,
|
});
|
}
|
};
|
|
// 提起申诉
|
const submitAppeal = (review) => {
|
uni.navigateTo({
|
url: `/pages/ethics/appeal?id=${review.fcid || review.id}&caseNo=${
|
review.caseNo || ""
|
}&name=${review.name || ""}`,
|
});
|
};
|
|
// 重新开始
|
const restartReview = async (review) => {
|
uni.showModal({
|
title: "重新开始审查",
|
content: "确定要重新开始这个审查流程吗?",
|
success: async (res) => {
|
if (res.confirm) {
|
try {
|
uni.showLoading({
|
title: "处理中...",
|
mask: true,
|
});
|
|
const response = await uni.$uapi.put(
|
`/project/ethicalreviewopinions/reset/${review.fcid || review.id}`,
|
);
|
|
uni.hideLoading();
|
|
if (response.code == 200) {
|
uni.showToast({
|
title: "审查已重新开始",
|
icon: "success",
|
duration: 2000,
|
});
|
|
// 重新加载数据
|
resetAndLoad();
|
} else {
|
uni.showToast({
|
title: response.msg || "操作失败",
|
icon: "none",
|
duration: 2000,
|
});
|
}
|
} catch (error) {
|
uni.hideLoading();
|
console.error("重新开始审查失败:", error);
|
uni.showToast({
|
title: "操作失败",
|
icon: "error",
|
duration: 2000,
|
});
|
}
|
}
|
},
|
});
|
};
|
|
// 导出审查数据
|
const exportReviews = async () => {
|
try {
|
uni.showLoading({
|
title: "导出中...",
|
mask: true,
|
});
|
|
const params = buildQueryParams();
|
delete params.pageNum;
|
delete params.pageSize;
|
|
const res = await uni.$uapi.get(
|
`/project/ethicalreviewopinions/export`,
|
params,
|
);
|
|
uni.hideLoading();
|
|
if (res.code == 200) {
|
const fileUrl = res.data || res.url;
|
if (fileUrl) {
|
uni.showToast({
|
title: "导出成功",
|
icon: "success",
|
duration: 2000,
|
});
|
|
// 在新窗口中打开下载链接
|
window.open(fileUrl, "_blank");
|
} else {
|
uni.showToast({
|
title: "导出文件获取失败",
|
icon: "none",
|
duration: 2000,
|
});
|
}
|
} else {
|
uni.showToast({
|
title: res.msg || "导出失败",
|
icon: "none",
|
duration: 2000,
|
});
|
}
|
} catch (error) {
|
uni.hideLoading();
|
console.error("导出数据失败:", error);
|
uni.showToast({
|
title: "导出失败",
|
icon: "error",
|
duration: 2000,
|
});
|
}
|
};
|
|
// 生命周期
|
onLoad(async () => {
|
// 获取字典数据
|
dict.value = await useDict(
|
"sys_IDType",
|
"sys_user_sex",
|
"sys_Nation",
|
"sys_BloodType",
|
"sys_Infectious",
|
"sys_AgeUnit",
|
"ReviewForm_status",
|
"sys_ethical",
|
"expert_Conclusion",
|
);
|
|
// 加载数据
|
await loadCaseData();
|
await stateTotal();
|
});
|
|
onShow(() => {
|
// 页面显示时刷新数据
|
resetAndLoad();
|
});
|
|
// 监听下拉刷新
|
onPullDownRefresh(() => {
|
onRefresh();
|
});
|
|
// 监听上拉触底
|
onReachBottom(() => {
|
onLoadMore();
|
});
|
</script>
|
|
<style lang="scss" scoped>
|
.ethics-review-list {
|
min-height: 100vh;
|
background: #f5f7fa;
|
padding: 20rpx;
|
|
.stats-card {
|
background: linear-gradient(135deg, #747cf9, #9b7cf9);
|
border-radius: 16rpx;
|
padding: 40rpx 20rpx;
|
display: flex;
|
align-items: center;
|
margin-bottom: 24rpx;
|
box-shadow: 0 4rpx 20rpx rgba(116, 124, 249, 0.3);
|
|
.stat-item {
|
flex: 1;
|
text-align: center;
|
|
.count {
|
font-size: 36rpx;
|
color: #fff;
|
font-weight: bold;
|
margin-bottom: 8rpx;
|
display: block;
|
}
|
|
.label {
|
font-size: 24rpx;
|
color: rgba(255, 255, 255, 0.9);
|
}
|
}
|
|
.divider {
|
width: 2rpx;
|
height: 50rpx;
|
background: rgba(255, 255, 255, 0.2);
|
}
|
}
|
|
.filter-bar {
|
background: #fff;
|
border-radius: 16rpx;
|
padding: 24rpx;
|
margin-bottom: 24rpx;
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
|
.status-filter {
|
display: flex;
|
margin-bottom: 20rpx;
|
flex-wrap: wrap;
|
|
text {
|
flex: 1;
|
// min-width: 120rpx;
|
text-align: center;
|
font-size: 26rpx;
|
color: #606266;
|
padding: 16rpx 0;
|
position: relative;
|
margin: 0 8rpx;
|
|
&.active {
|
color: #747cf9;
|
font-weight: 500;
|
|
&::after {
|
content: "";
|
position: absolute;
|
left: 50%;
|
bottom: 0;
|
transform: translateX(-50%);
|
width: 40rpx;
|
height: 4rpx;
|
background: #747cf9;
|
border-radius: 2rpx;
|
}
|
}
|
}
|
}
|
}
|
|
.review-list {
|
height: calc(100vh - 300rpx);
|
|
.review-item {
|
background: #fff;
|
border-radius: 16rpx;
|
padding: 32rpx;
|
margin-bottom: 24rpx;
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
|
.review-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: flex-start;
|
margin-bottom: 24rpx;
|
|
.case-info {
|
display: flex;
|
align-items: center;
|
|
.hospital-badge {
|
background: linear-gradient(135deg, #747cf9, #9b7cf9);
|
width: 64rpx;
|
height: 64rpx;
|
border-radius: 12rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-right: 20rpx;
|
}
|
|
.info-content {
|
.donor-name {
|
font-size: 32rpx;
|
color: #303133;
|
font-weight: 600;
|
display: block;
|
margin-bottom: 4rpx;
|
max-width: 300rpx;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.hospital-no {
|
font-size: 26rpx;
|
color: #909399;
|
margin-right: 16rpx;
|
background: #f5f5f5;
|
padding: 4rpx 12rpx;
|
border-radius: 8rpx;
|
}
|
|
.expert-type {
|
font-size: 22rpx;
|
color: #747cf9;
|
background: #f0f2ff;
|
padding: 4rpx 12rpx;
|
border-radius: 12rpx;
|
margin-top: 4rpx;
|
display: inline-block;
|
}
|
}
|
}
|
|
.status-tag {
|
padding: 8rpx 16rpx;
|
border-radius: 20rpx;
|
font-size: 24rpx;
|
font-weight: 500;
|
white-space: nowrap;
|
|
&.approved {
|
background: #f6ffed;
|
color: #52c41a;
|
}
|
|
&.rejected {
|
background: #fff2e8;
|
color: #fa541c;
|
}
|
|
&.abandoned {
|
background: #f5f5f5;
|
color: #8c8c8c;
|
}
|
|
&.pending {
|
background: #e6f7ff;
|
color: #1890ff;
|
}
|
|
&.unknown {
|
background: #f5f5f5;
|
color: #bfbfbf;
|
}
|
}
|
}
|
|
.basic-info {
|
margin-bottom: 20rpx;
|
|
.info-row {
|
display: grid;
|
grid-template-columns: 1fr 1fr 1fr;
|
gap: 20rpx;
|
|
.info-col {
|
.info-label {
|
font-size: 24rpx;
|
color: #909399;
|
display: block;
|
margin-bottom: 4rpx;
|
}
|
|
.info-value {
|
font-size: 26rpx;
|
color: #303133;
|
font-weight: 500;
|
display: block;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
}
|
}
|
}
|
|
.review-details {
|
display: flex;
|
flex-direction: column;
|
gap: 12rpx;
|
margin-bottom: 20rpx;
|
|
.detail-item {
|
display: flex;
|
align-items: center;
|
gap: 8rpx;
|
|
.detail-text {
|
font-size: 24rpx;
|
color: #606266;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
}
|
}
|
|
.conclusion-section {
|
background: #f6ffed;
|
border-radius: 8rpx;
|
padding: 20rpx;
|
margin-bottom: 20rpx;
|
|
.conclusion-label {
|
font-size: 24rpx;
|
color: #52c41a;
|
font-weight: 500;
|
margin-right: 8rpx;
|
}
|
|
.conclusion-content {
|
font-size: 24rpx;
|
color: #303133;
|
}
|
}
|
|
.opinion-section {
|
background: #e6f7ff;
|
border-radius: 8rpx;
|
padding: 20rpx;
|
margin-bottom: 20rpx;
|
|
.opinion-label {
|
font-size: 24rpx;
|
color: #1890ff;
|
font-weight: 500;
|
margin-right: 8rpx;
|
}
|
|
.opinion-content {
|
font-size: 24rpx;
|
color: #303133;
|
}
|
}
|
|
.action-buttons {
|
display: flex;
|
justify-content: space-between;
|
gap: 16rpx;
|
flex-wrap: wrap;
|
|
.action-btn {
|
flex: 1;
|
min-width: 200rpx;
|
height: 64rpx;
|
border: none;
|
border-radius: 32rpx;
|
font-size: 26rpx;
|
font-weight: 500;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
gap: 6rpx;
|
margin-bottom: 8rpx;
|
|
&.detail-btn {
|
background: #f5f5f5;
|
color: #747cf9;
|
}
|
|
&.download-btn {
|
background: #f6ffed;
|
color: #52c41a;
|
border: 1rpx solid #b7eb8f;
|
}
|
|
&.appeal-btn {
|
background: #fff2e8;
|
color: #fa8c16;
|
border: 1rpx solid #ffbb96;
|
}
|
|
&.restart-btn {
|
background: #f0f2ff;
|
color: #747cf9;
|
border: 1rpx solid #adc6ff;
|
}
|
}
|
}
|
}
|
|
.empty-state {
|
text-align: center;
|
padding: 120rpx 0;
|
|
.empty-text {
|
display: block;
|
font-size: 32rpx;
|
color: #909399;
|
margin: 24rpx 0 12rpx;
|
}
|
|
.empty-desc {
|
font-size: 26rpx;
|
color: #c0c4cc;
|
margin-bottom: 32rpx;
|
}
|
|
.empty-action {
|
background: linear-gradient(135deg, #747cf9, #9b7cf9);
|
color: #fff;
|
border: none;
|
border-radius: 32rpx;
|
padding: 16rpx 32rpx;
|
font-size: 28rpx;
|
}
|
}
|
|
.load-complete {
|
text-align: center;
|
padding: 32rpx;
|
color: #909399;
|
font-size: 24rpx;
|
}
|
}
|
}
|
|
/* 响应式设计 */
|
@media (max-width: 768px) {
|
.ethics-review-list {
|
padding: 20rpx;
|
|
.stats-card {
|
padding: 30rpx 15rpx;
|
|
.stat-item {
|
.count {
|
font-size: 30rpx;
|
}
|
|
.label {
|
font-size: 22rpx;
|
}
|
}
|
}
|
|
.review-item .basic-info .info-row {
|
grid-template-columns: 1fr;
|
gap: 16rpx;
|
}
|
|
.review-header {
|
flex-direction: column;
|
align-items: flex-start !important;
|
|
.status-tag {
|
margin-top: 16rpx;
|
}
|
}
|
|
.action-buttons {
|
flex-direction: column;
|
|
.action-btn {
|
min-width: 100% !important;
|
}
|
}
|
}
|
}
|
</style>
|