diff --git a/pocket-base/bai_api_pb_hooks/bai_api_shared/middlewares/requestGuards.js b/pocket-base/bai_api_pb_hooks/bai_api_shared/middlewares/requestGuards.js index 95e78b0..afab028 100644 --- a/pocket-base/bai_api_pb_hooks/bai_api_shared/middlewares/requestGuards.js +++ b/pocket-base/bai_api_pb_hooks/bai_api_shared/middlewares/requestGuards.js @@ -150,11 +150,13 @@ function normalizeDictionaryItem(item, index) { throw createAppError(400, '第 ' + (index + 1) + ' 项 sortOrder 必须为数字') } + const imageIdList = normalizeAttachmentIdList(current.image, '第 ' + (index + 1) + ' 项 image') + return { enum: String(current.enum), description: String(current.description), sortOrder: sortOrderNumber, - image: current.image ? String(current.image) : '', + image: imageIdList.join('|'), } } diff --git a/pocket-base/bai_api_pb_hooks/bai_api_shared/services/dictionaryService.js b/pocket-base/bai_api_pb_hooks/bai_api_shared/services/dictionaryService.js index 73a0e48..747689c 100644 --- a/pocket-base/bai_api_pb_hooks/bai_api_shared/services/dictionaryService.js +++ b/pocket-base/bai_api_pb_hooks/bai_api_shared/services/dictionaryService.js @@ -16,6 +16,30 @@ function safeJsonParse(text, fallback) { } } +function parseAttachmentIdList(value) { + if (Array.isArray(value)) { + return value + .map(function (item) { + return String(item || '').trim() + }) + .filter(function (item) { + return !!item + }) + } + + const text = String(value || '').trim() + if (!text) return [] + + return text + .split('|') + .map(function (item) { + return String(item || '').trim() + }) + .filter(function (item) { + return !!item + }) +} + function normalizeItemsFromRecord(record) { const enums = safeJsonParse(record.getString('dict_word_enum'), []) const descriptions = safeJsonParse(record.getString('dict_word_description'), []) @@ -29,21 +53,31 @@ function normalizeItemsFromRecord(record) { continue } - const imageAttachmentId = typeof images[i] === 'undefined' ? '' : String(images[i] || '') - let imageAttachment = null - if (imageAttachmentId) { + const rawImageValue = typeof images[i] === 'undefined' ? '' : String(images[i] || '') + const imageAttachmentIds = parseAttachmentIdList(rawImageValue) + const imageAttachments = [] + const imageUrls = [] + + for (let imageIndex = 0; imageIndex < imageAttachmentIds.length; imageIndex += 1) { + const attachmentId = imageAttachmentIds[imageIndex] try { - imageAttachment = documentService.getAttachmentDetail(imageAttachmentId) + const imageAttachment = documentService.getAttachmentDetail(attachmentId) + imageAttachments.push(imageAttachment) + imageUrls.push(imageAttachment ? imageAttachment.attachments_url : '') } catch (_error) { - imageAttachment = null + imageAttachments.push(null) + imageUrls.push('') } } + items.push({ enum: typeof enums[i] === 'undefined' ? '' : String(enums[i]), description: typeof descriptions[i] === 'undefined' ? '' : String(descriptions[i]), - image: imageAttachmentId, - imageUrl: imageAttachment ? imageAttachment.attachments_url : '', - imageAttachment: imageAttachment, + image: imageAttachmentIds.join('|'), + imageIds: imageAttachmentIds, + imageUrls: imageUrls, + imageAttachments: imageAttachments, + imageUrl: imageUrls.length ? imageUrls[0] : '', sortOrder: Number(sortOrders[i] || 0), }) } @@ -89,7 +123,7 @@ function fillDictionaryItems(record, items) { for (let i = 0; i < items.length; i += 1) { enums.push(items[i].enum) descriptions.push(items[i].description) - images.push(items[i].image || '') + images.push(parseAttachmentIdList(items[i].image).join('|')) sortOrders.push(items[i].sortOrder) } diff --git a/pocket-base/bai_web_pb_hooks/pages/dictionary-manage.js b/pocket-base/bai_web_pb_hooks/pages/dictionary-manage.js index ffca20b..4474d7c 100644 --- a/pocket-base/bai_web_pb_hooks/pages/dictionary-manage.js +++ b/pocket-base/bai_web_pb_hooks/pages/dictionary-manage.js @@ -64,7 +64,17 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { .enum-preview-item { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; } .enum-preview-more { margin-top: 8px; display: none; } .enum-preview-toggle { margin-top: 6px; } - .image-upload-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px; margin-top: 10px; } + .item-image-grid { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; } + .image-tile { width: 86px; border: 1px solid #dbe3f0; border-radius: 12px; background: #fff; padding: 6px; display: flex; flex-direction: column; gap: 6px; cursor: grab; } + .image-tile.dragging { opacity: 0.55; } + .image-tile-thumb { width: 100%; height: 56px; border-radius: 8px; border: 1px solid #e2e8f0; background: #f8fafc; display: flex; align-items: center; justify-content: center; overflow: hidden; font-size: 12px; color: #64748b; } + .image-tile-thumb img { width: 100%; height: 100%; object-fit: cover; } + .image-tile-actions { display: flex; align-items: center; justify-content: space-between; gap: 6px; } + .image-tile-order { font-size: 11px; color: #64748b; } + .item-field-stack { display: flex; flex-direction: column; gap: 10px; min-width: 260px; } + .item-field-label { font-size: 12px; color: #64748b; margin-bottom: 4px; } + .item-delete-wrap { margin-top: 2px; } + .image-upload-row { display: grid; grid-template-columns: minmax(0, 1fr); align-items: center; gap: 8px; margin-top: 10px; } .image-upload-row input[type="file"] { width: 100%; min-width: 0; } .icon-btn { min-width: 36px; padding: 6px 10px; line-height: 1; font-size: 18px; } .drop-tip { color: #64748b; font-size: 12px; margin-top: 6px; } @@ -158,10 +168,8 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { - + - - @@ -204,6 +212,7 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { enumSeed: '', enumCounter: 1, expandedPreviewKey: '', + draggingImage: null, } const statusEl = document.getElementById('status') @@ -432,11 +441,21 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { enum: String((item && item.enum) || '').trim(), description: String((item && item.description) || ''), image: (item && item.image) || '', - imageUrl: (item && item.imageUrl) || '', - imageAttachment: (item && item.imageAttachment) || null, + imageIds: [], + imageUrls: [], + imageAttachments: [], + imageUrl: '', + imageAttachment: null, sortOrder: Number((item && item.sortOrder) || 0), } + const imageIds = normalizeAttachmentIdList(item && (item.imageIds || item.image)) + const imageUrls = normalizeImageUrlList(item && item.imageUrls, item && item.imageUrl, imageIds.length) + current.imageIds = imageIds + current.imageUrls = imageUrls + current.imageAttachments = normalizeImageAttachmentList(item && item.imageAttachments, item && item.imageAttachment, imageIds.length) + applyItemImageSummary(current) + if (!current.enum || used.has(current.enum)) { current.enum = nextAutoEnum(used) } @@ -450,12 +469,74 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { }) } + function normalizeAttachmentIdList(value) { + if (Array.isArray(value)) { + return value.map(function (item) { + return String(item || '').trim() + }).filter(function (item) { + return !!item + }) + } + + const text = String(value || '').trim() + if (!text) { + return [] + } + + return text.split('|').map(function (item) { + return String(item || '').trim() + }).filter(function (item) { + return !!item + }) + } + + function normalizeImageUrlList(urls, singleUrl, expectedLength) { + const list = Array.isArray(urls) + ? urls.map(function (item) { return String(item || '') }) + : (singleUrl ? [String(singleUrl)] : []) + + while (list.length < expectedLength) { + list.push('') + } + + return list.slice(0, Math.max(expectedLength, list.length)) + } + + function normalizeImageAttachmentList(attachments, singleAttachment, expectedLength) { + const list = Array.isArray(attachments) + ? attachments.slice() + : (singleAttachment ? [singleAttachment] : []) + + while (list.length < expectedLength) { + list.push(null) + } + + return list.slice(0, Math.max(expectedLength, list.length)) + } + + function applyItemImageSummary(item) { + const imageIds = normalizeAttachmentIdList(item && item.imageIds) + item.imageIds = imageIds + item.image = imageIds.join('|') + item.imageUrls = normalizeImageUrlList(item && item.imageUrls, item && item.imageUrl, imageIds.length) + item.imageAttachments = normalizeImageAttachmentList(item && item.imageAttachments, item && item.imageAttachment, imageIds.length) + item.imageUrl = item.imageUrls.length ? item.imageUrls[0] : '' + item.imageAttachment = item.imageAttachments.length ? item.imageAttachments[0] : null + return item + } + function renderEnumPreviewItem(item) { const desc = escapeHtml(item && item.description ? item.description : '(无描述)') - const imageHtml = item && item.imageUrl - ? '' + const imageUrls = normalizeImageUrlList(item && item.imageUrls, item && item.imageUrl, normalizeAttachmentIdList(item && item.image).length) + const imageHtml = imageUrls.length + ? '
' + imageUrls.map(function (url) { + if (!url) { + return '' + } + return '' + }).join('') + '
' : '无图' - return '
' + imageHtml + '' + desc + '
' + return '
' + imageHtml + '
' + desc + '
' } function renderItemsPreview(items, previewKey, isExpanded) { @@ -516,16 +597,19 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { remarkInput.value = record ? (record.dict_word_remark || '') : '' state.items = record && Array.isArray(record.items) && record.items.length ? record.items.map(function (item) { - return { + return applyItemImageSummary({ enum: item.enum, description: item.description, image: item.image || '', + imageIds: normalizeAttachmentIdList(item.imageIds || item.image), + imageUrls: Array.isArray(item.imageUrls) ? item.imageUrls : (item.imageUrl ? [item.imageUrl] : []), + imageAttachments: Array.isArray(item.imageAttachments) ? item.imageAttachments : (item.imageAttachment ? [item.imageAttachment] : []), imageUrl: item.imageUrl || '', imageAttachment: item.imageAttachment || null, sortOrder: item.sortOrder, - } + }) }) - : [{ enum: '', description: '', image: '', imageUrl: '', imageAttachment: null, sortOrder: 1 }] + : [applyItemImageSummary({ enum: '', description: '', image: '', imageIds: [], imageUrls: [], imageAttachments: [], imageUrl: '', imageAttachment: null, sortOrder: 1 })] normalizeItemEnums() renderItemsEditor() editorModal.classList.add('show') @@ -562,27 +646,49 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { function renderItemsEditor() { itemsBody.innerHTML = state.items.map(function (item, index) { - const imageCell = item.imageUrl - ? '
' + escapeHtml(item.image || '') + '
' + const imageIds = normalizeAttachmentIdList(item.imageIds || item.image) + const imageUrls = normalizeImageUrlList(item.imageUrls, item.imageUrl, imageIds.length) + const imageCell = imageIds.length + ? '
' + imageIds.map(function (imageId, imageIndex) { + const imageUrl = imageUrls[imageIndex] || '' + const thumbHtml = imageUrl + ? '' + : '无图' + return '
' + + '
' + thumbHtml + '
' + + '
' + + '#' + (imageIndex + 1) + '' + + '' + + '
' + + '
' + }).join('') + '
' : '
未上传图片
' return '' - + '' + + '' + '' - + '' - + '' + '' }).join('') } - async function setItemImageFromFile(index, file) { - if (!file) { + async function addItemImagesFromFiles(index, files) { + const validFiles = Array.from(files || []).filter(function (file) { + return !!file + }) + + if (!validFiles.length) { return } @@ -594,10 +700,22 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { setStatus('正在上传字典项图片...', '') showLoading('正在上传字典项图片,请稍候...') try { - const attachment = await uploadAttachment(file, 'dict-item-' + (index + 1)) - state.items[index].image = attachment.attachments_id - state.items[index].imageUrl = attachment.attachments_url || '' - state.items[index].imageAttachment = attachment + for (let fileIndex = 0; fileIndex < validFiles.length; fileIndex += 1) { + const attachment = await uploadAttachment(validFiles[fileIndex], 'dict-item-' + (index + 1) + '-' + (fileIndex + 1)) + if (!state.items[index]) { + break + } + + state.items[index].imageIds = normalizeAttachmentIdList(state.items[index].imageIds || state.items[index].image) + state.items[index].imageUrls = normalizeImageUrlList(state.items[index].imageUrls, state.items[index].imageUrl, state.items[index].imageIds.length) + state.items[index].imageAttachments = normalizeImageAttachmentList(state.items[index].imageAttachments, state.items[index].imageAttachment, state.items[index].imageIds.length) + + state.items[index].imageIds.push(attachment.attachments_id || '') + state.items[index].imageUrls.push(attachment.attachments_url || '') + state.items[index].imageAttachments.push(attachment) + applyItemImageSummary(state.items[index]) + } + renderItemsEditor() setStatus('字典项图片上传成功。', 'success') } catch (err) { @@ -616,6 +734,9 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { enum: state.items[index] ? String(state.items[index].enum || '') : '', description: descriptionInput.value.trim(), image: state.items[index] ? (state.items[index].image || '') : '', + imageIds: state.items[index] ? normalizeAttachmentIdList(state.items[index].imageIds || state.items[index].image) : [], + imageUrls: state.items[index] ? normalizeImageUrlList(state.items[index].imageUrls, state.items[index].imageUrl, normalizeAttachmentIdList(state.items[index].imageIds || state.items[index].image).length) : [], + imageAttachments: state.items[index] ? normalizeImageAttachmentList(state.items[index].imageAttachments, state.items[index].imageAttachment, normalizeAttachmentIdList(state.items[index].imageIds || state.items[index].image).length) : [], imageUrl: state.items[index] ? (state.items[index].imageUrl || '') : '', imageAttachment: state.items[index] ? (state.items[index].imageAttachment || null) : null, sortOrder: Number(sortOrderInput.value || index + 1), @@ -628,12 +749,14 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { if (!rows.length) { return } - state.items = collectItemsFromEditor() + state.items = collectItemsFromEditor().map(function (item) { + return applyItemImageSummary(item) + }) } - async function uploadItemImage(index, inputEl) { - const file = inputEl && inputEl.files && inputEl.files[0] - await setItemImageFromFile(index, file) + async function uploadItemImages(index, inputEl) { + const files = inputEl && inputEl.files ? inputEl.files : [] + await addItemImagesFromFiles(index, files) } async function loadList() { @@ -777,15 +900,109 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { imageViewerImg.src = url imageViewer.classList.add('show') } - window.__uploadItemImage = uploadItemImage + window.__uploadItemImages = uploadItemImages window.__allowItemDrop = function (event) { event.preventDefault() } window.__dropItemImage = function (index, event) { event.preventDefault() const files = event.dataTransfer && event.dataTransfer.files - const file = files && files[0] - setItemImageFromFile(index, file) + addItemImagesFromFiles(index, files) + } + window.__startItemImageDrag = function (itemIndex, imageIndex, event) { + state.draggingImage = { + itemIndex: itemIndex, + imageIndex: imageIndex, + } + + if (event && event.dataTransfer) { + event.dataTransfer.effectAllowed = 'move' + } + + const tile = event && event.currentTarget + if (tile && tile.classList) { + tile.classList.add('dragging') + } + } + window.__endItemImageDrag = function (event) { + const tile = event && event.currentTarget + if (tile && tile.classList) { + tile.classList.remove('dragging') + } + } + window.__allowItemImageDrop = function (event) { + event.preventDefault() + if (event && event.dataTransfer) { + event.dataTransfer.dropEffect = 'move' + } + } + window.__dropItemImageAt = function (itemIndex, targetImageIndex, event) { + event.preventDefault() + + const dragging = state.draggingImage + state.draggingImage = null + + if (!dragging || dragging.itemIndex !== itemIndex) { + return + } + + syncItemsStateFromEditor() + const item = state.items[itemIndex] + if (!item) { + return + } + + const imageIds = normalizeAttachmentIdList(item.imageIds || item.image) + if (!imageIds.length) { + return + } + + const sourceIndex = dragging.imageIndex + if (sourceIndex === targetImageIndex || sourceIndex < 0 || sourceIndex >= imageIds.length || targetImageIndex < 0 || targetImageIndex >= imageIds.length) { + return + } + + const imageUrls = normalizeImageUrlList(item.imageUrls, item.imageUrl, imageIds.length) + const imageAttachments = normalizeImageAttachmentList(item.imageAttachments, item.imageAttachment, imageIds.length) + + const movedId = imageIds.splice(sourceIndex, 1)[0] + const movedUrl = imageUrls.splice(sourceIndex, 1)[0] + const movedAttachment = imageAttachments.splice(sourceIndex, 1)[0] + + imageIds.splice(targetImageIndex, 0, movedId) + imageUrls.splice(targetImageIndex, 0, movedUrl) + imageAttachments.splice(targetImageIndex, 0, movedAttachment) + + item.imageIds = imageIds + item.imageUrls = imageUrls + item.imageAttachments = imageAttachments + applyItemImageSummary(item) + renderItemsEditor() + } + window.__removeItemImage = function (index, imageIndex) { + syncItemsStateFromEditor() + const item = state.items[index] + if (!item) { + return + } + + const imageIds = normalizeAttachmentIdList(item.imageIds || item.image) + if (imageIndex < 0 || imageIndex >= imageIds.length) { + return + } + + const imageUrls = normalizeImageUrlList(item.imageUrls, item.imageUrl, imageIds.length) + const imageAttachments = normalizeImageAttachmentList(item.imageAttachments, item.imageAttachment, imageIds.length) + + imageIds.splice(imageIndex, 1) + imageUrls.splice(imageIndex, 1) + imageAttachments.splice(imageIndex, 1) + + item.imageIds = imageIds + item.imageUrls = imageUrls + item.imageAttachments = imageAttachments + applyItemImageSummary(item) + renderItemsEditor() } window.__clearItemImage = function (index) { syncItemsStateFromEditor() @@ -793,16 +1010,19 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { return } state.items[index].image = '' + state.items[index].imageIds = [] + state.items[index].imageUrls = [] + state.items[index].imageAttachments = [] state.items[index].imageUrl = '' state.items[index].imageAttachment = null renderItemsEditor() - setStatus('已清空该枚举项图片。', 'success') + setStatus('已清空该枚举项所有图片。', 'success') } window.__removeItem = function (index) { syncItemsStateFromEditor() state.items.splice(index, 1) if (!state.items.length) { - state.items.push({ enum: '', description: '', image: '', imageUrl: '', imageAttachment: null, sortOrder: 1 }) + state.items.push(applyItemImageSummary({ enum: '', description: '', image: '', imageIds: [], imageUrls: [], imageAttachments: [], imageUrl: '', imageAttachment: null, sortOrder: 1 })) } normalizeItemEnums() renderItemsEditor() @@ -839,7 +1059,7 @@ routerAdd('GET', '/manage/dictionary-manage', function (e) { document.getElementById('addItemBtn').addEventListener('click', function () { syncItemsStateFromEditor() const used = new Set(state.items.map(function (item) { return String(item.enum || '') })) - state.items.push({ enum: nextAutoEnum(used), description: '', image: '', imageUrl: '', imageAttachment: null, sortOrder: state.items.length + 1 }) + state.items.push(applyItemImageSummary({ enum: nextAutoEnum(used), description: '', image: '', imageIds: [], imageUrls: [], imageAttachments: [], imageUrl: '', imageAttachment: null, sortOrder: state.items.length + 1 })) renderItemsEditor() scrollEditorModalToBottom() }) diff --git a/pocket-base/spec/openapi-wx.yaml b/pocket-base/spec/openapi-wx.yaml index 54dcd71..039bd76 100644 --- a/pocket-base/spec/openapi-wx.yaml +++ b/pocket-base/spec/openapi-wx.yaml @@ -753,10 +753,31 @@ paths: updated: 记录更新时间 | string document_id: 文档业务ID | string document_create: 文档创建时间,由数据库自动生成 | string + document_effect_date: 文档生效日期 | string + document_expiry_date: 文档到期日期 | string document_title: 文档标题 | string document_type: 文档类型,按system_dict_id@dict_word_enum保存 | string + document_subtitle: 文档副标题 | string + document_summary: 文档摘要 | string + document_content: 正文内容 | string + document_image: 图片附件ID串,底层按|分隔 | string + document_video: 视频附件ID串,底层按|分隔 | string + document_file: 文件附件ID串,底层按|分隔 | string document_status: 文档状态 | string document_owner: 上传者openid | string + document_relation_model: 关联机型标识 | string + document_keywords: 关键词,多选按|分隔 | string + document_share_count: 分享次数 | number + document_download_count: 下载次数 | number + document_favorite_count: 收藏次数 | number + document_embedding_status: 文档嵌入状态 | string + document_embedding_error: 文档嵌入错误原因 | string + document_embedding_lasttime: 最后一次嵌入更新时间 | string + document_vector_version: 向量版本号或模型名称 | string + document_product_categories: 产品关联文档,多选按|分隔 | string + document_application_scenarios: 筛选依据,多选按|分隔 | string + document_hotel_type: 适用场景,多选按|分隔 | string + document_remark: 备注 | string filterByTypeToken: value: page: 页码 | integer @@ -771,10 +792,31 @@ paths: updated: 记录更新时间 | string document_id: 文档业务ID | string document_create: 文档创建时间,由数据库自动生成 | string + document_effect_date: 文档生效日期 | string + document_expiry_date: 文档到期日期 | string document_title: 文档标题 | string document_type: 文档类型,按system_dict_id@dict_word_enum保存 | string + document_subtitle: 文档副标题 | string + document_summary: 文档摘要 | string + document_content: 正文内容 | string + document_image: 图片附件ID串,底层按|分隔 | string + document_video: 视频附件ID串,底层按|分隔 | string + document_file: 文件附件ID串,底层按|分隔 | string document_status: 文档状态 | string document_owner: 上传者openid | string + document_relation_model: 关联机型标识 | string + document_keywords: 关键词,多选按|分隔 | string + document_share_count: 分享次数 | number + document_download_count: 下载次数 | number + document_favorite_count: 收藏次数 | number + document_embedding_status: 文档嵌入状态 | string + document_embedding_error: 文档嵌入错误原因 | string + document_embedding_lasttime: 最后一次嵌入更新时间 | string + document_vector_version: 向量版本号或模型名称 | string + document_product_categories: 产品关联文档,多选按|分隔 | string + document_application_scenarios: 筛选依据,多选按|分隔 | string + document_hotel_type: 适用场景,多选按|分隔 | string + document_remark: 备注 | string - id: ofy47wp9mmm0aub collectionId: pbc_3636602973 collectionName: tbl_document @@ -782,10 +824,31 @@ paths: updated: '2026-03-28 07:20:00.000Z' document_id: DOC-1774680568340-TeUSQn document_create: '2026-03-28 08:22:48.000Z' + document_effect_date: '' + document_expiry_date: '' document_title: 易从碳达人节能系统,为酒店每天每间房省二元,以智能推动酒店ESG双碳落地!上海酒店用品展我们在E7A01等您!! document_type: DICT-1774599144591-hAEFQj@UT1 + document_subtitle: '' + document_summary: '' + document_content: '' + document_image: ATT-1774680568287-zuhJWN + document_video: '' + document_file: '' document_status: 有效 document_owner: su13106859882 + document_relation_model: '' + document_keywords: '' + document_share_count: 0 + document_download_count: 0 + document_favorite_count: 0 + document_embedding_status: '' + document_embedding_error: '' + document_embedding_lasttime: '' + document_vector_version: '' + document_product_categories: '' + document_application_scenarios: '' + document_hotel_type: '' + document_remark: '' '400': description: 查询参数错误 content: @@ -1433,13 +1496,46 @@ components: type: string description: "文档创建时间,由数据库自动生成" example: 文档创建时间,由数据库自动生成 | string + document_effect_date: + type: string + description: "文档生效日期" + example: 文档生效日期 | string + document_expiry_date: + type: string + description: "文档到期日期" + example: 文档到期日期 | string document_title: type: string description: "文档标题" example: 文档标题 | string document_type: type: string + description: "文档类型,多选时按 system_dict_id@dict_word_enum|... 保存" example: 文档类型,按system_dict_id@dict_word_enum保存 | string + document_subtitle: + type: string + description: "文档副标题" + example: 文档副标题 | string + document_summary: + type: string + description: "文档摘要" + example: 文档摘要 | string + document_content: + type: string + description: "正文内容,保存 Markdown" + example: 正文内容 | string + document_image: + type: string + description: "图片附件 ID 集合,底层以 | 分隔" + example: 图片附件ID串,底层按|分隔 | string + document_video: + type: string + description: "视频附件 ID 集合,底层以 | 分隔" + example: 视频附件ID串,底层按|分隔 | string + document_file: + type: string + description: "文件附件 ID 集合,底层以 | 分隔" + example: 文件附件ID串,底层按|分隔 | string document_status: type: string description: "文档状态,仅 `有效` / `过期`" @@ -1448,6 +1544,58 @@ components: type: string description: "上传者 openid" example: 上传者openid | string + document_relation_model: + type: string + description: "关联机型 / 模型标识" + example: 关联机型标识 | string + document_keywords: + type: string + description: "关键词,多选后以 | 分隔" + example: 关键词,多选按|分隔 | string + document_share_count: + type: number + description: "分享次数" + example: 分享次数 | number + document_download_count: + type: number + description: "下载次数" + example: 下载次数 | number + document_favorite_count: + type: number + description: "收藏次数" + example: 收藏次数 | number + document_embedding_status: + type: string + description: "文档嵌入状态" + example: 文档嵌入状态 | string + document_embedding_error: + type: string + description: "文档嵌入错误原因" + example: 文档嵌入错误原因 | string + document_embedding_lasttime: + type: string + description: "最后一次嵌入更新时间" + example: 最后一次嵌入更新时间 | string + document_vector_version: + type: string + description: "向量版本号 / 模型名称" + example: 向量版本号或模型名称 | string + document_product_categories: + type: string + description: "产品关联文档,多选后以 | 分隔" + example: 产品关联文档,多选按|分隔 | string + document_application_scenarios: + type: string + description: "筛选依据,多选后以 | 分隔" + example: 筛选依据,多选按|分隔 | string + document_hotel_type: + type: string + description: "适用场景,多选后以 | 分隔" + example: 适用场景,多选按|分隔 | string + document_remark: + type: string + description: "备注" + example: 备注 | string PocketBaseDocumentRecord: allOf: - $ref: '#/components/schemas/PocketBaseRecordBase' @@ -1460,10 +1608,31 @@ components: updated: 记录更新时间 | string document_id: 文档业务ID | string document_create: 文档创建时间,由数据库自动生成 | string + document_effect_date: 文档生效日期 | string + document_expiry_date: 文档到期日期 | string document_title: 文档标题 | string document_type: 文档类型,按system_dict_id@dict_word_enum保存 | string + document_subtitle: 文档副标题 | string + document_summary: 文档摘要 | string + document_content: 正文内容 | string + document_image: 图片附件ID串,底层按|分隔 | string + document_video: 视频附件ID串,底层按|分隔 | string + document_file: 文件附件ID串,底层按|分隔 | string document_status: 文档状态 | string document_owner: 上传者openid | string + document_relation_model: 关联机型标识 | string + document_keywords: 关键词,多选按|分隔 | string + document_share_count: 分享次数 | number + document_download_count: 下载次数 | number + document_favorite_count: 收藏次数 | number + document_embedding_status: 文档嵌入状态 | string + document_embedding_error: 文档嵌入错误原因 | string + document_embedding_lasttime: 最后一次嵌入更新时间 | string + document_vector_version: 向量版本号或模型名称 | string + document_product_categories: 产品关联文档,多选按|分隔 | string + document_application_scenarios: 筛选依据,多选按|分隔 | string + document_hotel_type: 适用场景,多选按|分隔 | string + document_remark: 备注 | string PocketBaseDocumentListResponse: type: object required: @@ -1510,10 +1679,31 @@ components: updated: 记录更新时间 | string document_id: 文档业务ID | string document_create: 文档创建时间,由数据库自动生成 | string + document_effect_date: 文档生效日期 | string + document_expiry_date: 文档到期日期 | string document_title: 文档标题 | string document_type: 文档类型,按system_dict_id@dict_word_enum保存 | string + document_subtitle: 文档副标题 | string + document_summary: 文档摘要 | string + document_content: 正文内容 | string + document_image: 图片附件ID串,底层按|分隔 | string + document_video: 视频附件ID串,底层按|分隔 | string + document_file: 文件附件ID串,底层按|分隔 | string document_status: 文档状态 | string document_owner: 上传者openid | string + document_relation_model: 关联机型标识 | string + document_keywords: 关键词,多选按|分隔 | string + document_share_count: 分享次数 | number + document_download_count: 下载次数 | number + document_favorite_count: 收藏次数 | number + document_embedding_status: 文档嵌入状态 | string + document_embedding_error: 文档嵌入错误原因 | string + document_embedding_lasttime: 最后一次嵌入更新时间 | string + document_vector_version: 向量版本号或模型名称 | string + document_product_categories: 产品关联文档,多选按|分隔 | string + document_application_scenarios: 筛选依据,多选按|分隔 | string + document_hotel_type: 适用场景,多选按|分隔 | string + document_remark: 备注 | string PocketBaseNativeError: type: object properties:
描述配置 图片排序操作
' + + '
' + + '
描述
' + + '
排序
' + + '
' + + '
' + + '
' + imageCell + '
' - + '' - + '' + + '' + + '' + '
' - + '
支持拖拽图片到本区域上传
' + + '
支持拖拽多张图片上传;图片可拖动调整顺序。
' + '