Home.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <template>
  2. <div id="app">
  3. <header class="app-header">
  4. <h1>文件管理客户端</h1>
  5. <div class="network-indicator" :class="isOnline ? 'online' : 'offline'">
  6. {{ isOnline ? '在线模式' : '离线模式' }}
  7. </div>
  8. </header>
  9. <main class="app-main">
  10. <FileUpload @file-uploaded="refreshFileList" />
  11. <FileList
  12. ref="fileListRef"
  13. @md5-check="handleMD5Check"
  14. @ocr-recognize="handleOcrRecognize"
  15. />
  16. </main>
  17. </div>
  18. </template>
  19. <script setup lang="ts">
  20. import { ref, onMounted, onUnmounted } from 'vue'
  21. import { useRouter } from 'vue-router'
  22. import FileUpload from '../components/FileUpload.vue'
  23. import FileList from '../components/FileList.vue'
  24. import apiManager from '../utils/apiManager'
  25. interface FileRecord {
  26. id: number
  27. originalName: string
  28. fileName: string
  29. filePath: string
  30. fileSize: number
  31. mimeType: string
  32. md5: string
  33. createdAt: string
  34. updatedAt: string
  35. }
  36. const router = useRouter()
  37. const fileListRef = ref<InstanceType<typeof FileList>>()
  38. const isOnline = ref(false)
  39. // 监听网络状态变化
  40. const handleNetworkChange = (event: CustomEvent<{ baseUrl: string; isOnline: boolean }>) => {
  41. isOnline.value = event.detail.isOnline
  42. console.log('App: 网络状态变更', event.detail)
  43. }
  44. onMounted(() => {
  45. isOnline.value = apiManager.isOnlineMode()
  46. window.addEventListener('apiBaseUrlChanged', handleNetworkChange as EventListener)
  47. })
  48. onUnmounted(() => {
  49. window.removeEventListener('apiBaseUrlChanged', handleNetworkChange as EventListener)
  50. })
  51. const refreshFileList = (): void => {
  52. fileListRef.value?.refreshList()
  53. }
  54. const handleMD5Check = async (file: FileRecord, isChanged: boolean, newMD5: string): Promise<void> => {
  55. if (isChanged) {
  56. const confirmed = confirm('文件内容已发生变化,是否更新MD5信息?')
  57. if (confirmed) {
  58. try {
  59. await apiManager.request(`/api/files/${file.id}/update-md5`, {
  60. method: 'PUT',
  61. headers: {
  62. 'Content-Type': 'application/json'
  63. },
  64. body: JSON.stringify({ md5: newMD5 })
  65. })
  66. alert('MD5信息已更新')
  67. refreshFileList()
  68. } catch (error) {
  69. console.error('更新MD5失败:', error)
  70. alert('更新失败')
  71. }
  72. }
  73. } else {
  74. alert('文件未发生变化')
  75. }
  76. }
  77. const handleOcrRecognize = (file: FileRecord): void => {
  78. // 跳转到OCR识别页面
  79. router.push(`/ocr?fileId=${file.id}`).then((res) => {
  80. console.log('导航成功:', res)
  81. }).catch((error) => {
  82. console.error('导航错误:', error)
  83. // 如果路由跳转失败,尝试使用 hash 方式
  84. window.location.hash = `/ocr?fileId=${file.id}`
  85. })
  86. }
  87. </script>
  88. <style>
  89. * {
  90. margin: 0;
  91. padding: 0;
  92. box-sizing: border-box;
  93. }
  94. body {
  95. font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  96. background: #f5f5f5;
  97. height: 100vh;
  98. overflow: hidden;
  99. }
  100. #app {
  101. height: 100vh;
  102. display: flex;
  103. flex-direction: column;
  104. }
  105. .app-header {
  106. background: #2c3e50;
  107. color: white;
  108. padding: 1rem;
  109. display: flex;
  110. justify-content: space-between;
  111. align-items: center;
  112. box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  113. flex-shrink: 0; /* 防止头部被压缩 */
  114. }
  115. .network-indicator {
  116. padding: 0.25rem 0.5rem;
  117. border-radius: 4px;
  118. font-size: 0.875rem;
  119. font-weight: bold;
  120. }
  121. .network-indicator.online {
  122. background: #27ae60;
  123. }
  124. .network-indicator.offline {
  125. background: #e74c3c;
  126. }
  127. .app-main {
  128. flex: 1;
  129. padding: 1rem;
  130. display: flex;
  131. flex-direction: column;
  132. gap: 1rem;
  133. overflow: hidden; /* 改为 hidden,内部组件自己处理滚动 */
  134. }
  135. </style>