feat: move revision tracking to ExportRecord, add perceptual hash comparison, cut list modal, and auto-start API
- Move Revision from Drawing to ExportRecord so each export captures its own revision snapshot - Add Hamming distance comparison for perceptual hashes (tolerance of 10 bits) to avoid false revision bumps - Replace CoenM.ImageHash with inline DifferenceHash impl (compatible with ImageSharp 3.x) - Increase PDF render DPI from 72 to 150 for better hash fidelity - Add download-dxfs-by-drawing endpoint for cross-export DXF zip downloads - Prefix DXF filenames with equipment number when no drawing number is present - Pass original filename to storage service for standalone part exports - Auto-start FabWorks.Api from ExportDXF client if not already running - Add cut list modal with copy-to-clipboard in the web UI - Update PDF hash on existing export records after upload - Bump static asset cache versions to v3 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,7 @@ namespace FabWorks.Api.Services
|
||||
public interface IFileStorageService
|
||||
{
|
||||
string OutputFolder { get; }
|
||||
Task<FileUploadResult> StoreDxfAsync(Stream stream, string equipment, string drawingNo, string itemNo, string contentHash);
|
||||
Task<FileUploadResult> StoreDxfAsync(Stream stream, string equipment, string drawingNo, string itemNo, string contentHash, string originalFileName = null);
|
||||
Task<FileUploadResult> StorePdfAsync(Stream stream, string equipment, string drawingNo, string contentHash, int? exportRecordId = null);
|
||||
Stream OpenBlob(string contentHash, string extension);
|
||||
bool BlobExists(string contentHash, string extension);
|
||||
@@ -39,9 +39,9 @@ namespace FabWorks.Api.Services
|
||||
Directory.CreateDirectory(blobRoot);
|
||||
}
|
||||
|
||||
public async Task<FileUploadResult> StoreDxfAsync(Stream stream, string equipment, string drawingNo, string itemNo, string contentHash)
|
||||
public async Task<FileUploadResult> StoreDxfAsync(Stream stream, string equipment, string drawingNo, string itemNo, string contentHash, string originalFileName = null)
|
||||
{
|
||||
var fileName = BuildDxfFileName(drawingNo, equipment, itemNo);
|
||||
var fileName = BuildDxfFileName(drawingNo, equipment, itemNo, originalFileName);
|
||||
|
||||
// Look up previous hash by drawing number + item number
|
||||
var drawingNumber = BuildDrawingNumber(equipment, drawingNo);
|
||||
@@ -147,8 +147,16 @@ namespace FabWorks.Api.Services
|
||||
return drawingNo ?? "";
|
||||
}
|
||||
|
||||
private static string BuildDxfFileName(string drawingNo, string equipment, string itemNo)
|
||||
private static string BuildDxfFileName(string drawingNo, string equipment, string itemNo, string originalFileName = null)
|
||||
{
|
||||
// No drawing number: use the original filename from the client
|
||||
if (string.IsNullOrEmpty(drawingNo) && !string.IsNullOrEmpty(originalFileName))
|
||||
{
|
||||
return originalFileName.EndsWith(".dxf", StringComparison.OrdinalIgnoreCase)
|
||||
? originalFileName
|
||||
: originalFileName + ".dxf";
|
||||
}
|
||||
|
||||
var drawingNumber = BuildDrawingNumber(equipment, drawingNo);
|
||||
var paddedItem = (itemNo ?? "").PadLeft(2, '0');
|
||||
if (!string.IsNullOrEmpty(drawingNumber) && !string.IsNullOrEmpty(itemNo))
|
||||
|
||||
Reference in New Issue
Block a user