auditModal.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <template>
  2. <a-modal v-model:visible="visibles" title="资源信息" @cancel="handleCancel" :footer="null" width="800px">
  3. <div class="audit-container">
  4. <!-- 左侧 - 文件展示区域 -->
  5. <div class="file-preview">
  6. <!-- <img src="/src/assets/images/flw/REVOKE.png" /> -->
  7. <video-player
  8. v-if="recordData.suffix === 'mp4'"
  9. :source="activeVideoSource"
  10. @ready="playerReadied"
  11. ></video-player>
  12. <div
  13. v-else-if="['pdf', 'word', 'ppt', 'doc', 'docx'].includes(recordData.suffix.toLowerCase())"
  14. class="preview-iframe"
  15. >
  16. <iframe
  17. :src="`https://docs.google.com/gview?url=${sysConfig.FILE_URL + recordData.fileUrl}&embedded=true`"
  18. frameborder="0"
  19. ></iframe>
  20. </div>
  21. <!-- 图片预览 -->
  22. <div v-else-if="['jpg', 'jpeg', 'png', 'gif'].includes(recordData.suffix.toLowerCase())" class="image-viewer">
  23. <img
  24. :src="sysConfig.FILE_URL + recordData.fileUrl"
  25. :alt="recordData.fileName"
  26. style="max-width: 100%; max-height: 100%; object-fit: contain"
  27. />
  28. </div>
  29. <div v-else class="preview-placeholder">
  30. <file-unknown-filled style="font-size: 48px; color: #999" />
  31. <p>文件预览</p>
  32. </div>
  33. </div>
  34. <!-- 右侧 - 审核信息区域 -->
  35. <div class="audit-info">
  36. <div class="info-section">
  37. <p><strong>上传人:</strong>{{ detailData.resourceCreaterUserName || '--' }}</p>
  38. <p><strong>所属院系:</strong>{{ detailData?.collegeAllIdName || '--' }}</p>
  39. <p><strong>所属专业:</strong>{{ detailData?.majorIdName || '--' }}</p>
  40. <p><strong>资源类型:</strong>{{ detailData?.resourceTypeName || '--' }}</p>
  41. <p><strong>资源格式:</strong>{{ detailData?.suffix || '--' }}</p>
  42. <p><strong>视频时长:</strong>{{ detailData?.duration || '--' }}</p>
  43. <p><strong>视频大小:</strong>{{ detailData?.FILESIZE || '--' }}<span v-if="detailData?.FILESIZE">b</span></p>
  44. <p><strong>发布时间:</strong>{{ detailData?.uploadTime || '--' }}</p>
  45. <p><strong>资源描述:</strong>{{ detailData?.resourceDesc || '--' }}</p>
  46. </div>
  47. </div>
  48. </div>
  49. <div style="display: flex; justify-content: flex-end; margin-top: 10px" v-if="isAudit">
  50. <a-button @click="handleAuditResult(3)" style="margin-right: 10px">不同意</a-button>
  51. <a-button type="primary" @click="handleAuditResult(2)">同意</a-button>
  52. </div>
  53. </a-modal>
  54. </template>
  55. <script setup>
  56. import { ref, defineProps, defineEmits, computed } from 'vue'
  57. import resourceAuditApi from '@/api/resourceAudit.js'
  58. import VideoPlayer from './VideoPlayer.vue'
  59. import sysConfig from '@/config/index'
  60. // import videoPlayer from 'vue-video-player'
  61. const props = defineProps({
  62. recordData: {
  63. type: Object,
  64. required: true,
  65. default: null
  66. },
  67. //是否是审核
  68. isAudit: {
  69. type: Boolean,
  70. required: true,
  71. default: false
  72. }
  73. })
  74. const emit = defineEmits(['confirm', 'close'])
  75. const auditResult = ref(1) // 默认为通过
  76. const detailData = ref({})
  77. const visibles = ref(true)
  78. const activeVideoSource = computed(() => ({
  79. type: `video/mp4`,
  80. src: sysConfig.FILE_URL + props.recordData.fileUrl
  81. }))
  82. const handleCancel = () => {
  83. emit('close')
  84. }
  85. const handleAuditResult = (val) => {
  86. auditResult.value = val
  87. emit('confirm', { ...props.recordData, auditResult: auditResult.value })
  88. }
  89. const playerReadied = (player) => {
  90. // player ready
  91. }
  92. // 获取资源详情
  93. const getDetail = () => {
  94. resourceAuditApi.detail({ id: props.recordData.id }).then((res) => {
  95. console.log(res.data, '资源详情')
  96. detailData.value = res.data
  97. })
  98. }
  99. onMounted(() => {
  100. getDetail()
  101. })
  102. </script>
  103. <style scoped>
  104. .audit-container {
  105. display: flex;
  106. gap: 20px;
  107. height: 500px;
  108. border-bottom: 1px solid #ccc;
  109. padding-bottom: 10px;
  110. }
  111. .file-preview {
  112. flex: 1;
  113. display: flex;
  114. justify-content: center;
  115. align-items: center;
  116. background-color: #f5f5f5;
  117. border-radius: 4px;
  118. overflow: hidden;
  119. }
  120. .preview-placeholder {
  121. display: flex;
  122. flex-direction: column;
  123. align-items: center;
  124. gap: 10px;
  125. color: #666;
  126. }
  127. .audit-info {
  128. flex: 1;
  129. display: flex;
  130. flex-direction: column;
  131. gap: 20px;
  132. }
  133. .info-section {
  134. background: #fff;
  135. border-radius: 4px;
  136. }
  137. .info-section h4 {
  138. margin-bottom: 12px;
  139. font-size: 16px;
  140. color: #333;
  141. }
  142. .description-box {
  143. padding: 12px;
  144. border: 1px solid #d9d9d9;
  145. border-radius: 4px;
  146. max-height: 150px;
  147. overflow-y: auto;
  148. }
  149. .audit-action {
  150. margin-top: auto;
  151. padding-top: 20px;
  152. border-top: 1px dashed #d9d9d9;
  153. }
  154. /* 调整描述列表样式 */
  155. :deep(.ant-descriptions-item-label) {
  156. width: 100px;
  157. font-weight: normal;
  158. }
  159. .ant-modal-footer {
  160. display: none !important; /* 检查是否被覆盖 */
  161. }
  162. .preview-iframe {
  163. width: 100%;
  164. height: 100%;
  165. min-height: 500px;
  166. }
  167. .preview-iframe iframe {
  168. width: 100%;
  169. height: 100%;
  170. border: none;
  171. }
  172. </style>