Scope knowledge and image libraries by brand
Frontend CI / Frontend (push) Successful in 2m59s
Backend CI / Backend (push) Successful in 14m58s

This commit is contained in:
2026-06-30 12:30:10 +08:00
parent 95ddb3057f
commit ced0c4ec0f
35 changed files with 1136 additions and 326 deletions
+20 -2
View File
@@ -18,11 +18,14 @@ import { imagesApi } from '@/lib/api'
import { formatBytes, formatDateTime, formatPercentage } from '@/lib/display'
import { formatError } from '@/lib/errors'
import { IMAGE_UPLOAD_ACCEPT, useImageUploadProgress } from '@/lib/image-webp'
import { useCompanyStore } from '@/stores/company'
import type { ImageAssetItem, ImageFolder } from '@geo/shared-types'
const { t } = useI18n()
const queryClient = useQueryClient()
const imageUploadProgress = useImageUploadProgress()
const companyStore = useCompanyStore()
const currentBrandId = computed(() => companyStore.currentBrandId)
// State
const selectedFolderId = ref<number | null>(null) // null means "All" or is handled by folders query
@@ -51,7 +54,8 @@ const fileInput = ref<HTMLInputElement | null>(null)
// Queries
const foldersQuery = useQuery({
queryKey: ['images', 'folders'],
queryKey: computed(() => ['images', 'folders', currentBrandId.value]),
enabled: computed(() => Boolean(currentBrandId.value)),
queryFn: () => imagesApi.listFolders(),
})
@@ -59,6 +63,7 @@ const imagesQuery = useQuery({
queryKey: computed(() => [
'images',
'list',
currentBrandId.value,
{
folder_id: debouncedSearch.value ? undefined : selectedFolderId.value,
q: debouncedSearch.value,
@@ -66,6 +71,7 @@ const imagesQuery = useQuery({
page_size: pageSize.value,
},
]),
enabled: computed(() => Boolean(currentBrandId.value)),
queryFn: () =>
imagesApi.list({
folder_id: debouncedSearch.value ? undefined : (selectedFolderId.value ?? undefined),
@@ -76,7 +82,8 @@ const imagesQuery = useQuery({
})
const allImagesCountQuery = useQuery({
queryKey: ['images', 'list', 'all-count'],
queryKey: computed(() => ['images', 'list', 'all-count', currentBrandId.value]),
enabled: computed(() => Boolean(currentBrandId.value)),
queryFn: () =>
imagesApi.list({
page: 1,
@@ -181,6 +188,17 @@ watch(searchKeyword, () => {
}, 300)
})
watch(currentBrandId, () => {
selectedFolderId.value = null
movingImage.value = null
previewingImage.value = null
renamingImage.value = null
moveModalOpen.value = false
previewModalOpen.value = false
renameImageModalOpen.value = false
currentPage.value = 1
})
function handleFolderSelect(id: number | null) {
if (debouncedSearch.value) return
selectedFolderId.value = id
+19 -2
View File
@@ -16,6 +16,7 @@ import KnowledgeDetailDrawer from '@/components/KnowledgeDetailDrawer.vue'
import { knowledgeApi } from '@/lib/api'
import { formatDateTime } from '@/lib/display'
import { formatError } from '@/lib/errors'
import { useCompanyStore } from '@/stores/company'
type KnowledgeSourceType = 'document' | 'website' | 'text'
type KnowledgeGroupLevel = 'root' | 'child'
@@ -35,6 +36,8 @@ interface TreeNode {
}
const queryClient = useQueryClient()
const companyStore = useCompanyStore()
const currentBrandId = computed(() => companyStore.currentBrandId)
const selectedGroupId = ref<number | null>(null)
const groupModalOpen = ref(false)
@@ -59,12 +62,14 @@ const urlsText = ref('')
const textItems = ref([{ name: '', content: '' }])
const groupsQuery = useQuery({
queryKey: ['knowledge', 'groups'],
queryKey: computed(() => ['knowledge', 'groups', currentBrandId.value]),
enabled: computed(() => Boolean(currentBrandId.value)),
queryFn: () => knowledgeApi.listGroups(),
})
const itemsQuery = useQuery({
queryKey: computed(() => ['knowledge', 'items', selectedGroupId.value]),
queryKey: computed(() => ['knowledge', 'items', currentBrandId.value, selectedGroupId.value]),
enabled: computed(() => Boolean(currentBrandId.value)),
queryFn: () => knowledgeApi.listItems(selectedGroupId.value ?? undefined),
refetchInterval: (query) => {
const items = query.state.data as KnowledgeItem[] | undefined
@@ -267,6 +272,18 @@ const retryItemMutation = useMutation({
onError: (error) => message.error(formatError(error)),
})
watch(
currentBrandId,
() => {
selectedGroupId.value = null
groupModalOpen.value = false
editingGroup.value = null
itemModalOpen.value = false
previewItemId.value = null
previewDrawerOpen.value = false
},
)
watch(
() => groupsQuery.data.value,
(groups) => {