diff --git a/packages/core/client/src/collection-manager/Configuration/DeleteCollectionAction.tsx b/packages/core/client/src/collection-manager/Configuration/DeleteCollectionAction.tsx index 06817dfbaf..97784749bc 100644 --- a/packages/core/client/src/collection-manager/Configuration/DeleteCollectionAction.tsx +++ b/packages/core/client/src/collection-manager/Configuration/DeleteCollectionAction.tsx @@ -120,11 +120,15 @@ export const DeleteCollectionAction = (props) => { {isBulk ? ( - ) : ( - setVisible(true)} {...otherProps}> + setVisible(true)} + {...otherProps} + style={record.deletable === false ? { color: 'rgba(0, 0, 0, 0.25)', cursor: 'not-allowed' } : {}} + > {children || t('Delete')} )} diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/interfaces/attachment.ts b/packages/plugins/@nocobase/plugin-file-manager/src/client/interfaces/attachment.ts index a8f38d17e1..85cb977b0d 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/client/interfaces/attachment.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/interfaces/attachment.ts @@ -25,7 +25,7 @@ export class AttachmentFieldInterface extends CollectionFieldInterface { uiSchema: { type: 'array', // title, - 'x-component': 'Upload.Attachment', + 'x-component': 'AssociationField', 'x-use-component-props': 'useAttachmentFieldProps', }, }; diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/templates/file.ts b/packages/plugins/@nocobase/plugin-file-manager/src/client/templates/file.ts index 5d74d8ef53..8b7be1c95f 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/client/templates/file.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/templates/file.ts @@ -132,6 +132,7 @@ export class FileCollectionTemplate extends CollectionTemplate { target: 'storages', foreignKey: 'storageId', deletable: false, + interface: 'm2o', uiSchema: { type: 'string', title: `{{t("Storage", { ns: "${NAMESPACE}" })}}`, diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/common/collections/attachments.ts b/packages/plugins/@nocobase/plugin-file-manager/src/common/collections/attachments.ts index 8884cbd053..330df6d766 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/common/collections/attachments.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/common/collections/attachments.ts @@ -7,7 +7,10 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ +import { NAMESPACE } from '../constants'; + export default { + title: `{{t("Attachments", { ns: "${NAMESPACE}" })}}`, dumpRules: { group: 'user', }, @@ -19,26 +22,75 @@ export default { updatedBy: true, template: 'file', filterTargetKey: 'id', + deletable: false, fields: [ + { + type: 'bigInt', + name: 'id', + deletable: false, + interface: 'number', + autoIncrement: true, + uiSchema: { + type: 'number', + title: `{{t("ID")}}`, + 'x-component': 'InputNumber', + 'x-read-pretty': true, + }, + }, { comment: '用户文件名(不含扩展名)', type: 'string', name: 'title', + deletable: false, + interface: 'input', + uiSchema: { + type: 'string', + title: `{{t("Title")}}`, + 'x-component': 'Input', + }, }, { comment: '系统文件名(含扩展名)', type: 'string', name: 'filename', + deletable: false, + interface: 'input', + uiSchema: { + type: 'string', + title: `{{t("File name", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'Input', + 'x-read-pretty': true, + }, }, { comment: '扩展名(含“.”)', type: 'string', name: 'extname', + deletable: false, + interface: 'input', + uiSchema: { + type: 'string', + title: `{{t("Extension name", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'Input', + 'x-read-pretty': true, + }, }, { comment: '文件体积(字节)', type: 'integer', name: 'size', + deletable: false, + interface: 'integer', + uiSchema: { + type: 'number', + title: `{{t("Size", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'InputNumber', + 'x-read-pretty': true, + 'x-component-props': { + stringMode: true, + step: '0', + }, + }, }, // TODO: 使用暂不明确,以后再考虑 // { @@ -49,28 +101,81 @@ export default { { type: 'string', name: 'mimetype', + deletable: false, + interface: 'input', + uiSchema: { + type: 'string', + title: `{{t("MIME type", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'Input', + 'x-read-pretty': true, + }, }, { comment: '存储引擎', type: 'belongsTo', name: 'storage', + deletable: false, + interface: 'm2o', + uiSchema: { + type: 'string', + title: `{{t("Storage engine", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'Input', + 'x-read-pretty': true, + }, }, { comment: '相对路径(含“/”前缀)', type: 'text', name: 'path', + deletable: false, + interface: 'input', + uiSchema: { + type: 'string', + title: `{{t("Path", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'Input', + 'x-read-pretty': true, + }, }, { comment: '其他文件信息(如图片的宽高)', type: 'jsonb', name: 'meta', defaultValue: {}, + deletable: false, + interface: 'json', + uiSchema: { + type: 'object', + title: `{{t("Meta", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'Input.JSON', + 'x-read-pretty': true, + }, }, { comment: '网络访问地址', type: 'text', name: 'url', - // formula: '{{ storage.baseUrl }}{{ path }}/{{ filename }}' + deletable: false, + interface: 'url', + uiSchema: { + type: 'string', + title: `{{t("URL", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'Input.URL', + 'x-read-pretty': true, + }, + }, + // 用于预览 + { + interface: 'url', + type: 'text', + name: 'preview', + field: 'url', // 直接引用 url 字段 + deletable: false, + uiSchema: { + type: 'string', + title: `{{t("Preview", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'Preview', + 'x-read-pretty': true, + }, }, ], }; diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/common/constants.ts b/packages/plugins/@nocobase/plugin-file-manager/src/common/constants.ts index a40cc65d15..7ee31a77e6 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/common/constants.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/common/constants.ts @@ -7,4 +7,6 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ +export const NAMESPACE = 'file-manager'; + export const INVALID_FILENAME_CHARS = '<>?*~\\/'; diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/locale/zh-CN.json b/packages/plugins/@nocobase/plugin-file-manager/src/locale/zh-CN.json index 31fe9e3592..011ddc81c5 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/locale/zh-CN.json +++ b/packages/plugins/@nocobase/plugin-file-manager/src/locale/zh-CN.json @@ -12,6 +12,7 @@ "File storage": "文件存储", "File manager": "文件管理器", "Attachment": "附件", + "Attachments": "附件", "Allow uploading multiple files": "允许上传多个文件", "Storage": "存储空间", "Storages": "存储空间", diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/server/migrations/20250624212912-db2cm.ts b/packages/plugins/@nocobase/plugin-file-manager/src/server/migrations/20250624212912-db2cm.ts new file mode 100644 index 0000000000..4963bef370 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-file-manager/src/server/migrations/20250624212912-db2cm.ts @@ -0,0 +1,21 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { Migration } from '@nocobase/server'; +import { CollectionRepository } from '@nocobase/plugin-data-source-main'; + +export default class extends Migration { + on = 'afterLoad'; // 'beforeLoad' or 'afterLoad' + appVersion = '<1.8.0'; + + async up() { + const CollectionRepo = this.db.getRepository('collections') as CollectionRepository; + await CollectionRepo.db2cm('attachments'); + } +} diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts b/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts index c54fe59932..6e1c4ad133 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts @@ -163,6 +163,11 @@ export class PluginFileManagerServer extends Plugin { } async install() { + const collectionRepo = this.db.getRepository('collections'); + if (collectionRepo) { + await collectionRepo.db2cm('attachments'); + } + const defaultStorageType = this.storageTypes.get(DEFAULT_STORAGE_TYPE); if (defaultStorageType) {