# NovaStorage 使用规则(cc 编程工具) 面向 cc 的编程规则,帮助你在任意页面仅通过 `cid` 即可加载与使用存储工具,无需关注 Provider 细节。 ## 快速约定 - 仅需 `cid`:使用 `NovaStorage.withCid(cid)` 自动选择企业账套 Provider。 - 统一返回:上传结果为 `NovaFile`,含 `key`, `url`, `name`, `type`, `size`, `metadata`, `md5` 等。 - 生成 Key:默认格式 `storage/company////-`。 - 可选前缀:通过 `prefixKey` 在公司段后、日期目录前插入自定义目录(自动去除首尾斜杠)。 - 查重与保存:封装 `getAttachmentByMd5` 与 `saveAttachment`,避免重复上传并统一写入 `Attachment`。 ## 依赖导入 ```ts import { NovaStorage, NovaFile } from 'fmode-ng/core'; ``` ## 初始化(仅凭 cid) ```ts const cid = localStorage.getItem('company')!; // 或服务获取 const storage = await NovaStorage.withCid(cid); ``` ## 上传文件(含进度与 prefixKey) ```ts const file = (event.target as HTMLInputElement).files![0]; const uploaded: NovaFile = await storage.upload(file, { prefixKey: 'project/pid/', // 项目页需要加项目前缀 onProgress: (p) => console.log('progress %', p.total.percent), }); console.log(uploaded.key, uploaded.url); ``` # Attachment 数据范式说明 # Parse 服务 `Attachment` 表结构分析 `Attachment` 表是 Parse 服务中用于**存储文件附件核心信息**的业务表,主要关联文件元数据、上传用户、所属公司/分类等维度,支撑附件的管理、查询与关联业务(如文档附件、媒体文件关联等)。 ## 一、表核心定位 用于记录附件的基础属性(名称、大小、URL)、校验信息(MD5)、关联主体(用户、公司、分类)及文件元数据(分辨率、时长等),是附件与业务模块(如内容、用户系统)的关联枢纽。 ## 二、字段详情 ### 1. 核心业务字段(自定义字段) 以下字段为代码中明确通过 `attachment.set(...)` 定义的业务字段,涵盖附件的核心属性与关联关系: | 字段名 | 数据类型 | 赋值逻辑 | 字段含义 | 可选性 | |--------------|---------------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------|--------| | `size` | Number(整数) | 取自 `file.size`(`NovaFile` 或传入对象的 `size` 字段,单位:字节) | 附件文件的实际大小,用于前端展示、容量统计等 | 必选 | | `url` | String | 1. 优先取 `file.url`;
2. 若 `url` 非 HTTP 开头,拼接 `domain` 前缀;
3. 清除 `undefined/` 无效前缀 | 附件的**可访问地址**(绝对 URL),用于前端下载、预览附件 | 必选 | | `name` | String | 取自 `file.name`(`NovaFile` 或传入对象的文件名,含扩展名) | 附件的原始文件名(如 `test.jpg`),用于前端展示、文件识别 | 必选 | | `mime` | String | 取自 `file.type`(MIME 类型,如 `image/jpeg`、`audio/mp3`、`video/mp4`) | 附件的文件类型,用于判断文件类别(图片/音视频/文档)、前端渲染方式 | 必选 | | `md5` | String | 1. 优先取 `file.md5`;
2. 若有 `srcFile`(原始 `File/Blob`),通过 `calcFileMd5` 计算 | 附件文件的 MD5 哈希值,用于**文件完整性校验**(避免传输损坏)、去重判断 | 可选 | | `metadata` | Object(嵌套结构) | 取自 `file.metadata`(若传入则直接存储,无则不主动生成) | 附件的**文件元数据**,随文件类型不同包含不同子字段(见下方补充) | 可选 | | `company` | Parse Pointer(关联 `Company` 表) | 取值优先级:`categoryId` > `this.cid` > localStorage 的 `company` 值 | 关联附件所属的公司,用于数据隔离(不同公司只能查看自己的附件) | 可选 | | `category` | Parse Pointer(关联 `Category` 表) | 取自传入的 `categoryId` 参数 | 关联附件所属的分类(如“产品图片”“合同附件”),用于附件分类管理 | 可选 | | `user` | Parse Pointer(关联 `_User` 表) | 取自 `Parse.User.current()`(当前登录用户),生成指向 `_User` 表的指针 | 记录附件的**上传用户**,用于追溯上传人、权限控制(如仅上传者可编辑) | 可选(无当前用户时不设置) | #### 补充:`metadata` 字段的常见子字段 `metadata` 存储文件的个性化元数据,具体子字段由文件类型决定(依赖 `getFileMetadata` 函数提取): | 子字段 | 数据类型 | 适用文件类型 | 含义 | |----------------|----------|--------------------|----------------------------------------------------------------------| | `width` | Number | 图片、视频 | 分辨率宽度(如图片 1920px,视频 1280px) | | `height` | Number | 图片、视频 | 分辨率高度(如图片 1080px,视频 720px) | | `duration` | Number | 音频、视频 | 媒体时长(单位:秒,如音频 120s,视频 300s) | | `lastModified` | Number | 所有文件 | 文件最后修改时间戳(取自 `file.lastModified` 或当前时间) | | `bitrate` | Number | 音频、视频(预留) | 媒体码率(代码类型定义中存在,暂未在 `extractMediaMetadata` 中实现) | | `codec` | String | 音频、视频(预留) | 媒体编码格式(如 H.264、MP3,暂未实现) | | `colorDepth` | Number | 图片(预留) | 图片色深(如 24 位真彩色,暂未实现) | ### 2. Parse 系统默认字段 所有 Parse Object(包括 `Attachment`)都会自动生成以下系统字段,无需手动赋值: | 字段名 | 数据类型 | 含义 | |----------------|------------|----------------------------------------------------------------------| | `objectId` | String | 表的**主键**(唯一标识),由 Parse 自动生成(如 `X7y8Z9a0B1c2D3e4`) | | `createdAt` | Date | 附件记录的**创建时间**(上传时间),自动生成 | | `updatedAt` | Date | 附件记录的**最后更新时间**(如修改分类、更新 URL),自动更新 | | `ACL` | Parse ACL | 附件的权限控制列表(默认继承 Parse 全局配置,可自定义读写权限) | ## 三、关键关联关系 `Attachment` 表通过 **Pointer 类型**与其他核心表关联,形成业务数据链路: 1. **与 `_User` 表**:通过 `user` 字段关联,追溯附件的上传用户,支持“个人附件列表”“按用户筛选附件”等场景。 2. **与 `Company` 表**:通过 `company` 字段关联,实现“公司级数据隔离”,确保不同公司用户仅能访问本公司的附件。 3. **与 `Category` 表**:通过 `category` 字段关联,支持附件的分类管理(如“产品素材”“财务文档”),便于筛选与归类。 ## 四、特殊处理逻辑 1. **URL 兼容性处理**:若传入的 `file.url` 是相对路径(非 HTTP 开头),自动拼接 `domain` 生成绝对 URL,避免前端无法访问。 2. **MD5 动态计算**:若未传入 `file.md5`,但提供了原始文件 `srcFile`,则通过 `calcFileMd5` 函数动态计算 MD5,保证校验信息的可用性。 3. **公司 ID 多来源 fallback**:`company` 字段优先取显式传入的 `companyId`,其次取当前实例的 `cid`、localStorage 缓存的 `company` 值,确保关联关系尽可能完整。