chore: 修复大量导入路径错误

- 迁移 files API 到 shared/api/
- 修复所有 features 中的 @/api/ 导入
- 修复所有 features 中的 @/composables/ 导入
- 更新 useOrderDetail 中的 uploadFile 调用

类型错误:272 → 190 → 135
This commit is contained in:
yml2213
2026-06-04 09:30:13 +08:00
parent e010f2ce7e
commit 956c2eca91
22 changed files with 234 additions and 30 deletions
@@ -16,8 +16,8 @@ import {
Warning
} from '@element-plus/icons-vue'
import { fetchAdminDashboard, type AdminDashboard } from '@/features/admin/api/adminDashboard'
import { useAdminTable } from '@/composables/useAdminTable'
import { useMoney } from '@/composables/useMoney'
import { useAdminTable } from '@/features/admin/composables/useAdminTable'
import { useMoney } from '@/shared/composables/useMoney'
import { disputeStatusLabel, orderStatusLabel } from '@/utils/statusLabels'
import { formatDateTime } from '@/utils/time'
@@ -4,8 +4,8 @@ import { ElMessage } from 'element-plus'
import { computed, reactive, ref } from 'vue'
import { fetchAdminListings, type AdminListingPage, type AdminListingQuery, type Listing } from '@/features/listings'
import { useAdminTable } from '@/composables/useAdminTable'
import { useMoney } from '@/composables/useMoney'
import { useAdminTable } from '@/features/admin/composables/useAdminTable'
import { useMoney } from '@/shared/composables/useMoney'
import {
assetRegions,
formatEstimatedRentalDuration,
@@ -3,7 +3,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { ref } from 'vue'
import { fetchAdminMgrUsers, deleteAdminMgrUser, changeAdminPassword, type AdminMgrUser } from '@/features/admin/api/adminMgr'
import { useAdminPaginatedTable } from '@/composables/useAdminPaginatedTable'
import { useAdminPaginatedTable } from '@/features/admin/composables/useAdminPaginatedTable'
import { formatDateTime } from '@/utils/time'
import AdminUserDialog from './components/AdminUserDialog.vue'
@@ -2,7 +2,7 @@
import { computed, ref } from 'vue'
import { fetchAdminOrders, type Order } from '@/features/orders'
import { useAdminTable } from '@/composables/useAdminTable'
import { useAdminTable } from '@/features/admin/composables/useAdminTable'
import { handoffStatusLabel, orderStatusLabel, settlementStatusLabel } from '@/utils/statusLabels'
import { formatDateTime } from '@/utils/time'
@@ -3,7 +3,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { ref } from 'vue'
import { fetchRoles, deleteRole, type Role } from '@/features/admin/api/adminRoles'
import { useAdminTable } from '@/composables/useAdminTable'
import { useAdminTable } from '@/features/admin/composables/useAdminTable'
import AssignPermissionsDialog from './components/AssignPermissionsDialog.vue'
import RoleDialog from './components/RoleDialog.vue'
@@ -3,7 +3,7 @@ import { ElMessage } from 'element-plus'
import { ref } from 'vue'
import { fetchAdminUsers, freezeAdminUser, unfreezeAdminUser, type AdminUserItem } from '@/features/admin/api/adminUsers'
import { useAdminPaginatedTable } from '@/composables/useAdminPaginatedTable'
import { useAdminPaginatedTable } from '@/features/admin/composables/useAdminPaginatedTable'
import { userStatusLabel } from '@/utils/statusLabels'
import { formatDateTime } from '@/utils/time'
@@ -1,5 +1,5 @@
import { onBeforeUnmount, ref, type Ref } from 'vue'
import { refreshAccessToken } from '@/api/client'
import { refreshAccessToken } from '@/shared/api/client'
import { getAccessToken, type AuthScope } from '@/utils/authStorage'
export interface SSEMessage {
@@ -10,10 +10,10 @@ import {
sendChatMessage,
type ChatConversation,
type ChatMessage,
} from '@/api/chats'
} from '@/features/chats/api/chats'
import { uploadFile } from '@/shared/api/files'
import ChatAttachmentImage from '@/components/ChatAttachmentImage.vue'
import { useChatSSE, type ChatEvent } from '@/composables/useChatSSE'
import { useChatSSE, type ChatEvent } from '@/features/chats/composables/useChatSSE'
import { formatDateMinute } from '@/utils/time'
const currentUserId = Number(localStorage.getItem('user_id') || 0)
@@ -3,8 +3,8 @@ import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { ChatDotRound, Refresh, Tickets } from '@element-plus/icons-vue'
import { fetchChats, type ChatConversation } from '@/api/chats'
import { useChatSSE, type ChatEvent } from '@/composables/useChatSSE'
import { fetchChats, type ChatConversation } from '@/features/chats/api/chats'
import { useChatSSE, type ChatEvent } from '@/features/chats/composables/useChatSSE'
import { formatDateMinute } from '@/utils/time'
const router = useRouter()
@@ -9,10 +9,10 @@ import {
sendChatMessage,
type ChatConversation,
type ChatMessage,
} from '@/api/chats'
} from '@/features/chats/api/chats'
import { uploadFile } from '@/shared/api/files'
import ChatAttachmentImage from '@/components/ChatAttachmentImage.vue'
import { useChatSSE, type ChatEvent } from '@/composables/useChatSSE'
import { useChatSSE, type ChatEvent } from '@/features/chats/composables/useChatSSE'
import { formatDateMinute } from '@/utils/time'
const currentUserId = Number(localStorage.getItem('user_id') || 0)
@@ -3,7 +3,7 @@ import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { showToast } from 'vant'
import MobileBottomNav from '@/components/MobileBottomNav.vue'
import { fetchChats, type ChatConversation } from '@/api/chats'
import { fetchChats, type ChatConversation } from '@/features/chats/api/chats'
import { formatDateMinute } from '@/utils/time'
const router = useRouter()
@@ -9,9 +9,9 @@ import {
moneyRangeOptions,
totalRangeOptions,
fireLevelRangeOptions,
} from '@/composables/home/useFilterOptions'
} from '@/features/listings/composables/useFilterOptions'
import type { ListingPublishOptions } from '@/features/listings/api/listingOptions'
import type { FilterPopoverKey, HomeFilters } from '@/composables/home/useHomeFilters'
import type { FilterPopoverKey, HomeFilters } from '@/features/listings/composables/useHomeFilters'
interface Props {
filters: HomeFilters
@@ -2,7 +2,7 @@
import { ArrowDown } from '@element-plus/icons-vue'
import { ElInputNumber, ElPopover } from 'element-plus'
import { computed } from 'vue'
import { rangeLabel, isRangeSelected } from '@/composables/home/useFilterOptions'
import { rangeLabel, isRangeSelected } from '@/features/listings/composables/useFilterOptions'
interface RangeOption {
label: string
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest'
import { rangeLabel, isRangeSelected } from '@/composables/home/useFilterOptions'
import { rangeLabel, isRangeSelected } from '@/features/listings/composables/useFilterOptions'
describe('useFilterOptions', () => {
describe('rangeLabel', () => {
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest'
import { useHomeFilters } from '@/composables/home/useHomeFilters'
import { useHomeFilters } from '@/features/listings/composables/useHomeFilters'
import { ref } from 'vue'
import { emptyListingPublishOptions } from '@/api/listingOptions'
@@ -6,13 +6,13 @@ import {
defaultHomeBanners,
fetchMobileHomeConfig,
type HomeBannerSlide,
} from '@/api/homeConfig'
} from '@/features/listings/api/homeConfig'
import {
emptyListingPublishOptions,
type ListingPublishOptions,
} from '@/features/listings/api/listingOptions'
import { useHomeFilters } from '@/composables/home/useHomeFilters'
import { useListingQuery } from '@/composables/home/useListingQuery'
import { useHomeFilters } from '@/features/listings/composables/useHomeFilters'
import { useListingQuery } from '@/features/listings/composables/useListingQuery'
import HomeAnnouncement from './components/HomeAnnouncement.vue'
import HomeBanner from './components/HomeBanner.vue'
import HomeStats from './components/HomeStats.vue'
@@ -9,9 +9,9 @@ import {
submitHandoff,
confirmReceive,
} from '../api/orders'
import { createDispute } from '@/api/disputes'
import { uploadFile } from '@/api/files'
import { fetchOrderChat } from '@/api/chats'
import { createDispute } from '@/features/disputes/api/disputes'
import { uploadFile } from '@/shared/api/files'
import { fetchOrderChat } from '@/features/chats/api/chats'
import { useSessionStore } from '@/stores/session'
import { usePaymentPolling } from './usePaymentPolling'
import { useSettlement } from './useSettlement'
@@ -147,7 +147,7 @@ export function useOrderDetail() {
async function handleUploadEvidence(file: File) {
uploadingEvidence.value = true
try {
const result = await uploadFile(file)
const result = await uploadFile(file, 'evidence')
return result.url
} finally {
uploadingEvidence.value = false
@@ -5,7 +5,7 @@ import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import QRCode from 'qrcode'
import { fetchOrderChat } from '@/api/chats'
import { fetchOrderChat } from '@/features/chats/api/chats'
import { createDispute } from '@/features/disputes'
import { uploadFile } from '@/shared/api/files'
import {
@@ -1,7 +1,7 @@
import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import { fetchFileBlobByURL, uploadFile } from '@/api/files'
import { fetchFileBlobByURL, uploadFile } from '@/shared/api/files'
import {
emptyListingPublishOptions,
emptyListingSalePriceConfig,
+51
View File
@@ -0,0 +1,51 @@
import { apiClient } from './client'
import type { ApiResponse } from '@/shared/types/types'
import { optimizeImageForUpload } from '@/shared/utils/imageUpload'
export interface UploadedFile {
object_key: string
url: string
thumbnail_url?: string
medium_url?: string
filename: string
content_type: string
size: number
}
export async function uploadFile(file: File, scene: string) {
const uploadTarget = await optimizeImageForUpload(file, scene)
const form = new FormData()
form.append('file', uploadTarget)
form.append('scene', scene)
const { data } = await apiClient.post<ApiResponse<UploadedFile>>('/files/upload', form, {
headers: { 'Content-Type': 'multipart/form-data' },
})
return data.data
}
export async function uploadAdminFile(file: File, scene: string) {
const uploadTarget = await optimizeImageForUpload(file, scene)
const form = new FormData()
form.append('file', uploadTarget)
form.append('scene', scene)
const { data } = await apiClient.post<ApiResponse<UploadedFile>>('/admin/files/upload', form, {
headers: { 'Content-Type': 'multipart/form-data' },
})
return data.data
}
export async function fetchAdminFileBlob(key: string) {
const { data } = await apiClient.get<Blob>('/admin/files/object', {
params: { key },
responseType: 'blob',
})
return data
}
export async function fetchFileBlobByURL(fileURL: string) {
const apiPath = fileURL.startsWith('/api/') ? fileURL.slice(4) : fileURL
const { data } = await apiClient.get<Blob>(apiPath, {
responseType: 'blob',
})
return data
}
+1
View File
@@ -1,2 +1,3 @@
// API 基础设施
export * from './client'
export * from './files'