share-home 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/_events_57266.json +1 -0
- package/package.json +1 -1
- package/src/services/fileService.ts +160 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"eventName":"NEXT_CLI_SESSION_STOPPED","payload":{"nextVersion":"16.2.6","nodeVersion":"v24.14.1","cliCommand":"dev","durationMilliseconds":172,"turboFlag":false,"pagesDir":false,"appDir":true,"isRspack":false}}]
|
package/package.json
CHANGED
|
@@ -19,6 +19,15 @@ export interface SharedFile {
|
|
|
19
19
|
uploadedAt: number;
|
|
20
20
|
deviceInfo: string;
|
|
21
21
|
filePath: string;
|
|
22
|
+
boxId?: string; // 新增:所属收纳盒ID
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface SharedBox {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
color: string; // 渐变色样式
|
|
30
|
+
createdAt: number;
|
|
22
31
|
}
|
|
23
32
|
|
|
24
33
|
export class FileService {
|
|
@@ -44,7 +53,10 @@ export class FileService {
|
|
|
44
53
|
public static getInstance(): FileService {
|
|
45
54
|
const globalSymbols = global as any;
|
|
46
55
|
// 热重载自愈:若全局单例残留了旧方法,强制清空以在下一句重新 new 挂载新定义!
|
|
47
|
-
if (globalSymbols.__file_service_instance__ &&
|
|
56
|
+
if (globalSymbols.__file_service_instance__ && (
|
|
57
|
+
typeof globalSymbols.__file_service_instance__.registerTransferTask !== 'function' ||
|
|
58
|
+
typeof globalSymbols.__file_service_instance__.createSharedBox !== 'function'
|
|
59
|
+
)) {
|
|
48
60
|
console.warn('[FileService] 检测到 Next.js 热重载全局残留旧版单例,正在强制清空并重新初始化新版单例...');
|
|
49
61
|
globalSymbols.__file_service_instance__ = null;
|
|
50
62
|
}
|
|
@@ -379,7 +391,7 @@ export class FileService {
|
|
|
379
391
|
/**
|
|
380
392
|
* 注册一个公共共享文件
|
|
381
393
|
*/
|
|
382
|
-
public registerSharedFile(id: string, fileName: string, fileSize: number, filePath: string, deviceInfo: string): void {
|
|
394
|
+
public registerSharedFile(id: string, fileName: string, fileSize: number, filePath: string, deviceInfo: string, boxId?: string): void {
|
|
383
395
|
// 1. 先安全读取元数据索引文件,将当前新文件提前登记,解决物理合并落盘瞬时与 getSharedFiles() 产生的 Race Condition
|
|
384
396
|
let indexedFiles: SharedFile[] = [];
|
|
385
397
|
const metaPath = this.getSharedFilesPath();
|
|
@@ -398,7 +410,8 @@ export class FileService {
|
|
|
398
410
|
fileSize,
|
|
399
411
|
uploadedAt: Date.now(),
|
|
400
412
|
deviceInfo,
|
|
401
|
-
filePath
|
|
413
|
+
filePath,
|
|
414
|
+
boxId: boxId || undefined
|
|
402
415
|
};
|
|
403
416
|
|
|
404
417
|
// 剔除相同 id
|
|
@@ -601,4 +614,148 @@ export class FileService {
|
|
|
601
614
|
console.log(`[FileService] 已清空客户端 ${clientId} 所有完结的物理互传任务记录`);
|
|
602
615
|
}
|
|
603
616
|
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* 获取共享收纳盒元数据文件路径
|
|
620
|
+
*/
|
|
621
|
+
private getSharedBoxesPath(): string {
|
|
622
|
+
const storageDir = ConfigService.getInstance().getStoragePath();
|
|
623
|
+
return path.join(storageDir, 'shared_boxes.json');
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* 获取所有注册的公共共享收纳盒列表
|
|
628
|
+
*/
|
|
629
|
+
public getSharedBoxes(): SharedBox[] {
|
|
630
|
+
const filePath = this.getSharedBoxesPath();
|
|
631
|
+
if (!fs.existsSync(filePath)) {
|
|
632
|
+
return [];
|
|
633
|
+
}
|
|
634
|
+
try {
|
|
635
|
+
const data = fs.readFileSync(filePath, 'utf-8');
|
|
636
|
+
return JSON.parse(data);
|
|
637
|
+
} catch (err) {
|
|
638
|
+
console.error('[FileService] 读取收纳盒元数据失败:', err);
|
|
639
|
+
return [];
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* 将收纳盒列表元数据写入 JSON
|
|
645
|
+
*/
|
|
646
|
+
private writeSharedBoxesMetadata(boxes: SharedBox[]): void {
|
|
647
|
+
const filePath = this.getSharedBoxesPath();
|
|
648
|
+
try {
|
|
649
|
+
fs.writeFileSync(filePath, JSON.stringify(boxes, null, 2), 'utf-8');
|
|
650
|
+
} catch (err) {
|
|
651
|
+
console.error('[FileService] 写入收纳盒元数据失败:', err);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* 创建一个全新的共享收纳盒
|
|
657
|
+
*/
|
|
658
|
+
public createSharedBox(name: string, description?: string, color?: string): SharedBox {
|
|
659
|
+
const boxes = this.getSharedBoxes();
|
|
660
|
+
const boxId = `box_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
661
|
+
|
|
662
|
+
// 默认高质感炫彩渐变色预设 (HSL Tailormade Rich Aesthetics Gradients)
|
|
663
|
+
const defaultGradients = [
|
|
664
|
+
'linear-gradient(135deg, #FF6B6B 0%, #FF8E53 100%)', // 熔岩橙
|
|
665
|
+
'linear-gradient(135deg, #7F00FF 0%, #E100FF 100%)', // 霓虹紫
|
|
666
|
+
'linear-gradient(135deg, #00C6FF 0%, #0072FF 100%)', // 极光蓝
|
|
667
|
+
'linear-gradient(135deg, #11998e 0%, #38ef7d 100%)', // 翡翠绿
|
|
668
|
+
'linear-gradient(135deg, #f12711 0%, #f5af19 100%)' // 日落金
|
|
669
|
+
];
|
|
670
|
+
|
|
671
|
+
const selectedColor = color || defaultGradients[boxes.length % defaultGradients.length];
|
|
672
|
+
|
|
673
|
+
const newBox: SharedBox = {
|
|
674
|
+
id: boxId,
|
|
675
|
+
name,
|
|
676
|
+
description,
|
|
677
|
+
color: selectedColor,
|
|
678
|
+
createdAt: Date.now()
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
boxes.push(newBox);
|
|
682
|
+
this.writeSharedBoxesMetadata(boxes);
|
|
683
|
+
|
|
684
|
+
console.log(`[FileService] 收纳盒已成功创建并保存: ${name} (${boxId})`);
|
|
685
|
+
|
|
686
|
+
// 广播最新的收纳盒列表给局域网所有在线伙伴
|
|
687
|
+
SocketService.getInstance().broadcast('shared-boxes:update', boxes);
|
|
688
|
+
|
|
689
|
+
return newBox;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* 物理删除某个共享收纳盒 (非破坏性:仅将属于它的文件移回大厅未分类,防止物理文件丢失)
|
|
694
|
+
*/
|
|
695
|
+
public deleteSharedBox(boxId: string): boolean {
|
|
696
|
+
const boxes = this.getSharedBoxes();
|
|
697
|
+
const filteredBoxes = boxes.filter(b => b.id !== boxId);
|
|
698
|
+
if (boxes.length === filteredBoxes.length) {
|
|
699
|
+
return false;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// 1. 写回收纳盒元数据
|
|
703
|
+
this.writeSharedBoxesMetadata(filteredBoxes);
|
|
704
|
+
|
|
705
|
+
// 2. 清洗文件元数据:将该盒子下的所有文件安全释放(重置 boxId 为 undefined)
|
|
706
|
+
const files = this.getSharedFiles();
|
|
707
|
+
let hasChanges = false;
|
|
708
|
+
const updatedFiles = files.map(file => {
|
|
709
|
+
if (file.boxId === boxId) {
|
|
710
|
+
hasChanges = true;
|
|
711
|
+
const { boxId: _, ...rest } = file; // 剔除 boxId
|
|
712
|
+
return rest;
|
|
713
|
+
}
|
|
714
|
+
return file;
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
if (hasChanges) {
|
|
718
|
+
this.writeSharedFilesMetadata(updatedFiles);
|
|
719
|
+
// 广播更新文件列表
|
|
720
|
+
SocketService.getInstance().broadcast('shared-files:update', updatedFiles.sort((a, b) => b.uploadedAt - a.uploadedAt));
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
console.log(`[FileService] 收纳盒 ${boxId} 已被成功删除,受影响文件已安全释放回未分类大厅`);
|
|
724
|
+
|
|
725
|
+
// 3. 广播更新收纳盒列表
|
|
726
|
+
SocketService.getInstance().broadcast('shared-boxes:update', filteredBoxes);
|
|
727
|
+
return true;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* 将指定的一个或多个共享文件转移到特定收纳盒中 (移出为 null)
|
|
732
|
+
*/
|
|
733
|
+
public moveFilesToBox(fileIds: string[], boxId: string | null): boolean {
|
|
734
|
+
const files = this.getSharedFiles();
|
|
735
|
+
let hasChanges = false;
|
|
736
|
+
|
|
737
|
+
const updatedFiles = files.map(file => {
|
|
738
|
+
if (fileIds.includes(file.id)) {
|
|
739
|
+
hasChanges = true;
|
|
740
|
+
if (boxId) {
|
|
741
|
+
return { ...file, boxId };
|
|
742
|
+
} else {
|
|
743
|
+
const { boxId: _, ...rest } = file;
|
|
744
|
+
return rest;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
return file;
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
if (hasChanges) {
|
|
751
|
+
this.writeSharedFilesMetadata(updatedFiles);
|
|
752
|
+
const sorted = updatedFiles.sort((a, b) => b.uploadedAt - a.uploadedAt);
|
|
753
|
+
console.log(`[FileService] 成功将 ${fileIds.length} 个文件转移到收纳盒: ${boxId || '未分类大厅'}`);
|
|
754
|
+
// 广播更新
|
|
755
|
+
SocketService.getInstance().broadcast('shared-files:update', sorted);
|
|
756
|
+
return true;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
604
761
|
}
|