|
@@ -911,20 +911,24 @@ export class StageOrderComponent implements OnInit {
|
|
|
const query = new Parse.Query('ProjectFile');
|
|
|
query.equalTo('project', this.project.toPointer());
|
|
|
query.include('uploadedBy');
|
|
|
+ query.include('attach');
|
|
|
query.descending('uploadedAt');
|
|
|
query.limit(50);
|
|
|
|
|
|
const files = await query.find();
|
|
|
|
|
|
- this.projectFiles = files.map((file: FmodeObject) => ({
|
|
|
- id: file.id || '',
|
|
|
- name: file.get('name') || file.get('originalName') || '',
|
|
|
- url: file.get('url') || '',
|
|
|
- type: file.get('type') || '',
|
|
|
- size: file.get('size') || 0,
|
|
|
- uploadedBy: file.get('uploadedBy')?.get('name') || '未知用户',
|
|
|
- uploadedAt: file.get('uploadedAt') || file.createdAt
|
|
|
- }));
|
|
|
+ this.projectFiles = files.map((file: FmodeObject) => {
|
|
|
+ const attach = file.get('attach');
|
|
|
+ return {
|
|
|
+ id: file.id || '',
|
|
|
+ name: attach?.get('name') || attach?.get('originalName') || file.get('name') || file.get('originalName') || '',
|
|
|
+ url: attach?.get('url') || file.get('url') || '',
|
|
|
+ type: attach?.get('type') || file.get('type') || '',
|
|
|
+ size: attach?.get('size') || file.get('size') || 0,
|
|
|
+ uploadedBy: file.get('uploadedBy')?.get('name') || '未知用户',
|
|
|
+ uploadedAt: file.get('uploadedAt') || file.createdAt
|
|
|
+ };
|
|
|
+ });
|
|
|
|
|
|
console.log(`✅ 加载了 ${this.projectFiles.length} 个项目文件`);
|
|
|
} catch (error) {
|
|
@@ -986,30 +990,43 @@ export class StageOrderComponent implements OnInit {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- // 保存文件信息到 ProjectFile 表
|
|
|
+ // 创建 Attachment 记录并设置元数据
|
|
|
+ const attachment = new Parse.Object('Attachment');
|
|
|
+ attachment.set('name', file.name);
|
|
|
+ attachment.set('originalName', file.name);
|
|
|
+ attachment.set('url', uploaded.url);
|
|
|
+ attachment.set('key', uploaded.key);
|
|
|
+ attachment.set('type', file.type || (uploaded?.metadata ? uploaded.metadata['mime'] : '') || '');
|
|
|
+ attachment.set('size', file.size);
|
|
|
+ attachment.set('md5', uploaded.md5);
|
|
|
+ attachment.set('metadata', uploaded.metadata || {});
|
|
|
+ attachment.set('source', source);
|
|
|
+ attachment.set('user', this.currentUser.toPointer());
|
|
|
+ const companyPtr = this.project?.get('company');
|
|
|
+ if (companyPtr) {
|
|
|
+ attachment.set('company', companyPtr.toPointer ? companyPtr.toPointer() : companyPtr);
|
|
|
+ }
|
|
|
+ const savedAttachment = await attachment.save();
|
|
|
+
|
|
|
+ // 保存文件信息到 ProjectFile 表,指向 attach
|
|
|
const projectFile = new Parse.Object('ProjectFile');
|
|
|
projectFile.set('project', this.project.toPointer());
|
|
|
- projectFile.set('name', file.name);
|
|
|
- projectFile.set('originalName', file.name);
|
|
|
- projectFile.set('url', uploaded.url);
|
|
|
- projectFile.set('key', uploaded.key);
|
|
|
- projectFile.set('type', file.type);
|
|
|
- projectFile.set('size', file.size);
|
|
|
+ projectFile.set('attach', savedAttachment.toPointer ? savedAttachment.toPointer() : savedAttachment);
|
|
|
projectFile.set('uploadedBy', this.currentUser.toPointer());
|
|
|
projectFile.set('uploadedAt', new Date());
|
|
|
projectFile.set('source', source); // 标记来源:企业微信拖拽或手动选择
|
|
|
- projectFile.set('md5', uploaded.md5);
|
|
|
- projectFile.set('metadata', uploaded.metadata);
|
|
|
+ // 兼容字段:保留 key(若旧代码需要)
|
|
|
+ projectFile.set('key', uploaded.key);
|
|
|
|
|
|
const savedFile = await projectFile.save();
|
|
|
|
|
|
- // 添加到本地列表
|
|
|
+ // 添加到本地列表(从 attach 读取展示字段)
|
|
|
this.projectFiles.unshift({
|
|
|
id: savedFile.id || '',
|
|
|
- name: file.name,
|
|
|
- url: uploaded.url || '',
|
|
|
- type: file.type,
|
|
|
- size: file.size,
|
|
|
+ name: savedAttachment.get('name'),
|
|
|
+ url: savedAttachment.get('url') || '',
|
|
|
+ type: savedAttachment.get('type') || '',
|
|
|
+ size: savedAttachment.get('size') || 0,
|
|
|
uploadedBy: this.currentUser.get('name'),
|
|
|
uploadedAt: new Date()
|
|
|
});
|
|
@@ -1108,12 +1125,17 @@ export class StageOrderComponent implements OnInit {
|
|
|
/**
|
|
|
* 格式化文件大小
|
|
|
*/
|
|
|
- formatFileSize(bytes: number): string {
|
|
|
- if (bytes === 0) return '0 Bytes';
|
|
|
- const k = 1024;
|
|
|
- const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
|
- const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
|
+ formatFileSize(size: number): string {
|
|
|
+ if (size == null || isNaN(size)) return '0 B';
|
|
|
+ const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
|
+ let idx = 0;
|
|
|
+ let value = size;
|
|
|
+ while (value >= 1024 && idx < units.length - 1) {
|
|
|
+ value /= 1024;
|
|
|
+ idx++;
|
|
|
+ }
|
|
|
+ const formatted = value >= 100 ? Math.round(value).toString() : value.toFixed(1);
|
|
|
+ return `${formatted} ${units[idx]}`;
|
|
|
}
|
|
|
|
|
|
/**
|