ReviewForm.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <template>
  2. <view class="document-form">
  3. <uv-loading-icon v-if="loading" mode="circle" text="正在加载伦理审查详情..."></uv-loading-icon>
  4. <template v-else-if="form">
  5. <!-- 基本信息 -->
  6. <view class="common-section-card">
  7. <view class="section-title">基本信息</view>
  8. <view class="info-row">
  9. <text class="label">审查类型</text>
  10. <text class="value">{{ getDictLabel('sci_review_type', form.reviewType) }}</text>
  11. </view>
  12. <view class="info-row">
  13. <text class="label">项目类型</text>
  14. <text class="value">{{ getDictLabel('sci_preoject_type', form.projectType) }}</text>
  15. </view>
  16. <view class="info-row">
  17. <text class="label">项目名称</text>
  18. <text class="value">{{ form.projectName || '-' }}</text>
  19. </view>
  20. </view>
  21. <!-- 申请资料 -->
  22. <AttachmentList :list="form.fileList" title="申请资料" />
  23. <!-- 审查信息 -->
  24. <view class="common-section-card mt20">
  25. <view class="section-title">审查详情</view>
  26. <view class="info-row">
  27. <text class="label">审查方式</text>
  28. <text class="value">{{ form.reviewMethod === '10' ? '简易审查' : form.reviewMethod === '20' ? '会议审查' : '-' }}</text>
  29. </view>
  30. <view class="info-row">
  31. <text class="label">审查委员</text>
  32. <text class="value">{{ memberNames || '-' }}</text>
  33. </view>
  34. <view class="info-row" v-if="form.formReviewResult === '20'">
  35. <text class="label">审查说明</text>
  36. <text class="value">{{ form.remark || '-' }}</text>
  37. </view>
  38. </view>
  39. </template>
  40. <uv-empty v-else mode="data" text="暂无数据"></uv-empty>
  41. </view>
  42. </template>
  43. <script setup lang="ts">
  44. import { ref, onMounted, watch, computed } from 'vue';
  45. import { useDict } from '@/hooks/useDict';
  46. import { useDocumentApi } from '@/api/document';
  47. import { formatDate } from '@/utils/date';
  48. import { previewFile } from '@/utils/file';
  49. import to from 'await-to-js';
  50. const props = defineProps<{
  51. code: string;
  52. }>();
  53. const { getDictLabel } = useDict('sci_review_type', 'sci_preoject_type');
  54. const documentApi = useDocumentApi();
  55. const form = ref<any>(null);
  56. const loading = ref(false);
  57. const memberNames = computed(() => {
  58. if (!form.value?.memberList?.length) return '';
  59. return form.value.memberList.map((m: any) => m.memberName || m.nickName).join('、');
  60. });
  61. const fetchData = async () => {
  62. if (!props.code) return;
  63. loading.value = true;
  64. const [err, res] = await to(documentApi.getReviewByCode(props.code));
  65. if (!err && res?.data) {
  66. form.value = res.data;
  67. }
  68. loading.value = false;
  69. };
  70. onMounted(() => {
  71. fetchData();
  72. });
  73. watch(() => props.code, () => {
  74. fetchData();
  75. });
  76. </script>
  77. <style lang="scss" scoped>
  78. @import "./common.scss";
  79. .material-list {
  80. .material-item {
  81. background: #f8f9fc;
  82. border-radius: 12rpx;
  83. padding: 24rpx;
  84. margin-bottom: 20rpx;
  85. .m-header {
  86. display: flex;
  87. align-items: center;
  88. margin-bottom: 16rpx;
  89. .m-name {
  90. font-size: 28rpx;
  91. color: #333;
  92. font-weight: bold;
  93. }
  94. .m-required {
  95. color: #ff4d4f;
  96. margin-left: 8rpx;
  97. }
  98. }
  99. .m-meta {
  100. display: flex;
  101. flex-wrap: wrap;
  102. .m-cell {
  103. width: 50%;
  104. font-size: 24rpx;
  105. line-height: 1.6;
  106. .cl { color: #888; }
  107. .cv { color: #555; }
  108. }
  109. }
  110. .m-action {
  111. margin-top: 16rpx;
  112. text-align: right;
  113. font-size: 24rpx;
  114. color: var(--primary-color);
  115. }
  116. }
  117. }
  118. </style>