luo-image-annotator 0.0.12 → 0.0.13

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.
@@ -1,33 +1,33 @@
1
- (function(S,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],t):(S=typeof globalThis<"u"?globalThis:S||self,t(S.VueImageAnnotator={},S.Vue))})(this,(function(S,t){"use strict";var Qe=Object.defineProperty;var tn=(S,t,N)=>t in S?Qe(S,t,{enumerable:!0,configurable:!0,writable:!0,value:N}):S[t]=N;var _=(S,t,N)=>tn(S,typeof t!="symbol"?t+"":t,N);const N=(p,e)=>Math.sqrt(Math.pow(p.x-e.x,2)+Math.pow(p.y-e.y,2)),st=(p,e)=>{let i=!1;for(let n=0,l=e.length-1;n<e.length;l=n++){const c=e[n].x,h=e[n].y,a=e[l].x,g=e[l].y;h>p.y!=g>p.y&&p.x<(a-c)*(p.y-h)/(g-h)+c&&(i=!i)}return i},q=(p,e,i)=>{const n=i*(Math.PI/180),l=Math.cos(n),c=Math.sin(n),h=p.x-e.x,a=p.y-e.y;return{x:e.x+(h*l-a*c),y:e.y+(h*c+a*l)}};class it{constructor(e){_(this,"canvas");_(this,"ctx");_(this,"img");_(this,"annotations",[]);_(this,"currentTool",null);_(this,"interactionMode","none");_(this,"activeAnnotation",null);_(this,"hoverAnnotation",null);_(this,"isDrawing",!1);_(this,"isDragging",!1);_(this,"isPanning",!1);_(this,"panStartPoint",null);_(this,"dragStartPoint",null);_(this,"dragStartAnnotation",null);_(this,"lastMouseMovePoint",null);_(this,"isHoveringStartPoint",!1);_(this,"currentLabelColor","#FF4081");_(this,"visibleLabels",new Set);_(this,"selectedHandleIndex",-1);_(this,"hoverHandleIndex",-1);_(this,"scale",1);_(this,"offset",{x:0,y:0});_(this,"listeners",{});_(this,"imageUrl","");this.canvas=e;const i=e.getContext("2d");if(!i)throw new Error("Could not get 2d context");this.ctx=i,this.img=new Image,this.img.crossOrigin="Anonymous",this.img.onload=()=>{this.fitImageToCanvas(),this.render()},this.bindEvents()}on(e,i){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(i)}emit(e,i){this.listeners[e]&&this.listeners[e].forEach(n=>n(i))}loadImage(e){this.imageUrl=e,this.img.src=e,this.activeAnnotation=null,this.isDrawing=!1}setAnnotations(e){this.annotations=JSON.parse(JSON.stringify(e)),this.render()}getAnnotations(){return this.annotations}setTool(e){e==="pan"?(this.interactionMode="pan",this.currentTool=null,this.isPanning=!1,this.canvas.style.cursor="grab"):e==="select"?(this.interactionMode="select",this.currentTool=null,this.canvas.style.cursor="default"):e?(this.interactionMode="draw",this.currentTool=e,this.canvas.style.cursor="crosshair"):(this.interactionMode="none",this.currentTool=null,this.canvas.style.cursor="default"),this.activeAnnotation=null,this.isDrawing=!1,this.render()}setLabelStyle(e){this.currentLabelColor=e}setVisibleLabels(e){this.visibleLabels=new Set(e),this.render()}zoom(e){const n=e>0?this.scale*1.1:this.scale/1.1;if(n<.1||n>10)return;const l=this.canvas.width/2,c=this.canvas.height/2,h=this.toImageCoords(l,c);this.scale=n,this.offset.x=l-h.x*this.scale,this.offset.y=c-h.y*this.scale,this.clampViewportOffset(),this.render()}resize(){this.fitImageToCanvas(),this.render()}toImageCoords(e,i){return{x:(e-this.offset.x)/this.scale,y:(i-this.offset.y)/this.scale}}toScreenCoords(e,i){return{x:e*this.scale+this.offset.x,y:i*this.scale+this.offset.y}}fitImageToCanvas(){const e=this.canvas.parentElement;if(e){if(this.canvas.width=e.clientWidth,this.canvas.height=e.clientHeight,this.img.width===0)return;const i=this.canvas.width/this.img.width,n=this.canvas.height/this.img.height;this.scale=Math.min(i,n),this.offset.x=(this.canvas.width-this.img.width*this.scale)/2,this.offset.y=(this.canvas.height-this.img.height*this.scale)/2,this.clampViewportOffset()}}clampViewportOffset(){if(this.img.width===0||this.img.height===0)return;const e=this.img.width*this.scale,i=this.img.height*this.scale;if(e<=this.canvas.width)this.offset.x=(this.canvas.width-e)/2;else{const n=this.canvas.width-e,l=0;this.offset.x=Math.min(l,Math.max(n,this.offset.x))}if(i<=this.canvas.height)this.offset.y=(this.canvas.height-i)/2;else{const n=this.canvas.height-i,l=0;this.offset.y=Math.min(l,Math.max(n,this.offset.y))}}bindEvents(){this.canvas.addEventListener("mousedown",this.handleMouseDown.bind(this)),this.canvas.addEventListener("mousemove",this.handleMouseMove.bind(this)),this.canvas.addEventListener("mouseup",this.handleMouseUp.bind(this)),this.canvas.addEventListener("mouseleave",this.handleMouseUp.bind(this)),window.addEventListener("keydown",this.handleKeyDown.bind(this))}handleKeyDown(e){this.interactionMode==="select"&&(e.key==="Delete"||e.key==="Backspace")&&this.activeAnnotation&&this.deleteAnnotation(this.activeAnnotation.id)}deleteAnnotation(e){const i=this.annotations.findIndex(n=>n.id===e);if(i>-1){const n=this.annotations[i];this.annotations.splice(i,1),this.activeAnnotation=null,this.emit("annotationChange",{action:"delete",changedItem:n,imageUrl:this.imageUrl}),this.render()}}handleMouseDown(e){const i=this.canvas.getBoundingClientRect(),n=e.clientX-i.left,l=e.clientY-i.top,c=this.toImageCoords(n,l);if(this.canvas.style.cursor==="grab"||this.canvas.style.cursor==="grabbing"){this.isPanning=!0,this.panStartPoint={x:n,y:l},this.canvas.style.cursor="grabbing";return}if(this.interactionMode==="select"&&this.activeAnnotation){const g=this.getHitHandle(n,l,this.activeAnnotation);if(g!==-100){this.isDragging=!0,this.dragStartPoint=c,this.selectedHandleIndex=g,this.dragStartAnnotation=JSON.parse(JSON.stringify(this.activeAnnotation));return}}const h=this.interactionMode==="select"?this.getHitCategory(n,l):null;if(h){this.activeAnnotation=h,this.isDragging=!1,this.selectedHandleIndex=-1,this.emit("annotationChange",{action:"select",changedItem:h,imageUrl:this.imageUrl}),this.render();return}const a=this.getHitAnnotation(c);if(this.interactionMode==="select"){if(a){if(!(this.visibleLabels.size>0&&!this.visibleLabels.has(a.label))){this.activeAnnotation=a,this.isDragging=!0,this.dragStartPoint=c,this.selectedHandleIndex=-1,this.dragStartAnnotation=JSON.parse(JSON.stringify(a)),this.emit("annotationChange",{action:"select",changedItem:a,imageUrl:this.imageUrl}),this.render();return}}else this.activeAnnotation=null,this.emit("annotationChange",{action:"select",changedItem:void 0,imageUrl:this.imageUrl}),this.render();return}if(this.interactionMode==="draw"){if(this.isDrawing&&this.currentTool==="polygon"&&this.activeAnnotation){const g=this.activeAnnotation.coordinates;if(g.points.length>2&&N(c,g.points[0])<20/this.scale){this.finishDrawing();return}this.startDrawing(c);return}if(this.currentTool){if(this.currentTool==="polygon"&&!this.isDrawing){this.startDrawing(c);return}this.startDrawing(c)}return}this.activeAnnotation=null,this.render()}handleMouseMove(e){const i=this.canvas.getBoundingClientRect(),n=e.clientX-i.left,l=e.clientY-i.top,c=this.toImageCoords(n,l);if(this.isPanning&&this.panStartPoint){const h=n-this.panStartPoint.x,a=l-this.panStartPoint.y;this.offset.x+=h,this.offset.y+=a,this.clampViewportOffset(),this.panStartPoint={x:n,y:l},this.render();return}if(this.lastMouseMovePoint=c,this.isDrawing){if(this.currentTool==="polygon"&&this.activeAnnotation){const h=this.activeAnnotation.coordinates;if(h.points.length>2){const a=h.points[0],g=N(c,a);this.isHoveringStartPoint=g<20/this.scale}else this.isHoveringStartPoint=!1}this.updateDrawing(c)}else this.isDragging&&this.activeAnnotation&&this.dragStartPoint?this.updateDragging(c):this.checkHover(n,l,c);this.render()}handleMouseUp(e){if(this.isPanning){this.isPanning=!1,this.panStartPoint=null,this.canvas.style.cursor="grab";return}if(this.isDrawing){if(this.currentTool==="polygon"){this.render();return}this.finishDrawing()}else this.isDragging&&this.activeAnnotation&&this.emit("annotationChange",{action:"update",changedItem:this.activeAnnotation,imageUrl:this.imageUrl});this.currentTool!=="polygon"&&(this.isDrawing=!1),this.isDragging=!1,this.dragStartPoint=null,this.selectedHandleIndex=-1,this.render()}hexToRgba(e,i){if(!e.startsWith("#"))return e;const n=parseInt(e.slice(1,3),16),l=parseInt(e.slice(3,5),16),c=parseInt(e.slice(5,7),16);return`rgba(${n}, ${l}, ${c}, ${i})`}startDrawing(e){if(!this.currentTool)return;const i=Date.now().toString();if(this.hexToRgba(this.currentLabelColor,.2),this.currentLabelColor,this.currentTool==="rectangle")this.isDrawing=!0,this.dragStartPoint=e,this.activeAnnotation={id:i,type:"rectangle",label:"",coordinates:{x1:e.x,y1:e.y,x2:e.x,y2:e.y},style:{strokeColor:this.currentLabelColor}};else if(this.currentTool==="point"){const n={id:i,type:"point",label:"",coordinates:{points:[e]},style:{strokeColor:this.currentLabelColor}};this.annotations.push(n),this.emit("annotationChange",{action:"add",changedItem:n,imageUrl:this.imageUrl}),this.activeAnnotation=n}else if(this.currentTool==="polygon")this.activeAnnotation&&this.activeAnnotation.type==="polygon"&&this.isDrawing?this.activeAnnotation.coordinates.points.push(e):(this.isDrawing=!0,this.activeAnnotation={id:i,type:"polygon",label:"",coordinates:{points:[e]},style:{strokeColor:this.currentLabelColor}});else if(this.currentTool==="category"){const n={id:i,type:"category",label:"",coordinates:null,style:{strokeColor:this.currentLabelColor}};this.annotations.push(n),this.emit("annotationChange",{action:"add",changedItem:n,imageUrl:this.imageUrl}),this.activeAnnotation=n}else this.currentTool==="rotatedRect"&&(this.isDrawing=!0,this.dragStartPoint=e,this.activeAnnotation={id:i,type:"rotatedRect",label:"",coordinates:{x:e.x,y:e.y,width:0,height:0,angle:0},style:{strokeColor:this.currentLabelColor}})}updateDrawing(e){if(this.activeAnnotation)if(this.activeAnnotation.type==="rectangle"&&this.dragStartPoint){const i=this.activeAnnotation.coordinates;i.x2=e.x,i.y2=e.y}else if(this.activeAnnotation.type==="rotatedRect"&&this.dragStartPoint){const i=this.activeAnnotation.coordinates,n=Math.abs(e.x-this.dragStartPoint.x),l=Math.abs(e.y-this.dragStartPoint.y);i.width=n*2,i.height=l*2}else this.activeAnnotation.type}finishDrawing(){if(this.activeAnnotation){if(this.activeAnnotation.type==="rectangle"){const e=this.activeAnnotation.coordinates;if(Math.abs(e.x1-e.x2)<2||Math.abs(e.y1-e.y2)<2){this.activeAnnotation=null,this.isDrawing=!1;return}const i=Math.min(e.x1,e.x2),n=Math.max(e.x1,e.x2),l=Math.min(e.y1,e.y2),c=Math.max(e.y1,e.y2);e.x1=i,e.x2=n,e.y1=l,e.y2=c,this.annotations.push(this.activeAnnotation),this.emit("annotationChange",{action:"add",changedItem:this.activeAnnotation,imageUrl:this.imageUrl})}else if(this.activeAnnotation.type==="polygon"){if(this.activeAnnotation.coordinates.points.length<3){this.activeAnnotation=null,this.isDrawing=!1;return}this.annotations.push(this.activeAnnotation),this.emit("annotationChange",{action:"add",changedItem:this.activeAnnotation,imageUrl:this.imageUrl})}else if(this.activeAnnotation.type==="rotatedRect"){const e=this.activeAnnotation.coordinates;if(e.width<2||e.height<2){this.activeAnnotation=null,this.isDrawing=!1;return}this.annotations.push(this.activeAnnotation),this.emit("annotationChange",{action:"add",changedItem:this.activeAnnotation,imageUrl:this.imageUrl})}this.activeAnnotation.type}this.isDrawing=!1}updateDragging(e){if(!this.activeAnnotation||!this.dragStartPoint||!this.dragStartAnnotation)return;const i=e.x-this.dragStartPoint.x,n=e.y-this.dragStartPoint.y;this.selectedHandleIndex===-1?this.moveAnnotation(this.activeAnnotation,this.dragStartAnnotation,i,n):this.resizeAnnotation(this.activeAnnotation,this.dragStartAnnotation,this.selectedHandleIndex,e)}moveAnnotation(e,i,n,l){if(e.type==="rectangle"){const c=i.coordinates,h=e.coordinates;h.x1=c.x1+n,h.x2=c.x2+n,h.y1=c.y1+l,h.y2=c.y2+l}else if(e.type==="point"){const c=i.coordinates,h=e.coordinates;h.points=c.points.map(a=>({x:a.x+n,y:a.y+l}))}else if(e.type==="rotatedRect"){const c=i.coordinates,h=e.coordinates;h.x=c.x+n,h.y=c.y+l}else if(e.type==="polygon"){const c=i.coordinates,h=e.coordinates;h.points=c.points.map(a=>({x:a.x+n,y:a.y+l}))}}resizeAnnotation(e,i,n,l){if(e.type==="rectangle"){const c=e.coordinates;n===0&&(c.x1=l.x,c.y1=l.y),n===1&&(c.x2=l.x,c.y1=l.y),n===2&&(c.x2=l.x,c.y2=l.y),n===3&&(c.x1=l.x,c.y2=l.y)}else if(e.type==="polygon"){const c=e.coordinates;n>=0&&n<c.points.length&&(c.points[n]=l)}else if(e.type==="point"){const c=e.coordinates;n>=0&&n<c.points.length&&(c.points[n]=l)}else if(e.type==="rotatedRect"){const c=e.coordinates;if(n===-2){const h=c.x,a=c.y,g=l.x-h,u=l.y-a;let x=Math.atan2(u,g)*180/Math.PI;x+=90,c.angle=x}else{const h=c.angle*Math.PI/180,a=Math.cos(-h),g=Math.sin(-h),u=l.x-c.x,x=l.y-c.y,f=u*a-x*g,k=u*g+x*a;(n===0||n===3)&&(c.width/2,c.width=Math.abs(f)*2),(n===1||n===2)&&(c.width=Math.abs(f)*2),(n===0||n===1)&&(c.height=Math.abs(k)*2),(n===2||n===3)&&(c.height=Math.abs(k)*2)}}}getHitAnnotation(e){for(let i=this.annotations.length-1;i>=0;i--){const n=this.annotations[i];if(this.isPointInAnnotation(e,n))return n}return null}isPointInAnnotation(e,i){if(i.type==="rectangle"){const n=i.coordinates;return e.x>=n.x1&&e.x<=n.x2&&e.y>=n.y1&&e.y<=n.y2}else if(i.type==="polygon"){const n=i.coordinates;return st(e,n.points)}else if(i.type==="rotatedRect"){const n=i.coordinates,l=q(e,{x:n.x,y:n.y},-n.angle),c=n.width/2,h=n.height/2;return l.x>=n.x-c&&l.x<=n.x+c&&l.y>=n.y-h&&l.y<=n.y+h}else if(i.type==="point")return i.coordinates.points.some(l=>N(e,l)<10/this.scale);return!1}getHitHandle(e,i,n){const l=this.getAnnotationHandles(n),c=6;for(let h=0;h<l.length;h++){const a=l[h],g=this.toScreenCoords(a.x,a.y);if(Math.abs(e-g.x)<c&&Math.abs(i-g.y)<c)return n.type==="rotatedRect"&&h===4?-2:h}return-100}getAnnotationHandles(e){if(e.type==="rectangle"){const i=e.coordinates;return[{x:i.x1,y:i.y1},{x:i.x2,y:i.y1},{x:i.x2,y:i.y2},{x:i.x1,y:i.y2}]}else{if(e.type==="polygon")return e.coordinates.points;if(e.type==="point")return e.coordinates.points;if(e.type==="rotatedRect"){const i=e.coordinates,n={x:i.x,y:i.y},l=i.width/2,c=i.height/2,h={x:i.x-l,y:i.y-c},a={x:i.x+l,y:i.y-c},g={x:i.x+l,y:i.y+c},u={x:i.x-l,y:i.y+c},x={x:i.x,y:i.y-c-20/this.scale};return[h,a,g,u,x].map(f=>q(f,n,i.angle))}}return[]}checkHover(e,i,n){const l=this.getHitCategory(e,i);if(l){this.canvas.style.cursor="pointer",this.hoverAnnotation=l;return}if(this.activeAnnotation&&this.getHitHandle(e,i,this.activeAnnotation)!==-100){this.canvas.style.cursor="pointer";return}const c=this.getHitAnnotation(n);c?(this.canvas.style.cursor="move",this.hoverAnnotation=c):(this.canvas.style.cursor="default",this.hoverAnnotation=null)}render(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.img.complete&&this.img.width>0&&this.ctx.drawImage(this.img,this.offset.x,this.offset.y,this.img.width*this.scale,this.img.height*this.scale),this.annotations.forEach(e=>{e!==this.activeAnnotation&&this.drawItem(e,!1)}),this.activeAnnotation&&this.drawItem(this.activeAnnotation,!0),this.renderCategories()}renderCategories(){const e=this.annotations.filter(g=>g.type==="category");if(e.length===0)return;this.ctx.save(),this.ctx.font="14px sans-serif",this.ctx.textBaseline="top";let i=10;const n=10,l=8,c=4,h=24,a=8;e.forEach(g=>{const u=g.label||"Unlabeled",x=this.ctx.measureText(u).width+l*2,f=this.activeAnnotation===g,k=this.hoverAnnotation===g;this.ctx.fillStyle=f?"#E3F2FD":k?"#F5F5F5":"rgba(255, 255, 255, 0.9)",this.ctx.strokeStyle=f?"#2196F3":"#666",this.ctx.lineWidth=f?2:1,this.ctx.beginPath(),this.ctx.rect(i,n,x,h),this.ctx.fill(),this.ctx.stroke(),this.ctx.fillStyle=f?"#1976D2":"#333",this.ctx.fillText(u,i+l,n+c),i+=x+a}),this.ctx.restore()}getHitCategory(e,i){const n=this.annotations.filter(x=>x.type==="category");if(n.length===0)return null;this.ctx.save(),this.ctx.font="14px sans-serif";let l=10;const c=10,h=8,a=24,g=8;let u=null;for(const x of n){const f=x.label||"Unlabeled",k=this.ctx.measureText(f).width+h*2;if(e>=l&&e<=l+k&&i>=c&&i<=c+a){u=x;break}l+=k+g}return this.ctx.restore(),u}drawItem(e,i){var c;if(this.visibleLabels.size>0&&!this.visibleLabels.has(e.label)&&!i)return;this.ctx.save();const n=((c=e.style)==null?void 0:c.strokeColor)||"#FF4081",l=i?"#00E5FF":n;if(this.ctx.strokeStyle=l,this.ctx.lineWidth=2,i?this.ctx.fillStyle="rgba(0, 229, 255, 0.2)":this.ctx.fillStyle=this.hexToRgba(n,.2),e.type==="rectangle"){const h=e.coordinates,a=this.toScreenCoords(h.x1,h.y1),g=this.toScreenCoords(h.x2,h.y2),u=Math.min(a.x,g.x),x=Math.min(a.y,g.y),f=Math.abs(a.x-g.x),k=Math.abs(a.y-g.y);this.ctx.strokeRect(u,x,f,k),this.ctx.fillStyle=i?"rgba(0, 229, 255, 0.2)":"rgba(255, 64, 129, 0.2)",this.ctx.fillRect(u,x,f,k),i&&this.drawHandles(this.getAnnotationHandles(e))}else if(e.type==="polygon"){const h=e.coordinates;if(h.points.length===0){this.ctx.restore();return}this.ctx.beginPath();const a=this.toScreenCoords(h.points[0].x,h.points[0].y);this.ctx.moveTo(a.x,a.y);for(let g=1;g<h.points.length;g++){const u=this.toScreenCoords(h.points[g].x,h.points[g].y);this.ctx.lineTo(u.x,u.y)}if(!this.isDrawing||e!==this.activeAnnotation)this.ctx.closePath();else if(this.lastMouseMovePoint){let g=this.lastMouseMovePoint;if(this.isHoveringStartPoint&&h.points.length>0){g=h.points[0];const x=this.toScreenCoords(h.points[0].x,h.points[0].y);this.ctx.save(),this.ctx.beginPath(),this.ctx.arc(x.x,x.y,10,0,Math.PI*2),this.ctx.fillStyle="rgba(255, 215, 0, 0.6)",this.ctx.strokeStyle="#FFFFFF",this.ctx.lineWidth=2,this.ctx.fill(),this.ctx.stroke(),this.ctx.restore()}const u=this.toScreenCoords(g.x,g.y);this.ctx.lineTo(u.x,u.y)}this.ctx.stroke(),this.ctx.fillStyle=i?"rgba(0, 229, 255, 0.2)":"rgba(255, 64, 129, 0.2)",this.ctx.fill(),i&&this.drawHandles(this.getAnnotationHandles(e))}else if(e.type==="rotatedRect"){const h=e.coordinates;this.ctx.translate(this.toScreenCoords(h.x,h.y).x,this.toScreenCoords(h.x,h.y).y),this.ctx.rotate(h.angle*Math.PI/180);const a=h.width*this.scale,g=h.height*this.scale;this.ctx.strokeRect(-a/2,-g/2,a,g),this.ctx.fillStyle=i?"rgba(0, 229, 255, 0.2)":"rgba(255, 64, 129, 0.2)",this.ctx.fillRect(-a/2,-g/2,a,g),this.ctx.rotate(-h.angle*Math.PI/180),this.ctx.translate(-this.toScreenCoords(h.x,h.y).x,-this.toScreenCoords(h.x,h.y).y),i&&this.drawHandles(this.getAnnotationHandles(e))}else e.type==="point"&&e.coordinates.points.forEach(a=>{const g=this.toScreenCoords(a.x,a.y);this.ctx.beginPath(),this.ctx.arc(g.x,g.y,5,0,Math.PI*2),this.ctx.fillStyle=i?"#00E5FF":n,this.ctx.fill(),this.ctx.stroke()});this.ctx.restore()}drawHandles(e){this.ctx.fillStyle="#FFFFFF",this.ctx.strokeStyle="#000000",this.ctx.lineWidth=1,e.forEach(i=>{const n=this.toScreenCoords(i.x,i.y);this.ctx.fillRect(n.x-4,n.y-4,8,8),this.ctx.strokeRect(n.x-4,n.y-4,8,8)})}}const at=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
1
+ (function(B,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],t):(B=typeof globalThis<"u"?globalThis:B||self,t(B.VueImageAnnotator={},B.Vue))})(this,(function(B,t){"use strict";var Qe=Object.defineProperty;var tn=(B,t,z)=>t in B?Qe(B,t,{enumerable:!0,configurable:!0,writable:!0,value:z}):B[t]=z;var A=(B,t,z)=>tn(B,typeof t!="symbol"?t+"":t,z);const z=(y,e)=>Math.sqrt(Math.pow(y.x-e.x,2)+Math.pow(y.y-e.y,2)),it=(y,e)=>{let i=!1;for(let n=0,a=e.length-1;n<e.length;a=n++){const h=e[n].x,c=e[n].y,l=e[a].x,g=e[a].y;c>y.y!=g>y.y&&y.x<(l-h)*(y.y-c)/(g-c)+h&&(i=!i)}return i},q=(y,e,i)=>{const n=i*(Math.PI/180),a=Math.cos(n),h=Math.sin(n),c=y.x-e.x,l=y.y-e.y;return{x:e.x+(c*a-l*h),y:e.y+(c*h+l*a)}};class at{constructor(e){A(this,"canvas");A(this,"ctx");A(this,"img");A(this,"annotations",[]);A(this,"currentTool",null);A(this,"interactionMode","none");A(this,"activeAnnotation",null);A(this,"hoverAnnotation",null);A(this,"isDrawing",!1);A(this,"isDragging",!1);A(this,"isPanning",!1);A(this,"panStartPoint",null);A(this,"dragStartPoint",null);A(this,"dragStartAnnotation",null);A(this,"lastMouseMovePoint",null);A(this,"isHoveringStartPoint",!1);A(this,"currentLabelColor","#FF4081");A(this,"visibleLabels",new Set);A(this,"selectedHandleIndex",-1);A(this,"hoverHandleIndex",-1);A(this,"scale",1);A(this,"offset",{x:0,y:0});A(this,"listeners",{});A(this,"imageUrl","");this.canvas=e;const i=e.getContext("2d");if(!i)throw new Error("Could not get 2d context");this.ctx=i,this.img=new Image,this.img.crossOrigin="Anonymous",this.img.onload=()=>{this.fitImageToCanvas(),this.render()},this.bindEvents()}on(e,i){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(i)}emit(e,i){this.listeners[e]&&this.listeners[e].forEach(n=>n(i))}loadImage(e){this.imageUrl=e,this.img.src=e,this.activeAnnotation=null,this.isDrawing=!1}setAnnotations(e){this.annotations=JSON.parse(JSON.stringify(e)),this.render()}getAnnotations(){return this.annotations}setTool(e){e==="pan"?(this.interactionMode="pan",this.currentTool=null,this.isPanning=!1,this.canvas.style.cursor="grab"):e==="select"?(this.interactionMode="select",this.currentTool=null,this.canvas.style.cursor="default"):e?(this.interactionMode="draw",this.currentTool=e,this.canvas.style.cursor="crosshair"):(this.interactionMode="none",this.currentTool=null,this.canvas.style.cursor="default"),this.activeAnnotation=null,this.isDrawing=!1,this.render()}setLabelStyle(e){this.currentLabelColor=e}setVisibleLabels(e){this.visibleLabels=new Set(e),this.render()}zoom(e){const n=e>0?this.scale*1.1:this.scale/1.1;if(n<.1||n>10)return;const a=this.canvas.width/2,h=this.canvas.height/2,c=this.toImageCoords(a,h);this.scale=n,this.offset.x=a-c.x*this.scale,this.offset.y=h-c.y*this.scale,this.clampViewportOffset(),this.render()}resize(){this.fitImageToCanvas(),this.render()}toImageCoords(e,i){return{x:(e-this.offset.x)/this.scale,y:(i-this.offset.y)/this.scale}}toScreenCoords(e,i){return{x:e*this.scale+this.offset.x,y:i*this.scale+this.offset.y}}fitImageToCanvas(){const e=this.canvas.parentElement;if(e){if(this.canvas.width=e.clientWidth,this.canvas.height=e.clientHeight,this.img.width===0)return;const i=this.canvas.width/this.img.width,n=this.canvas.height/this.img.height;this.scale=Math.min(i,n),this.offset.x=(this.canvas.width-this.img.width*this.scale)/2,this.offset.y=(this.canvas.height-this.img.height*this.scale)/2,this.clampViewportOffset()}}clampViewportOffset(){if(this.img.width===0||this.img.height===0)return;const e=this.img.width*this.scale,i=this.img.height*this.scale;if(e<=this.canvas.width)this.offset.x=(this.canvas.width-e)/2;else{const n=this.canvas.width-e,a=0;this.offset.x=Math.min(a,Math.max(n,this.offset.x))}if(i<=this.canvas.height)this.offset.y=(this.canvas.height-i)/2;else{const n=this.canvas.height-i,a=0;this.offset.y=Math.min(a,Math.max(n,this.offset.y))}}bindEvents(){this.canvas.addEventListener("mousedown",this.handleMouseDown.bind(this)),this.canvas.addEventListener("mousemove",this.handleMouseMove.bind(this)),this.canvas.addEventListener("mouseup",this.handleMouseUp.bind(this)),this.canvas.addEventListener("mouseleave",this.handleMouseUp.bind(this)),window.addEventListener("keydown",this.handleKeyDown.bind(this))}handleKeyDown(e){this.interactionMode==="select"&&(e.key==="Delete"||e.key==="Backspace")&&this.activeAnnotation&&this.deleteAnnotation(this.activeAnnotation.id)}deleteAnnotation(e){const i=this.annotations.findIndex(n=>n.id===e);if(i>-1){const n=this.annotations[i];this.annotations.splice(i,1),this.activeAnnotation=null,this.emit("annotationChange",{action:"delete",changedItem:n,imageUrl:this.imageUrl}),this.render()}}handleMouseDown(e){const i=this.canvas.getBoundingClientRect(),n=e.clientX-i.left,a=e.clientY-i.top,h=this.toImageCoords(n,a);if(this.canvas.style.cursor==="grab"||this.canvas.style.cursor==="grabbing"){this.isPanning=!0,this.panStartPoint={x:n,y:a},this.canvas.style.cursor="grabbing";return}if(this.interactionMode==="select"&&this.activeAnnotation){const g=this.getHitHandle(n,a,this.activeAnnotation);if(g!==-100){this.isDragging=!0,this.dragStartPoint=h,this.selectedHandleIndex=g,this.dragStartAnnotation=JSON.parse(JSON.stringify(this.activeAnnotation));return}}const c=this.interactionMode==="select"?this.getHitCategory(n,a):null;if(c){this.activeAnnotation=c,this.isDragging=!1,this.selectedHandleIndex=-1,this.emit("annotationChange",{action:"select",changedItem:c,imageUrl:this.imageUrl}),this.render();return}const l=this.getHitAnnotation(h);if(this.interactionMode==="select"){if(l){if(!(this.visibleLabels.size>0&&!this.visibleLabels.has(l.label))){this.activeAnnotation=l,this.isDragging=!0,this.dragStartPoint=h,this.selectedHandleIndex=-1,this.dragStartAnnotation=JSON.parse(JSON.stringify(l)),this.emit("annotationChange",{action:"select",changedItem:l,imageUrl:this.imageUrl}),this.render();return}}else this.activeAnnotation=null,this.emit("annotationChange",{action:"select",changedItem:void 0,imageUrl:this.imageUrl}),this.render();return}if(this.interactionMode==="draw"){if(this.isDrawing&&this.currentTool==="polygon"&&this.activeAnnotation){const g=this.activeAnnotation.coordinates;if(g.points.length>2&&z(h,g.points[0])<20/this.scale){this.finishDrawing();return}this.startDrawing(h);return}if(this.currentTool){if(this.currentTool==="polygon"&&!this.isDrawing){this.startDrawing(h);return}this.startDrawing(h)}return}this.activeAnnotation=null,this.render()}handleMouseMove(e){const i=this.canvas.getBoundingClientRect(),n=e.clientX-i.left,a=e.clientY-i.top,h=this.toImageCoords(n,a);if(this.isPanning&&this.panStartPoint){const c=n-this.panStartPoint.x,l=a-this.panStartPoint.y;this.offset.x+=c,this.offset.y+=l,this.clampViewportOffset(),this.panStartPoint={x:n,y:a},this.render();return}if(this.lastMouseMovePoint=h,this.isDrawing){if(this.currentTool==="polygon"&&this.activeAnnotation){const c=this.activeAnnotation.coordinates;if(c.points.length>2){const l=c.points[0],g=z(h,l);this.isHoveringStartPoint=g<20/this.scale}else this.isHoveringStartPoint=!1}this.updateDrawing(h)}else this.isDragging&&this.activeAnnotation&&this.dragStartPoint?this.updateDragging(h):this.checkHover(n,a,h);this.render()}handleMouseUp(e){if(this.isPanning){this.isPanning=!1,this.panStartPoint=null,this.canvas.style.cursor="grab";return}if(this.isDrawing){if(this.currentTool==="polygon"){this.render();return}this.finishDrawing()}else this.isDragging&&this.activeAnnotation&&this.emit("annotationChange",{action:"update",changedItem:this.activeAnnotation,imageUrl:this.imageUrl});this.currentTool!=="polygon"&&(this.isDrawing=!1),this.isDragging=!1,this.dragStartPoint=null,this.selectedHandleIndex=-1,this.render()}hexToRgba(e,i){if(!e.startsWith("#"))return e;const n=parseInt(e.slice(1,3),16),a=parseInt(e.slice(3,5),16),h=parseInt(e.slice(5,7),16);return`rgba(${n}, ${a}, ${h}, ${i})`}startDrawing(e){if(!this.currentTool)return;const i=Date.now().toString();if(this.hexToRgba(this.currentLabelColor,.2),this.currentLabelColor,this.currentTool==="rectangle")this.isDrawing=!0,this.dragStartPoint=e,this.activeAnnotation={id:i,type:"rectangle",label:"",coordinates:{x1:e.x,y1:e.y,x2:e.x,y2:e.y},style:{strokeColor:this.currentLabelColor}};else if(this.currentTool==="point"){const n={id:i,type:"point",label:"",coordinates:{points:[e]},style:{strokeColor:this.currentLabelColor}};this.annotations.push(n),this.emit("annotationChange",{action:"add",changedItem:n,imageUrl:this.imageUrl}),this.activeAnnotation=n}else if(this.currentTool==="polygon")this.activeAnnotation&&this.activeAnnotation.type==="polygon"&&this.isDrawing?this.activeAnnotation.coordinates.points.push(e):(this.isDrawing=!0,this.activeAnnotation={id:i,type:"polygon",label:"",coordinates:{points:[e]},style:{strokeColor:this.currentLabelColor}});else if(this.currentTool==="category"){const n={id:i,type:"category",label:"",coordinates:null,style:{strokeColor:this.currentLabelColor}};this.annotations.push(n),this.emit("annotationChange",{action:"add",changedItem:n,imageUrl:this.imageUrl}),this.activeAnnotation=n}else this.currentTool==="rotatedRect"&&(this.isDrawing=!0,this.dragStartPoint=e,this.activeAnnotation={id:i,type:"rotatedRect",label:"",coordinates:{x:e.x,y:e.y,width:0,height:0,angle:0},style:{strokeColor:this.currentLabelColor}})}updateDrawing(e){if(this.activeAnnotation)if(this.activeAnnotation.type==="rectangle"&&this.dragStartPoint){const i=this.activeAnnotation.coordinates;i.x2=e.x,i.y2=e.y}else if(this.activeAnnotation.type==="rotatedRect"&&this.dragStartPoint){const i=this.activeAnnotation.coordinates,n=Math.abs(e.x-this.dragStartPoint.x),a=Math.abs(e.y-this.dragStartPoint.y);i.width=n*2,i.height=a*2}else this.activeAnnotation.type}finishDrawing(){if(this.activeAnnotation){if(this.activeAnnotation.type==="rectangle"){const e=this.activeAnnotation.coordinates;if(Math.abs(e.x1-e.x2)<2||Math.abs(e.y1-e.y2)<2){this.activeAnnotation=null,this.isDrawing=!1;return}const i=Math.min(e.x1,e.x2),n=Math.max(e.x1,e.x2),a=Math.min(e.y1,e.y2),h=Math.max(e.y1,e.y2);e.x1=i,e.x2=n,e.y1=a,e.y2=h,this.annotations.push(this.activeAnnotation),this.emit("annotationChange",{action:"add",changedItem:this.activeAnnotation,imageUrl:this.imageUrl})}else if(this.activeAnnotation.type==="polygon"){if(this.activeAnnotation.coordinates.points.length<3){this.activeAnnotation=null,this.isDrawing=!1;return}this.annotations.push(this.activeAnnotation),this.emit("annotationChange",{action:"add",changedItem:this.activeAnnotation,imageUrl:this.imageUrl})}else if(this.activeAnnotation.type==="rotatedRect"){const e=this.activeAnnotation.coordinates;if(e.width<2||e.height<2){this.activeAnnotation=null,this.isDrawing=!1;return}this.annotations.push(this.activeAnnotation),this.emit("annotationChange",{action:"add",changedItem:this.activeAnnotation,imageUrl:this.imageUrl})}this.activeAnnotation.type}this.isDrawing=!1}updateDragging(e){if(!this.activeAnnotation||!this.dragStartPoint||!this.dragStartAnnotation)return;const i=e.x-this.dragStartPoint.x,n=e.y-this.dragStartPoint.y;this.selectedHandleIndex===-1?this.moveAnnotation(this.activeAnnotation,this.dragStartAnnotation,i,n):this.resizeAnnotation(this.activeAnnotation,this.dragStartAnnotation,this.selectedHandleIndex,e)}moveAnnotation(e,i,n,a){if(e.type==="rectangle"){const h=i.coordinates,c=e.coordinates;c.x1=h.x1+n,c.x2=h.x2+n,c.y1=h.y1+a,c.y2=h.y2+a}else if(e.type==="point"){const h=i.coordinates,c=e.coordinates;c.points=h.points.map(l=>({x:l.x+n,y:l.y+a}))}else if(e.type==="rotatedRect"){const h=i.coordinates,c=e.coordinates;c.x=h.x+n,c.y=h.y+a}else if(e.type==="polygon"){const h=i.coordinates,c=e.coordinates;c.points=h.points.map(l=>({x:l.x+n,y:l.y+a}))}}resizeAnnotation(e,i,n,a){if(e.type==="rectangle"){const h=e.coordinates;n===0&&(h.x1=a.x,h.y1=a.y),n===1&&(h.x2=a.x,h.y1=a.y),n===2&&(h.x2=a.x,h.y2=a.y),n===3&&(h.x1=a.x,h.y2=a.y)}else if(e.type==="polygon"){const h=e.coordinates;n>=0&&n<h.points.length&&(h.points[n]=a)}else if(e.type==="point"){const h=e.coordinates;n>=0&&n<h.points.length&&(h.points[n]=a)}else if(e.type==="rotatedRect"){const h=e.coordinates;if(n===-2){const c=h.x,l=h.y,g=a.x-c,m=a.y-l;let x=Math.atan2(m,g)*180/Math.PI;x+=90,h.angle=x}else{const c=h.angle*Math.PI/180,l=Math.cos(-c),g=Math.sin(-c),m=a.x-h.x,x=a.y-h.y,u=m*l-x*g,k=m*g+x*l;(n===0||n===3)&&(h.width/2,h.width=Math.abs(u)*2),(n===1||n===2)&&(h.width=Math.abs(u)*2),(n===0||n===1)&&(h.height=Math.abs(k)*2),(n===2||n===3)&&(h.height=Math.abs(k)*2)}}}getHitAnnotation(e){for(let i=this.annotations.length-1;i>=0;i--){const n=this.annotations[i];if(this.isPointInAnnotation(e,n))return n}return null}isPointInAnnotation(e,i){if(i.type==="rectangle"){const n=i.coordinates;return e.x>=n.x1&&e.x<=n.x2&&e.y>=n.y1&&e.y<=n.y2}else if(i.type==="polygon"){const n=i.coordinates;return it(e,n.points)}else if(i.type==="rotatedRect"){const n=i.coordinates,a=q(e,{x:n.x,y:n.y},-n.angle),h=n.width/2,c=n.height/2;return a.x>=n.x-h&&a.x<=n.x+h&&a.y>=n.y-c&&a.y<=n.y+c}else if(i.type==="point")return i.coordinates.points.some(a=>z(e,a)<10/this.scale);return!1}getHitHandle(e,i,n){const a=this.getAnnotationHandles(n),h=6;for(let c=0;c<a.length;c++){const l=a[c],g=this.toScreenCoords(l.x,l.y);if(Math.abs(e-g.x)<h&&Math.abs(i-g.y)<h)return n.type==="rotatedRect"&&c===4?-2:c}return-100}getAnnotationHandles(e){if(e.type==="rectangle"){const i=e.coordinates;return[{x:i.x1,y:i.y1},{x:i.x2,y:i.y1},{x:i.x2,y:i.y2},{x:i.x1,y:i.y2}]}else{if(e.type==="polygon")return e.coordinates.points;if(e.type==="point")return e.coordinates.points;if(e.type==="rotatedRect"){const i=e.coordinates,n={x:i.x,y:i.y},a=i.width/2,h=i.height/2,c={x:i.x-a,y:i.y-h},l={x:i.x+a,y:i.y-h},g={x:i.x+a,y:i.y+h},m={x:i.x-a,y:i.y+h},x={x:i.x,y:i.y-h-20/this.scale};return[c,l,g,m,x].map(u=>q(u,n,i.angle))}}return[]}checkHover(e,i,n){const a=this.getHitCategory(e,i);if(a){this.canvas.style.cursor="pointer",this.hoverAnnotation=a;return}if(this.activeAnnotation&&this.getHitHandle(e,i,this.activeAnnotation)!==-100){this.canvas.style.cursor="pointer";return}const h=this.getHitAnnotation(n);h?(this.canvas.style.cursor="move",this.hoverAnnotation=h):(this.canvas.style.cursor="default",this.hoverAnnotation=null)}render(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.img.complete&&this.img.width>0&&this.ctx.drawImage(this.img,this.offset.x,this.offset.y,this.img.width*this.scale,this.img.height*this.scale),this.annotations.forEach(e=>{e!==this.activeAnnotation&&this.drawItem(e,!1)}),this.activeAnnotation&&this.drawItem(this.activeAnnotation,!0),this.renderCategories()}renderCategories(){const e=this.annotations.filter(g=>g.type==="category");if(e.length===0)return;this.ctx.save(),this.ctx.font="14px sans-serif",this.ctx.textBaseline="top";let i=10;const n=10,a=8,h=4,c=24,l=8;e.forEach(g=>{const m=g.label||"Unlabeled",x=this.ctx.measureText(m).width+a*2,u=this.activeAnnotation===g,k=this.hoverAnnotation===g;this.ctx.fillStyle=u?"#E3F2FD":k?"#F5F5F5":"rgba(255, 255, 255, 0.9)",this.ctx.strokeStyle=u?"#2196F3":"#666",this.ctx.lineWidth=u?2:1,this.ctx.beginPath(),this.ctx.rect(i,n,x,c),this.ctx.fill(),this.ctx.stroke(),this.ctx.fillStyle=u?"#1976D2":"#333",this.ctx.fillText(m,i+a,n+h),i+=x+l}),this.ctx.restore()}getHitCategory(e,i){const n=this.annotations.filter(x=>x.type==="category");if(n.length===0)return null;this.ctx.save(),this.ctx.font="14px sans-serif";let a=10;const h=10,c=8,l=24,g=8;let m=null;for(const x of n){const u=x.label||"Unlabeled",k=this.ctx.measureText(u).width+c*2;if(e>=a&&e<=a+k&&i>=h&&i<=h+l){m=x;break}a+=k+g}return this.ctx.restore(),m}drawItem(e,i){var h;if(this.visibleLabels.size>0&&!this.visibleLabels.has(e.label)&&!i)return;this.ctx.save();const n=((h=e.style)==null?void 0:h.strokeColor)||"#FF4081",a=i?"#00E5FF":n;if(this.ctx.strokeStyle=a,this.ctx.lineWidth=2,i?this.ctx.fillStyle="rgba(0, 229, 255, 0.2)":this.ctx.fillStyle=this.hexToRgba(n,.2),e.type==="rectangle"){const c=e.coordinates,l=this.toScreenCoords(c.x1,c.y1),g=this.toScreenCoords(c.x2,c.y2),m=Math.min(l.x,g.x),x=Math.min(l.y,g.y),u=Math.abs(l.x-g.x),k=Math.abs(l.y-g.y);this.ctx.strokeRect(m,x,u,k),this.ctx.fillStyle=i?"rgba(0, 229, 255, 0.2)":"rgba(255, 64, 129, 0.2)",this.ctx.fillRect(m,x,u,k),i&&this.drawHandles(this.getAnnotationHandles(e))}else if(e.type==="polygon"){const c=e.coordinates;if(c.points.length===0){this.ctx.restore();return}this.ctx.beginPath();const l=this.toScreenCoords(c.points[0].x,c.points[0].y);this.ctx.moveTo(l.x,l.y);for(let g=1;g<c.points.length;g++){const m=this.toScreenCoords(c.points[g].x,c.points[g].y);this.ctx.lineTo(m.x,m.y)}if(!this.isDrawing||e!==this.activeAnnotation)this.ctx.closePath();else if(this.lastMouseMovePoint){let g=this.lastMouseMovePoint;if(this.isHoveringStartPoint&&c.points.length>0){g=c.points[0];const x=this.toScreenCoords(c.points[0].x,c.points[0].y);this.ctx.save(),this.ctx.beginPath(),this.ctx.arc(x.x,x.y,10,0,Math.PI*2),this.ctx.fillStyle="rgba(255, 215, 0, 0.6)",this.ctx.strokeStyle="#FFFFFF",this.ctx.lineWidth=2,this.ctx.fill(),this.ctx.stroke(),this.ctx.restore()}const m=this.toScreenCoords(g.x,g.y);this.ctx.lineTo(m.x,m.y)}this.ctx.stroke(),this.ctx.fillStyle=i?"rgba(0, 229, 255, 0.2)":"rgba(255, 64, 129, 0.2)",this.ctx.fill(),i&&this.drawHandles(this.getAnnotationHandles(e))}else if(e.type==="rotatedRect"){const c=e.coordinates;this.ctx.translate(this.toScreenCoords(c.x,c.y).x,this.toScreenCoords(c.x,c.y).y),this.ctx.rotate(c.angle*Math.PI/180);const l=c.width*this.scale,g=c.height*this.scale;this.ctx.strokeRect(-l/2,-g/2,l,g),this.ctx.fillStyle=i?"rgba(0, 229, 255, 0.2)":"rgba(255, 64, 129, 0.2)",this.ctx.fillRect(-l/2,-g/2,l,g),this.ctx.rotate(-c.angle*Math.PI/180),this.ctx.translate(-this.toScreenCoords(c.x,c.y).x,-this.toScreenCoords(c.x,c.y).y),i&&this.drawHandles(this.getAnnotationHandles(e))}else e.type==="point"&&e.coordinates.points.forEach(l=>{const g=this.toScreenCoords(l.x,l.y);this.ctx.beginPath(),this.ctx.arc(g.x,g.y,5,0,Math.PI*2),this.ctx.fillStyle=i?"#00E5FF":n,this.ctx.fill(),this.ctx.stroke()});this.ctx.restore()}drawHandles(e){this.ctx.fillStyle="#FFFFFF",this.ctx.strokeStyle="#000000",this.ctx.lineWidth=1,e.forEach(i=>{const n=this.toScreenCoords(i.x,i.y);this.ctx.fillRect(n.x-4,n.y-4,8,8),this.ctx.strokeRect(n.x-4,n.y-4,8,8)})}}const lt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
2
2
  <path d="M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768zm0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896z m0-320a64 64 0 1 0 0-128 64 64 0 0 0 0 128z m0 64a128 128 0 1 1 0-256 128 128 0 0 1 0 256z" fill="currentColor"/>\r
3
- </svg>`,lt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
4
- <path d="M609.408 149.376l-277.76 277.76a96 96 0 0 0 0 135.68l277.76 277.76a32 32 0 1 0 45.248-45.248L376.96 512l277.76-277.76a32 32 0 0 0-45.248-45.248z" fill="currentColor"/>\r
5
3
  </svg>`,rt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
6
- <path d="M704 192h160v160h-160z m-64-64v288h288V128H640zM160 672h160v160H160z m-64-64v288h288V608H96z m256-320h320v64H352z" fill="currentColor"/>\r
4
+ <path d="M609.408 149.376l-277.76 277.76a96 96 0 0 0 0 135.68l277.76 277.76a32 32 0 1 0 45.248-45.248L376.96 512l277.76-277.76a32 32 0 0 0-45.248-45.248z" fill="currentColor"/>\r
7
5
  </svg>`,ct=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
8
- <path d="M256 256h512v512H256z m-64-64v640h640V192H192z" fill="currentColor"/>\r
6
+ <path d="M704 192h160v160h-160z m-64-64v288h288V128H640zM160 672h160v160H160z m-64-64v288h288V608H96z m256-320h320v64H352z" fill="currentColor"/>\r
9
7
  </svg>`,ht=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
10
- <path d="M160 256h704a32 32 0 1 1 0 64h-64v608a32 32 0 0 1-32 32H256a32 32 0 0 1-32-32V320h-64a32 32 0 1 1 0-64zm128 64v576h448V320H288z m128 0v512a32 32 0 1 1-64 0V320a32 32 0 1 1 64 0zm256 0v512a32 32 0 1 1-64 0V320a32 32 0 1 1 64 0zM352 128h320a32 32 0 0 1 32 32v64H320v-64a32 32 0 0 1 32-32z" fill="currentColor"/>\r
8
+ <path d="M256 256h512v512H256z m-64-64v640h640V192H192z" fill="currentColor"/>\r
11
9
  </svg>`,dt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
12
- <path d="M512 666.56l-186.88-186.88a32 32 0 0 0-45.248 45.248l209.536 209.536a96 96 0 0 0 135.68 0l209.536-209.536a32 32 0 1 0-45.248-45.248L544 666.56V128a32 32 0 0 0-64 0v538.56zM192 832h640a32 32 0 1 1 0 64H192a32 32 0 1 1 0-64z" fill="currentColor"/>\r
10
+ <path d="M160 256h704a32 32 0 1 1 0 64h-64v608a32 32 0 0 1-32 32H256a32 32 0 0 1-32-32V320h-64a32 32 0 1 1 0-64zm128 64v576h448V320H288z m128 0v512a32 32 0 1 1-64 0V320a32 32 0 1 1 64 0zm256 0v512a32 32 0 1 1-64 0V320a32 32 0 1 1 64 0zM352 128h320a32 32 0 0 1 32 32v64H320v-64a32 32 0 0 1 32-32z" fill="currentColor"/>\r
13
11
  </svg>`,gt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
14
- <path d="M832 512a32 32 0 1 1 64 0v352a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V160a32 32 0 0 1 32-32h352a32 32 0 0 1 0 64H192v640h640V512z m-144-320l-480 480v160h160l480-480-160-160z m-114.56 480H256v-117.76L653.44 236.8l117.76 117.76L573.44 672z m208-208l-117.76-117.76 66.56-66.56a32 32 0 0 1 45.248 0l72.512 72.512a32 32 0 0 1 0 45.248l-66.56 66.56z" fill="currentColor"/>\r
12
+ <path d="M512 666.56l-186.88-186.88a32 32 0 0 0-45.248 45.248l209.536 209.536a96 96 0 0 0 135.68 0l209.536-209.536a32 32 0 1 0-45.248-45.248L544 666.56V128a32 32 0 0 0-64 0v538.56zM192 832h640a32 32 0 1 1 0 64H192a32 32 0 1 1 0-64z" fill="currentColor"/>\r
15
13
  </svg>`,mt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
16
- <path d="M940.48 876.16L148.16 83.84a32 32 0 1 0-45.12 45.12L236.8 262.4C163.52 337.28 107.52 429.12 82.56 528.96a32 32 0 0 0 0 20.48C144.384 727.68 314.88 840.96 512 840.96c103.04 0 199.36-30.72 283.52-83.84l99.84 99.84a32 32 0 1 0 45.12-45.12zM512 776.96c-176.64 0-333.44-98.56-402.56-248.96 25.6-56.32 63.36-107.52 110.08-151.04L364.8 522.24a128 128 0 0 0 147.2 147.2l123.52 123.52A445.44 445.44 0 0 1 512 776.96z m373.12-32.64l-64-64C857.6 627.84 879.616 572.16 879.616 512c0-176.64-156.8-328.96-367.616-328.96-58.24 0-113.6 11.52-164.48 32.64l-55.68-55.68C346.88 136.96 427.52 119.04 512 119.04c229.76 0 425.216 142.08 493.44 346.24a32 32 0 0 1 0 20.48 450.56 450.56 0 0 1-120.32 258.56z m-309.12-309.12l-128-128A128 128 0 0 1 576 435.2z" fill="currentColor"/>\r
14
+ <path d="M832 512a32 32 0 1 1 64 0v352a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V160a32 32 0 0 1 32-32h352a32 32 0 0 1 0 64H192v640h640V512z m-144-320l-480 480v160h160l480-480-160-160z m-114.56 480H256v-117.76L653.44 236.8l117.76 117.76L573.44 672z m208-208l-117.76-117.76 66.56-66.56a32 32 0 0 1 45.248 0l72.512 72.512a32 32 0 0 1 0 45.248l-66.56 66.56z" fill="currentColor"/>\r
17
15
  </svg>`,ft=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
18
- <path d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm0 832a384 384 0 1 0 0-768 384 384 0 0 0 0 768zm-48-384H320a32 32 0 0 1 0-64h144V304a32 32 0 1 1 64 0v144h144a32 32 0 1 1 0 64H528v144a32 32 0 1 1-64 0V512z" fill="currentColor"/>\r
16
+ <path d="M940.48 876.16L148.16 83.84a32 32 0 1 0-45.12 45.12L236.8 262.4C163.52 337.28 107.52 429.12 82.56 528.96a32 32 0 0 0 0 20.48C144.384 727.68 314.88 840.96 512 840.96c103.04 0 199.36-30.72 283.52-83.84l99.84 99.84a32 32 0 1 0 45.12-45.12zM512 776.96c-176.64 0-333.44-98.56-402.56-248.96 25.6-56.32 63.36-107.52 110.08-151.04L364.8 522.24a128 128 0 0 0 147.2 147.2l123.52 123.52A445.44 445.44 0 0 1 512 776.96z m373.12-32.64l-64-64C857.6 627.84 879.616 572.16 879.616 512c0-176.64-156.8-328.96-367.616-328.96-58.24 0-113.6 11.52-164.48 32.64l-55.68-55.68C346.88 136.96 427.52 119.04 512 119.04c229.76 0 425.216 142.08 493.44 346.24a32 32 0 0 1 0 20.48 450.56 450.56 0 0 1-120.32 258.56z m-309.12-309.12l-128-128A128 128 0 0 1 576 435.2z" fill="currentColor"/>\r
19
17
  </svg>`,ut=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
20
- <path d="M224 448a32 32 0 0 0 9.536 22.592l416 416a32 32 0 0 0 45.248 0l226.24-226.24a32 32 0 0 0 0-45.248l-416-416A32 32 0 0 0 482.432 192H256a64 64 0 0 0-64 64v192z m64-192h160l384 384-160 160-384-384V256z m64 128a64 64 0 1 0 0-128 64 64 0 0 0 0 128z" fill="currentColor"/>\r
18
+ <path d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm0 832a384 384 0 1 0 0-768 384 384 0 0 0 0 768zm-48-384H320a32 32 0 0 1 0-64h144V304a32 32 0 1 1 64 0v144h144a32 32 0 1 1 0 64H528v144a32 32 0 1 1-64 0V512z" fill="currentColor"/>\r
21
19
  </svg>`,pt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
22
- <path d="M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64zm0-704h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64zm0 352h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64z" fill="currentColor"/>\r
20
+ <path d="M224 448a32 32 0 0 0 9.536 22.592l416 416a32 32 0 0 0 45.248 0l226.24-226.24a32 32 0 0 0 0-45.248l-416-416A32 32 0 0 0 482.432 192H256a64 64 0 0 0-64 64v192z m64-192h160l384 384-160 160-384-384V256z m64 128a64 64 0 1 0 0-128 64 64 0 0 0 0 128z" fill="currentColor"/>\r
23
21
  </svg>`,yt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
24
- <path d="M784.512 230.272v-50.56a32 32 0 1 1 64 0v149.056a32 32 0 0 1-32 32H667.52a32 32 0 1 1 0-64h92.992A320 320 0 1 0 524.8 833.152a320 320 0 0 0 320-320h64a384 384 0 0 1-384 384 384 384 0 0 1-384-384 384 384 0 0 1 643.712-282.88z" fill="currentColor"/>\r
22
+ <path d="M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64zm0-704h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64zm0 352h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64z" fill="currentColor"/>\r
25
23
  </svg>`,vt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
26
- <path d="M340.864 149.376a32 32 0 0 0-45.248 45.248L573.44 512l-277.76 317.376a32 32 0 0 0 45.248 45.248l277.76-277.76a96 96 0 0 0 0-135.68L340.864 149.376z" fill="currentColor"/>\r
24
+ <path d="M784.512 230.272v-50.56a32 32 0 1 1 64 0v149.056a32 32 0 0 1-32 32H667.52a32 32 0 1 1 0-64h92.992A320 320 0 1 0 524.8 833.152a320 320 0 0 0 320-320h64a384 384 0 0 1-384 384 384 384 0 0 1-384-384 384 384 0 0 1 643.712-282.88z" fill="currentColor"/>\r
27
25
  </svg>`,xt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
28
- <path d="M512 192c229.76 0 425.216 142.08 493.44 346.24a32 32 0 0 1 0 20.48C937.216 762.88 741.76 904.96 512 904.96S86.784 762.88 18.56 558.72a32 32 0 0 1 0-20.48C86.784 334.08 282.24 192 512 192zm0 64c-197.12 0-367.616 120.32-428.16 296.32C144.384 727.68 314.88 840.96 512 840.96s367.616-113.28 428.16-288.64C879.616 376.32 709.12 256 512 256zm0 160a128 128 0 1 1 0 256 128 128 0 0 1 0-256zm0 64a64 64 0 1 0 0 128 64 64 0 0 0 0-128z" fill="currentColor"/>\r
26
+ <path d="M340.864 149.376a32 32 0 0 0-45.248 45.248L573.44 512l-277.76 317.376a32 32 0 0 0 45.248 45.248l277.76-277.76a96 96 0 0 0 0-135.68L340.864 149.376z" fill="currentColor"/>\r
29
27
  </svg>`,bt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
30
- <path d="M637.12 693.376l182.208 182.208a32 32 0 1 1-45.248 45.248L591.872 738.624a352 352 0 1 1 45.248-45.248z m-45.248-45.248A288 288 0 1 0 183.872 240.128a288 288 0 0 0 408 408zM416 448h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64h96v-96a32 32 0 0 1 64 0v96z" fill="currentColor"/>\r
28
+ <path d="M512 192c229.76 0 425.216 142.08 493.44 346.24a32 32 0 0 1 0 20.48C937.216 762.88 741.76 904.96 512 904.96S86.784 762.88 18.56 558.72a32 32 0 0 1 0-20.48C86.784 334.08 282.24 192 512 192zm0 64c-197.12 0-367.616 120.32-428.16 296.32C144.384 727.68 314.88 840.96 512 840.96s367.616-113.28 428.16-288.64C879.616 376.32 709.12 256 512 256zm0 160a128 128 0 1 1 0 256 128 128 0 0 1 0-256zm0 64a64 64 0 1 0 0 128 64 64 0 0 0 0-128z" fill="currentColor"/>\r
31
29
  </svg>`,wt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
30
+ <path d="M637.12 693.376l182.208 182.208a32 32 0 1 1-45.248 45.248L591.872 738.624a352 352 0 1 1 45.248-45.248z m-45.248-45.248A288 288 0 1 0 183.872 240.128a288 288 0 0 0 408 408zM416 448h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64h96v-96a32 32 0 0 1 64 0v96z" fill="currentColor"/>\r
31
+ </svg>`,kt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
32
32
  <path d="M637.12 693.376l182.208 182.208a32 32 0 1 1-45.248 45.248L591.872 738.624a352 352 0 1 1 45.248-45.248z m-45.248-45.248A288 288 0 1 0 183.872 240.128a288 288 0 0 0 408 408zM256 448h320a32 32 0 1 1 0 64H256a32 32 0 1 1 0-64z" fill="currentColor"/>\r
33
- </svg>`,kt=["innerHTML"],Ct=t.defineComponent({__name:"SvgIcon",props:{name:{},size:{}},setup(p){const e=p,i=t.ref(""),n=Object.assign({"../assets/svg/aim.svg":at,"../assets/svg/back.svg":lt,"../assets/svg/connection.svg":rt,"../assets/svg/crop.svg":ct,"../assets/svg/delete.svg":ht,"../assets/svg/download.svg":dt,"../assets/svg/edit.svg":gt,"../assets/svg/hide.svg":mt,"../assets/svg/pointer.svg":ft,"../assets/svg/price-tag.svg":ut,"../assets/svg/rank.svg":pt,"../assets/svg/refresh-right.svg":yt,"../assets/svg/right.svg":vt,"../assets/svg/view.svg":xt,"../assets/svg/zoom-in.svg":bt,"../assets/svg/zoom-out.svg":wt});return t.watchEffect(()=>{const l=`../assets/svg/${e.name}.svg`,c=n[l];c?i.value=c:(console.warn(`Icon ${e.name} not found at path ${l}`),i.value="")}),(l,c)=>(t.openBlock(),t.createElementBlock("i",{class:t.normalizeClass(["svg-icon",[p.size?`size-${p.size}`:""]]),innerHTML:i.value},null,10,kt))}}),H=(p,e)=>{const i=p.__vccOpts||p;for(const[n,l]of e)i[n]=l;return i},E=H(Ct,[["__scopeId","data-v-3928607b"]]),At={key:0,class:"image-list-sidebar"},_t={class:"image-list-title"},It={class:"image-list-scroll"},Bt=["onClick"],St={class:"image-list-stage"},Et=["src","alt"],Vt={key:0,class:"thumb-overlay-layer"},Nt={key:1,class:"thumb-overlay-svg",viewBox:"0 0 100 100",preserveAspectRatio:"none"},zt=["points"],Mt={class:"image-list-text"},Tt={key:1,class:"left-sidebar"},$t=["onClick","title"],Pt={class:"center-area"},Dt={key:0,class:"top-bar"},Lt={class:"label-selector"},Ht={class:"tags-row"},Rt=["onClick"],Ft={key:0,class:"no-labels"},Ut={key:1,class:"batch-nav"},Ot=["disabled"],Wt=["disabled"],jt={key:2,class:"right-sidebar"},Jt={class:"label-list"},Yt={class:"label-row"},Xt=["onUpdate:modelValue","onChange"],qt=["title"],Gt=["onClick"],Kt={class:"action-icon more-actions"},Zt=["onClick"],Qt={key:3,class:"modal-overlay"},te={class:"modal-content"},ee={class:"form-group"},ne={class:"form-group"},oe={class:"color-input-wrapper"},G=H(t.defineComponent({__name:"ImageAnnotator",props:{annotationTypes:{default:()=>["rectangle","polygon","point","rotatedRect"]},batchImages:{default:()=>[]},labels:{default:()=>[]},defaultActiveType:{},theme:{default:"light"},readOnly:{type:Boolean,default:!1},image:{},predictionCandidates:{},session:{},requestId:{},minZoom:{},maxZoom:{}},emits:["annotationChange","batchChange","labelChange","ready","error","tool:change","viewport:change","annotation:add","annotation:update","annotation:delete","annotation:select","prediction:loaded","prediction:apply","prediction:reject"],setup(p,{expose:e,emit:i}){const n=p,l=i,c=t.ref(null),h=t.ref(null),a=t.ref(null),g=t.ref(null),u=t.ref(0),x=t.ref(""),f=t.ref([]),k=t.ref(""),z=t.ref(!1),A=t.ref({name:"",color:"#FF0000"}),C=t.ref("none"),b=t.ref([]),V=t.ref({}),D=t.computed(()=>g.value==="select"&&!!x.value),T=o=>{if(!o||V.value[o])return;const s=new Image;s.onload=()=>{const r=s.naturalWidth||1,d=s.naturalHeight||1;V.value={...V.value,[o]:{width:r,height:d}}},s.src=o},U=()=>{n.batchImages.forEach(o=>{T(o.imageUrl)})},M=()=>{var r,d,m,w;const o=n.batchImages[u.value],s=(o==null?void 0:o.imageUrl)||((r=n.image)==null?void 0:r.url);return{eventId:`${Date.now()}-${Math.random().toString(36).slice(2,10)}`,timestamp:Date.now(),requestId:n.requestId,taskId:(d=n.session)==null?void 0:d.taskId,imageId:((m=n.image)==null?void 0:m.id)||s,operator:(w=n.session)==null?void 0:w.userId}},O=o=>{var d;const s=o==null?void 0:o.action;if(!s)return;const r={meta:M(),action:s,current:o==null?void 0:o.changedItem,source:(d=o==null?void 0:o.changedItem)!=null&&d.predictionId?"prediction":"manual"};s==="add"&&l("annotation:add",r),s==="update"&&l("annotation:update",r),s==="delete"&&l("annotation:delete",r),s==="select"&&l("annotation:select",r)},W=t.computed(()=>n.annotationTypes.filter(o=>o!=="category")),j=o=>({rectangle:"crop",polygon:"connection",point:"aim",rotatedRect:"refresh-right",category:"price-tag"})[o]||o,J=o=>({rectangle:"矩形框",polygon:"多边形",point:"关键点",rotatedRect:"旋转矩形",category:"分类标签"})[o]||o;t.onMounted(()=>{if(U(),c.value){a.value=new it(c.value),a.value.on("annotationChange",s=>{var r,d;if(s.action==="add"&&s.changedItem){const m=f.value.find(w=>w.id===k.value);m&&(s.changedItem.label=m.name,s.changedItem.labelId=m.id)}s.action==="select"?x.value=((r=s.changedItem)==null?void 0:r.id)||"":s.action==="delete"&&((d=s.changedItem)==null?void 0:d.id)===x.value&&(x.value=""),l("annotationChange",s),O(s)}),y(),$();const o=new ResizeObserver(()=>{var s;(s=a.value)==null||s.resize()});h.value&&o.observe(h.value),n.defaultActiveType&&v(n.defaultActiveType),l("ready",{meta:M()})}});const $=()=>{if(!a.value)return;const o=f.value.find(r=>r.id===k.value);o&&a.value.setLabelStyle(o.color);const s=f.value.filter(r=>r.visible).map(r=>r.name);a.value.setVisibleLabels(s)},y=()=>{var o;if(a.value)if(x.value="",requestAnimationFrame(()=>{var s;(s=a.value)==null||s.resize()}),n.batchImages.length>0){const s=n.batchImages[u.value];a.value.loadImage(s.imageUrl),s.annotations?a.value.setAnnotations(s.annotations):a.value.setAnnotations([])}else(o=n.image)!=null&&o.url&&a.value.loadImage(n.image.url)},v=o=>{var s,r;if(g.value=o,x.value="",o!=="pan"&&o!=="select"&&f.value.length===0){alert("请先创建标签!");return}o==="pan"||o==="select"?(s=a.value)==null||s.setTool(o):(r=a.value)==null||r.setTool(o),l("tool:change",{meta:M(),tool:o})},I=()=>{var o;(o=a.value)!=null&&o.activeAnnotation&&a.value.deleteAnnotation(a.value.activeAnnotation.id)},P=()=>{a.value&&l("viewport:change",{meta:M(),scale:a.value.scale,offset:{...a.value.offset}})},Z=()=>{var o;(o=a.value)==null||o.zoom(1),P()},Ie=()=>{var o;(o=a.value)==null||o.zoom(-1),P()},Be=()=>{A.value={name:"",color:"#2196F3"},z.value=!0},Q=()=>{z.value=!1},Se=()=>{if(!A.value.name.trim()){alert("请输入标签名称");return}const s={id:Date.now().toString(),name:A.value.name,color:A.value.color,visible:!0};f.value.push(s),l("labelChange",f.value),f.value.length===1&&L(s),Q()},L=o=>{var s;k.value=o.id,(s=a.value)==null||s.setLabelStyle(o.color)},Ee=(o,s)=>{if(!o.startsWith("#"))return o;let r=0,d=0,m=0;return o.length===4?(r=parseInt(o[1]+o[1],16),d=parseInt(o[2]+o[2],16),m=parseInt(o[3]+o[3],16)):o.length===7&&(r=parseInt(o.slice(1,3),16),d=parseInt(o.slice(3,5),16),m=parseInt(o.slice(5,7),16)),`rgba(${r}, ${d}, ${m}, ${s})`},Ve=o=>{var s;if(o.id===k.value&&((s=a.value)==null||s.setLabelStyle(o.color)),a.value){const r=a.value.getAnnotations();let d=!1;r.forEach(m=>{m.label===o.name&&(m.style||(m.style={}),m.style.strokeColor=o.color,m.style.fillColor=Ee(o.color,.2),d=!0)}),d&&a.value.render()}l("labelChange",f.value)},Ne=o=>{o.visible=!o.visible,$()},ze=o=>{const s=f.value.findIndex(r=>r.id===o);s>-1&&(f.value.splice(s,1),l("labelChange",f.value),k.value===o&&(k.value=f.value.length>0?f.value[0].id:"",k.value&&L(f.value[0])),$())};t.watch(()=>n.labels,o=>{const s=JSON.parse(JSON.stringify(o||[]));if(f.value=s,f.value.length>0)if(!k.value||!f.value.find(r=>r.id===k.value))L(f.value[0]);else{const r=f.value.find(d=>d.id===k.value);r&&L(r)}else k.value="";$()},{immediate:!0,deep:!0});const Me=()=>{u.value>0&&(Y(),u.value--,y(),X())},Te=()=>{u.value<n.batchImages.length-1&&(Y(),u.value++,y(),X())},Y=()=>{if(a.value){const o=a.value.getAnnotations();n.batchImages[u.value].annotations=o}},X=()=>{const o=n.batchImages[u.value];l("batchChange",{currentIndex:u.value,total:n.batchImages.length,currentImageUrl:o.imageUrl,currentAnnotations:o.annotations||[]})},tt=(o=[])=>{var m;if(!a.value)return;if(b.value=JSON.parse(JSON.stringify(o)),b.value.length===0){C.value="none";return}C.value="loaded";const r=(a.value.getAnnotations()||[]).filter(w=>!w.predictionId),d=b.value.map(w=>{const B=JSON.parse(JSON.stringify(w.annotation));return B.id=B.id||`pred-${w.id}`,B.predictionId=w.id,B.modelRunId=w.modelRunId||B.modelRunId,B.confidence=w.confidence??B.confidence,B.reviewStatus=B.reviewStatus||"draft",B});a.value.setAnnotations([...r,...d]),l("prediction:loaded",{meta:M(),modelRunId:(m=b.value[0])==null?void 0:m.modelRunId,candidates:b.value})},$e=(o,s)=>{var m;if(!a.value)return[];C.value="applying";const d=(a.value.getAnnotations()||[]).filter(w=>w.predictionId&&o.includes(w.predictionId));return d.forEach(w=>{w.reviewStatus="accepted"}),C.value="applied",l("prediction:apply",{meta:M(),modelRunId:(m=d[0])==null?void 0:m.modelRunId,candidateIds:o,threshold:s,acceptedAnnotations:d}),a.value.render(),d},Pe=(o,s)=>{var m;if(!a.value)return;const r=a.value.getAnnotations()||[],d=r.filter(w=>!(w.predictionId&&o.includes(w.predictionId)));a.value.setAnnotations(d),l("prediction:reject",{meta:M(),modelRunId:(m=r.find(w=>w.predictionId&&o.includes(w.predictionId)))==null?void 0:m.modelRunId,candidateIds:o,reason:s})},De=(o,s=[])=>{a.value&&(a.value.loadImage(o.url),a.value.setAnnotations(s))},Le=o=>{var s;(s=a.value)==null||s.setAnnotations(o)},et=()=>{var o;return((o=a.value)==null?void 0:o.getAnnotations())||[]},He=(o="json")=>{var r,d;const s=et();return{format:o,image:((r=n.batchImages[u.value])==null?void 0:r.imageUrl)||((d=n.image)==null?void 0:d.url)||"",annotations:s}},nt=o=>{o>=0&&o<n.batchImages.length&&(Y(),u.value=o,y(),X())},Re=o=>{var s;return o===u.value&&a.value?a.value.getAnnotations()||[]:((s=n.batchImages[o])==null?void 0:s.annotations)||[]},Fe=o=>o.type==="rectangle",Ue=o=>o.type==="polygon",Oe=o=>o.type==="point",We=o=>o.type==="rotatedRect",R=o=>{var r,d;const s=(r=f.value.find(m=>m.name===o.label))==null?void 0:r.color;return((d=o.style)==null?void 0:d.strokeColor)||s||"#409eff"},ot=o=>{const s=o.coordinates;return(s==null?void 0:s.points)||[]},F=o=>{const s=n.batchImages[o];if(s!=null&&s.width&&(s!=null&&s.height))return{width:s.width,height:s.height};const r=s!=null&&s.imageUrl?V.value[s.imageUrl]:void 0;return r||(s!=null&&s.imageUrl&&T(s.imageUrl),{width:1,height:1})},je=o=>{const s=n.batchImages[o];return s!=null&&s.width&&(s!=null&&s.height)?!0:s!=null&&s.imageUrl?!!V.value[s.imageUrl]:!1},Je=(o,s)=>{const r=s.coordinates,d=F(o),m=R(s),w=Math.min(r.x1,r.x2),B=Math.min(r.y1,r.y2),Ke=Math.max(r.x1,r.x2),Ze=Math.max(r.y1,r.y2);return{left:`${w/d.width*100}%`,top:`${B/d.height*100}%`,width:`${(Ke-w)/d.width*100}%`,height:`${(Ze-B)/d.height*100}%`,borderColor:m,backgroundColor:`${m}22`}},Ye=(o,s)=>{const r=F(o);return ot(s).map(d=>`${d.x/r.width*100},${d.y/r.height*100}`).join(" ")},Xe=o=>{const s=R(o);return{fill:`${s}33`,stroke:s,strokeWidth:"1.4"}},qe=(o,s,r)=>{const d=F(o),m=R(r);return{left:`${s.x/d.width*100}%`,top:`${s.y/d.height*100}%`,backgroundColor:m}},Ge=(o,s)=>{const r=s.coordinates,d=F(o),m=R(s),w=Math.abs(r.width),B=Math.abs(r.height);return{left:`${(r.x-w/2)/d.width*100}%`,top:`${(r.y-B/2)/d.height*100}%`,width:`${w/d.width*100}%`,height:`${B/d.height*100}%`,transform:`rotate(${r.angle||0}deg)`,borderColor:m,backgroundColor:`${m}22`}};return e({jumpTo:nt,setImage:De,setAnnotations:Le,getAnnotations:et,selectTool:v,loadPredictionCandidates:tt,applyPredictions:$e,rejectPredictions:Pe,exportAnnotations:He,getAllAnnotations:()=>{var o,s;return n.batchImages.length>0?n.batchImages:[{imageUrl:((o=n.image)==null?void 0:o.url)||"",annotations:((s=a.value)==null?void 0:s.getAnnotations())||[]}]},getCurrentAnnotation:()=>{var o,s,r;return{imageUrl:((o=n.batchImages[u.value])==null?void 0:o.imageUrl)||((s=n.image)==null?void 0:s.url)||"",annotations:((r=a.value)==null?void 0:r.getAnnotations())||[]}}}),t.watch(()=>{var o;return(o=n.image)==null?void 0:o.url},()=>{var o;n.batchImages.length===0&&((o=n.image)!=null&&o.url)&&y()}),t.watch(()=>n.predictionCandidates,o=>{o&&tt(o)},{immediate:!0,deep:!0}),t.watch(()=>n.batchImages.map(o=>`${o.imageUrl}:${o.width||""}x${o.height||""}`),()=>{U()},{immediate:!0}),(o,s)=>(t.openBlock(),t.createElementBlock("div",{class:t.normalizeClass(["annotation-container",p.theme])},[p.batchImages&&p.batchImages.length>0?(t.openBlock(),t.createElementBlock("div",At,[t.createElementVNode("div",_t,"批量图片("+t.toDisplayString(p.batchImages.length)+")",1),t.createElementVNode("div",It,[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(p.batchImages,(r,d)=>(t.openBlock(),t.createElementBlock("button",{key:`${r.imageUrl}-${d}`,class:t.normalizeClass(["image-list-item",{active:d===u.value}]),onClick:m=>nt(d)},[t.createElementVNode("div",St,[t.createElementVNode("img",{src:r.imageUrl,alt:`第${d+1}张`,class:"image-list-thumb"},null,8,Et),je(d)?(t.openBlock(),t.createElementBlock("div",Vt,[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(Re(d),m=>(t.openBlock(),t.createElementBlock(t.Fragment,{key:m.id},[Fe(m)?(t.openBlock(),t.createElementBlock("div",{key:0,class:"thumb-overlay-rect",style:t.normalizeStyle(Je(d,m))},null,4)):Ue(m)?(t.openBlock(),t.createElementBlock("svg",Nt,[t.createElementVNode("polygon",{points:Ye(d,m),style:t.normalizeStyle(Xe(m))},null,12,zt)])):Oe(m)?(t.openBlock(!0),t.createElementBlock(t.Fragment,{key:2},t.renderList(ot(m),(w,B)=>(t.openBlock(),t.createElementBlock("div",{key:`${m.id}-${B}`,class:"thumb-overlay-point",style:t.normalizeStyle(qe(d,w,m))},null,4))),128)):We(m)?(t.openBlock(),t.createElementBlock("div",{key:3,class:"thumb-overlay-rotated",style:t.normalizeStyle(Ge(d,m))},null,4)):t.createCommentVNode("",!0)],64))),128))])):t.createCommentVNode("",!0)]),t.createElementVNode("span",Mt,"第 "+t.toDisplayString(d+1)+" 张",1)],10,Bt))),128))])])):t.createCommentVNode("",!0),p.readOnly?t.createCommentVNode("",!0):(t.openBlock(),t.createElementBlock("div",Tt,[t.createElementVNode("div",{class:t.normalizeClass(["tool-btn",{active:g.value==="pan"}]),onClick:s[0]||(s[0]=r=>v("pan")),title:"拖动"},[t.createVNode(E,{name:"rank"})],2),t.createElementVNode("div",{class:t.normalizeClass(["tool-btn",{active:g.value==="select"}]),onClick:s[1]||(s[1]=r=>v("select")),title:"选择"},[t.createVNode(E,{name:"pointer"})],2),s[5]||(s[5]=t.createElementVNode("div",{class:"divider"},null,-1)),(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(W.value,r=>(t.openBlock(),t.createElementBlock("div",{key:r,class:t.normalizeClass(["tool-btn",{active:g.value===r}]),onClick:d=>v(r),title:J(r)},[t.createVNode(E,{name:j(r)},null,8,["name"])],10,$t))),128)),s[6]||(s[6]=t.createElementVNode("div",{class:"divider"},null,-1)),t.createElementVNode("div",{class:"tool-btn",onClick:Z,title:"放大"},[t.createVNode(E,{name:"zoom-in"})]),t.createElementVNode("div",{class:"tool-btn",onClick:Ie,title:"缩小"},[t.createVNode(E,{name:"zoom-out"})]),s[7]||(s[7]=t.createElementVNode("div",{class:"divider"},null,-1)),D.value?(t.openBlock(),t.createElementBlock("div",{key:0,class:"tool-btn",onClick:I,title:"删除选中"},[t.createVNode(E,{name:"delete"})])):t.createCommentVNode("",!0)])),t.createElementVNode("div",Pt,[p.readOnly?t.createCommentVNode("",!0):(t.openBlock(),t.createElementBlock("div",Dt,[t.createElementVNode("div",Lt,[s[8]||(s[8]=t.createElementVNode("span",{class:"label-text"},"当前标签:",-1)),t.createElementVNode("div",Ht,[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(f.value,r=>(t.openBlock(),t.createElementBlock("div",{key:r.id,class:t.normalizeClass(["tag-chip",{active:k.value===r.id}]),style:t.normalizeStyle({backgroundColor:r.color,borderColor:r.color}),onClick:d=>L(r)},t.toDisplayString(r.name),15,Rt))),128)),f.value.length===0?(t.openBlock(),t.createElementBlock("div",Ft,"请在右侧创建标签")):t.createCommentVNode("",!0)])])])),t.createElementVNode("div",{class:"canvas-wrapper",ref_key:"canvasWrapper",ref:h,onWheel:s[2]||(s[2]=t.withModifiers(()=>{},["prevent"]))},[t.createElementVNode("canvas",{ref_key:"canvasRef",ref:c},null,512)],544),p.batchImages&&p.batchImages.length>0?(t.openBlock(),t.createElementBlock("div",Ut,[t.createElementVNode("button",{onClick:Me,disabled:u.value<=0},[t.createVNode(E,{name:"back"}),s[9]||(s[9]=t.createTextVNode(" 上一张 ",-1))],8,Ot),t.createElementVNode("span",null,t.toDisplayString(u.value+1)+" / "+t.toDisplayString(p.batchImages.length),1),t.createElementVNode("button",{onClick:Te,disabled:u.value>=p.batchImages.length-1},[s[10]||(s[10]=t.createTextVNode(" 下一张 ",-1)),t.createVNode(E,{name:"right"})],8,Wt)])):t.createCommentVNode("",!0)]),p.readOnly?t.createCommentVNode("",!0):(t.openBlock(),t.createElementBlock("div",jt,[t.createElementVNode("div",{class:"sidebar-header"},[s[11]||(s[11]=t.createElementVNode("h3",null,"标签管理",-1)),t.createElementVNode("button",{class:"add-btn",onClick:Be},"添加标签")]),t.createElementVNode("div",Jt,[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(f.value,r=>(t.openBlock(),t.createElementBlock("div",{key:r.id,class:"label-item"},[t.createElementVNode("div",Yt,[t.createElementVNode("label",{class:"color-wrapper",style:t.normalizeStyle({backgroundColor:r.color})},[t.withDirectives(t.createElementVNode("input",{type:"color","onUpdate:modelValue":d=>r.color=d,onChange:d=>Ve(r),style:{visibility:"hidden",width:"0",height:"0"}},null,40,Xt),[[t.vModelText,r.color]])],4),t.createElementVNode("span",{class:"label-name",title:r.name},t.toDisplayString(r.name),9,qt),t.createElementVNode("span",{class:"action-icon eye",onClick:d=>Ne(r)},[r.visible?(t.openBlock(),t.createBlock(E,{key:0,name:"view"})):(t.openBlock(),t.createBlock(E,{key:1,name:"hide"}))],8,Gt),t.createElementVNode("div",Kt,[s[12]||(s[12]=t.createElementVNode("span",{class:"dots"},"•••",-1)),t.createElementVNode("span",{class:"delete-btn",onClick:d=>ze(r.id),title:"删除"},[t.createVNode(E,{name:"delete"})],8,Zt)])])]))),128))])])),z.value?(t.openBlock(),t.createElementBlock("div",Qt,[t.createElementVNode("div",te,[s[15]||(s[15]=t.createElementVNode("h3",null,"新增标签",-1)),t.createElementVNode("div",ee,[s[13]||(s[13]=t.createElementVNode("label",null,"名称",-1)),t.withDirectives(t.createElementVNode("input",{"onUpdate:modelValue":s[3]||(s[3]=r=>A.value.name=r),placeholder:"请输入标签名称",class:"modal-input"},null,512),[[t.vModelText,A.value.name]])]),t.createElementVNode("div",ne,[s[14]||(s[14]=t.createElementVNode("label",null,"颜色",-1)),t.createElementVNode("div",oe,[t.withDirectives(t.createElementVNode("input",{type:"color","onUpdate:modelValue":s[4]||(s[4]=r=>A.value.color=r),class:"modal-color-picker"},null,512),[[t.vModelText,A.value.color]]),t.createElementVNode("span",null,t.toDisplayString(A.value.color),1)])]),t.createElementVNode("div",{class:"modal-actions"},[t.createElementVNode("button",{onClick:Q,class:"cancel-btn"},"取消"),t.createElementVNode("button",{onClick:Se,class:"confirm-btn"},"确认")])])])):t.createCommentVNode("",!0)],2))}}),[["__scopeId","data-v-79777e6e"]]),se={class:"thumbnail-wrapper",ref:"wrapper"},ie=["src","alt"],ae=["viewBox","preserveAspectRatio"],le=["x","y","width","height","stroke","stroke-width"],re=["points","stroke","stroke-width"],ce=["x","y","fill","font-size"],he={key:1,class:"loading-placeholder"},de=H(t.defineComponent({__name:"AnnotationThumbnail",props:{src:{},annotations:{},alt:{},labels:{},fit:{},strokeWidth:{},fontSize:{}},setup(p){const e=p,i=t.ref(null),n=t.ref(!1),l=t.ref(0),c=t.ref(0),h=()=>{i.value&&(l.value=i.value.naturalWidth,c.value=i.value.naturalHeight,n.value=!0)},a=t.computed(()=>e.fit==="contain"?"xMidYMid meet":"xMidYMid slice"),g=t.computed(()=>e.strokeWidth??10),u=t.computed(()=>e.fontSize??30),x=A=>{var C;if((C=A.style)!=null&&C.strokeColor)return A.style.strokeColor;if(e.labels){const b=e.labels.find(V=>V.name===A.label);if(b)return b.color}return"#FF0000"},f=A=>{const C=A.coordinates,b=Math.min(C.x1,C.x2),V=Math.min(C.y1,C.y2),D=Math.abs(C.x1-C.x2),T=Math.abs(C.y1-C.y2);return{x:b,y:V,width:D,height:T}},k=A=>A.coordinates.points.map(b=>`${b.x},${b.y}`).join(" "),z=A=>{if(A.type==="rectangle"){const C=f(A);return{x:C.x,y:C.y-5}}else if(A.type==="polygon"){const C=A.coordinates.points;if(C.length>0)return{x:C[0].x,y:C[0].y-5}}return{x:0,y:0}};return(A,C)=>(t.openBlock(),t.createElementBlock("div",se,[t.createElementVNode("img",{ref_key:"img",ref:i,src:p.src,class:"thumbnail-image",style:t.normalizeStyle({objectFit:p.fit}),onLoad:h,alt:p.alt},null,44,ie),n.value?(t.openBlock(),t.createElementBlock("svg",{key:0,class:"annotation-overlay",viewBox:`0 0 ${l.value} ${c.value}`,preserveAspectRatio:a.value},[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(p.annotations,b=>(t.openBlock(),t.createElementBlock(t.Fragment,{key:b.id},[b.type==="rectangle"?(t.openBlock(),t.createElementBlock("rect",{key:0,x:f(b).x,y:f(b).y,width:f(b).width,height:f(b).height,stroke:x(b),"stroke-width":g.value,fill:"transparent"},null,8,le)):t.createCommentVNode("",!0),b.type==="polygon"?(t.openBlock(),t.createElementBlock("polygon",{key:1,points:k(b),stroke:x(b),"stroke-width":g.value,fill:"transparent"},null,8,re)):t.createCommentVNode("",!0),b.label?(t.openBlock(),t.createElementBlock("text",{key:2,x:z(b).x,y:z(b).y,fill:x(b),"font-size":u.value,"font-weight":"bold",class:"anno-label"},t.toDisplayString(b.label),9,ce)):t.createCommentVNode("",!0)],64))),128))],8,ae)):(t.openBlock(),t.createElementBlock("div",he,"Loading..."))],512))}}),[["__scopeId","data-v-d2fd08ec"]]),ge={key:0,class:"gallery-view"},me={class:"gallery-header"},fe={class:"label-summary"},ue=["onClick"],pe={class:"thumbnail-wrapper"},ye={class:"img-meta"},ve={class:"img-index"},xe={class:"anno-count"},be={key:0,class:"bottom-bar"},we={key:1,class:"editor-view"},ke={class:"editor-header"},Ce={class:"header-left"},Ae={class:"editor-title"},_e={class:"editor-content"},K=H(t.defineComponent({__name:"BatchAnnotator",props:{images:{},labels:{},actionBar:{},clickToEnterEditor:{type:Boolean},thumbStrokeWidth:{},thumbFontSize:{}},emits:["export","update:images","imageClick"],setup(p,{expose:e,emit:i}){const n=p,l=i,c=t.ref("gallery"),h=t.ref([]),a=t.ref(0),g=t.ref(null),u=t.ref(null),x=t.ref(null),f=t.computed(()=>{var y,v;return((v=(y=n.actionBar)==null?void 0:y.annotateButton)==null?void 0:v.show)===!0}),k=t.computed(()=>{var y,v;return((v=(y=n.actionBar)==null?void 0:y.exportButton)==null?void 0:v.show)===!0}),z=t.computed(()=>f.value||k.value),A=t.computed(()=>{var y,v;return((v=(y=n.actionBar)==null?void 0:y.annotateButton)==null?void 0:v.text)||"手动标注"}),C=t.computed(()=>{var y,v;return((v=(y=n.actionBar)==null?void 0:y.exportButton)==null?void 0:v.text)||"导出"}),b=t.computed(()=>n.clickToEnterEditor!==!1);t.watch(()=>n.images,y=>{h.value=JSON.parse(JSON.stringify(y))},{immediate:!0,deep:!0});const V=y=>{a.value=y,c.value="editor",x.value&&(x.value.scrollTop=0),t.nextTick(()=>{u.value&&(u.value.scrollTop=0),window.scrollTo(0,0),requestAnimationFrame(()=>{var v,I;(I=(v=g.value)==null?void 0:v.jumpTo)==null||I.call(v,y)})})},D=(y,v)=>{if(b.value){V(y);return}l("imageClick",{index:y,imageId:v.id,image:v})},T=y=>h.value.findIndex(v=>v.id===y);e({openImageById:y=>{const v=T(y);return v<0?!1:(V(v),!0)},triggerImageClickById:y=>{const v=T(y);if(v<0)return!1;const I=h.value[v];return I?(l("imageClick",{index:v,imageId:I.id,image:I}),!0):!1}});const O=()=>{if(g.value&&g.value.getCurrentAnnotation){const y=g.value.getCurrentAnnotation();h.value[a.value]&&(h.value[a.value].annotations=y.annotations)}c.value="gallery"},W=()=>{l("export",h.value)},j=y=>{a.value=y.currentIndex,h.value[y.currentIndex]&&(h.value[y.currentIndex].annotations=y.currentAnnotations)},J=y=>{if(g.value&&g.value.getCurrentAnnotation){const v=g.value.getCurrentAnnotation();h.value[a.value]&&(h.value[a.value].annotations=v.annotations,l("update:images",h.value))}},$=y=>{};return(y,v)=>(t.openBlock(),t.createElementBlock("div",{ref_key:"batchRootRef",ref:u,class:"batch-annotator"},[c.value==="gallery"?(t.openBlock(),t.createElementBlock("div",ge,[t.createElementVNode("div",me,[t.createElementVNode("h3",null,"批量查看与标注 ("+t.toDisplayString(h.value.length)+" 张)",1),t.createElementVNode("div",fe,[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(p.labels,I=>(t.openBlock(),t.createElementBlock("span",{key:I.id,class:"label-badge",style:t.normalizeStyle({backgroundColor:I.color})},t.toDisplayString(I.name),5))),128))])]),t.createElementVNode("div",{ref_key:"galleryGridRef",ref:x,class:"gallery-grid"},[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(h.value,(I,P)=>(t.openBlock(),t.createElementBlock("div",{key:P,class:"gallery-item",onClick:Z=>D(P,I)},[t.createElementVNode("div",pe,[t.createVNode(de,{src:I.imageUrl,annotations:I.annotations||[],labels:p.labels,fit:"cover",strokeWidth:n.thumbStrokeWidth,fontSize:n.thumbFontSize},null,8,["src","annotations","labels","strokeWidth","fontSize"])]),t.createElementVNode("div",ye,[t.createElementVNode("span",ve,"#"+t.toDisplayString(P+1),1),t.createElementVNode("span",xe,t.toDisplayString((I.annotations||[]).length)+" 标注",1)])],8,ue))),128))],512),z.value?(t.openBlock(),t.createElementBlock("div",be,[f.value?(t.openBlock(),t.createElementBlock("button",{key:0,class:"action-btn primary",onClick:v[0]||(v[0]=I=>V(0))},[t.createVNode(E,{name:"edit"}),t.createTextVNode(" "+t.toDisplayString(A.value),1)])):t.createCommentVNode("",!0),k.value?(t.openBlock(),t.createElementBlock("button",{key:1,class:"action-btn success",onClick:W},[t.createVNode(E,{name:"download"}),t.createTextVNode(" "+t.toDisplayString(C.value),1)])):t.createCommentVNode("",!0)])):t.createCommentVNode("",!0)])):(t.openBlock(),t.createElementBlock("div",we,[t.createElementVNode("div",ke,[t.createElementVNode("div",Ce,[t.createElementVNode("button",{class:"back-btn",onClick:O},[t.createVNode(E,{name:"back"}),v[1]||(v[1]=t.createTextVNode(" 返回列表 ",-1))]),t.createElementVNode("span",Ae,"正在标注: "+t.toDisplayString(a.value+1)+" / "+t.toDisplayString(h.value.length),1)])]),t.createElementVNode("div",_e,[t.createVNode(G,{ref_key:"annotatorRef",ref:g,batchImages:h.value,labels:p.labels,annotationTypes:["rectangle","polygon","point","rotatedRect"],onBatchChange:j,onAnnotationChange:J,onLabelChange:$},null,8,["batchImages","labels"])])]))],512))}}),[["__scopeId","data-v-02216921"]]);S.BatchAnnotator=K,S.ImageAnnotator=G,S.default=K,Object.defineProperties(S,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
33
+ </svg>`,Ct=["innerHTML"],_t=t.defineComponent({__name:"SvgIcon",props:{name:{},size:{}},setup(y){const e=y,i=t.ref(""),n=Object.assign({"../assets/svg/aim.svg":lt,"../assets/svg/back.svg":rt,"../assets/svg/connection.svg":ct,"../assets/svg/crop.svg":ht,"../assets/svg/delete.svg":dt,"../assets/svg/download.svg":gt,"../assets/svg/edit.svg":mt,"../assets/svg/hide.svg":ft,"../assets/svg/pointer.svg":ut,"../assets/svg/price-tag.svg":pt,"../assets/svg/rank.svg":yt,"../assets/svg/refresh-right.svg":vt,"../assets/svg/right.svg":xt,"../assets/svg/view.svg":bt,"../assets/svg/zoom-in.svg":wt,"../assets/svg/zoom-out.svg":kt});return t.watchEffect(()=>{const a=`../assets/svg/${e.name}.svg`,h=n[a];h?i.value=h:(console.warn(`Icon ${e.name} not found at path ${a}`),i.value="")}),(a,h)=>(t.openBlock(),t.createElementBlock("i",{class:t.normalizeClass(["svg-icon",[y.size?`size-${y.size}`:""]]),innerHTML:i.value},null,10,Ct))}}),F=(y,e)=>{const i=y.__vccOpts||y;for(const[n,a]of e)i[n]=a;return i},E=F(_t,[["__scopeId","data-v-3928607b"]]),At={key:0,class:"image-list-sidebar"},It={class:"image-list-title"},St={class:"image-list-scroll"},Bt=["onClick"],Et={class:"image-list-stage"},Vt=["src","alt"],Nt={key:0,class:"thumb-overlay-layer"},zt={key:1,class:"thumb-overlay-svg",viewBox:"0 0 100 100",preserveAspectRatio:"none"},Mt=["points"],Tt={class:"image-list-text"},$t={key:1,class:"left-sidebar"},Dt=["onClick","title"],Pt={class:"center-area"},Lt={key:0,class:"top-bar"},Ht={class:"label-selector"},Rt={class:"tags-row"},Ft=["onClick"],Ut={key:0,class:"no-labels"},Ot={key:1,class:"batch-nav"},Wt=["disabled"],Jt=["disabled"],jt={key:2,class:"right-sidebar"},Yt={class:"label-list"},Xt={class:"label-row"},qt=["onUpdate:modelValue","onChange"],Gt=["title"],Kt=["onClick"],Zt={class:"action-icon more-actions"},Qt=["onClick"],te={key:3,class:"modal-overlay"},ee={class:"modal-content"},ne={class:"form-group"},oe={class:"form-group"},se={class:"color-input-wrapper"},G=F(t.defineComponent({__name:"ImageAnnotator",props:{annotationTypes:{default:()=>["rectangle","polygon","point","rotatedRect"]},batchImages:{default:()=>[]},labels:{default:()=>[]},defaultActiveType:{},theme:{default:"light"},readOnly:{type:Boolean,default:!1},image:{},predictionCandidates:{},session:{},requestId:{},minZoom:{},maxZoom:{}},emits:["annotationChange","batchChange","labelChange","ready","error","tool:change","viewport:change","annotation:add","annotation:update","annotation:delete","annotation:select","prediction:loaded","prediction:apply","prediction:reject"],setup(y,{expose:e,emit:i}){const n=y,a=i,h=t.ref(null),c=t.ref(null),l=t.ref(null),g=t.ref(null),m=t.ref(0),x=t.ref(""),u=t.ref([]),k=t.ref(""),N=t.ref(!1),_=t.ref({name:"",color:"#FF0000"}),C=t.ref("none"),b=t.ref([]),V=t.ref({}),$=t.computed(()=>g.value==="select"&&!!x.value),P=o=>{if(!o||V.value[o])return;const s=new Image;s.onload=()=>{const r=s.naturalWidth||1,d=s.naturalHeight||1;V.value={...V.value,[o]:{width:r,height:d}}},s.src=o},L=()=>{n.batchImages.forEach(o=>{P(o.imageUrl)})},M=()=>{var r,d,f,w;const o=n.batchImages[m.value],s=(o==null?void 0:o.imageUrl)||((r=n.image)==null?void 0:r.url);return{eventId:`${Date.now()}-${Math.random().toString(36).slice(2,10)}`,timestamp:Date.now(),requestId:n.requestId,taskId:(d=n.session)==null?void 0:d.taskId,imageId:((f=n.image)==null?void 0:f.id)||s,operator:(w=n.session)==null?void 0:w.userId}},Z=o=>{var d;const s=o==null?void 0:o.action;if(!s)return;const r={meta:M(),action:s,current:o==null?void 0:o.changedItem,source:(d=o==null?void 0:o.changedItem)!=null&&d.predictionId?"prediction":"manual"};s==="add"&&a("annotation:add",r),s==="update"&&a("annotation:update",r),s==="delete"&&a("annotation:delete",r),s==="select"&&a("annotation:select",r)},W=t.computed(()=>n.annotationTypes.filter(o=>o!=="category")),J=o=>({rectangle:"crop",polygon:"connection",point:"aim",rotatedRect:"refresh-right",category:"price-tag"})[o]||o,j=o=>({rectangle:"矩形框",polygon:"多边形",point:"关键点",rotatedRect:"旋转矩形",category:"分类标签"})[o]||o;t.onMounted(()=>{if(L(),h.value){l.value=new at(h.value),l.value.on("annotationChange",s=>{var r,d;if(s.action==="add"&&s.changedItem){const f=u.value.find(w=>w.id===k.value);f&&(s.changedItem.label=f.name,s.changedItem.labelId=f.id)}s.action==="select"?x.value=((r=s.changedItem)==null?void 0:r.id)||"":s.action==="delete"&&((d=s.changedItem)==null?void 0:d.id)===x.value&&(x.value=""),a("annotationChange",s),Z(s)}),D(),T();const o=new ResizeObserver(()=>{var s;(s=l.value)==null||s.resize()});c.value&&o.observe(c.value),n.defaultActiveType&&p(n.defaultActiveType),a("ready",{meta:M()})}});const T=()=>{if(!l.value)return;const o=u.value.find(r=>r.id===k.value);o&&l.value.setLabelStyle(o.color);const s=u.value.filter(r=>r.visible).map(r=>r.name);l.value.setVisibleLabels(s)},D=()=>{var o;if(l.value)if(x.value="",requestAnimationFrame(()=>{var s;(s=l.value)==null||s.resize()}),n.batchImages.length>0){const s=n.batchImages[m.value];l.value.loadImage(s.imageUrl),s.annotations?l.value.setAnnotations(s.annotations):l.value.setAnnotations([])}else(o=n.image)!=null&&o.url&&l.value.loadImage(n.image.url)},p=o=>{var s,r;if(g.value=o,x.value="",o!=="pan"&&o!=="select"&&u.value.length===0){alert("请先创建标签!");return}o==="pan"||o==="select"?(s=l.value)==null||s.setTool(o):(r=l.value)==null||r.setTool(o),a("tool:change",{meta:M(),tool:o})},v=()=>{var o;(o=l.value)!=null&&o.activeAnnotation&&l.value.deleteAnnotation(l.value.activeAnnotation.id)},I=()=>{l.value&&a("viewport:change",{meta:M(),scale:l.value.scale,offset:{...l.value.offset}})},H=()=>{var o;(o=l.value)==null||o.zoom(1),I()},Q=()=>{var o;(o=l.value)==null||o.zoom(-1),I()},Se=()=>{_.value={name:"",color:"#2196F3"},N.value=!0},tt=()=>{N.value=!1},Be=()=>{if(!_.value.name.trim()){alert("请输入标签名称");return}const s={id:Date.now().toString(),name:_.value.name,color:_.value.color,visible:!0};u.value.push(s),a("labelChange",u.value),T(),u.value.length===1&&R(s),tt()},R=o=>{var s;k.value=o.id,(s=l.value)==null||s.setLabelStyle(o.color)},Ee=(o,s)=>{if(!o.startsWith("#"))return o;let r=0,d=0,f=0;return o.length===4?(r=parseInt(o[1]+o[1],16),d=parseInt(o[2]+o[2],16),f=parseInt(o[3]+o[3],16)):o.length===7&&(r=parseInt(o.slice(1,3),16),d=parseInt(o.slice(3,5),16),f=parseInt(o.slice(5,7),16)),`rgba(${r}, ${d}, ${f}, ${s})`},Ve=o=>{var s;if(o.id===k.value&&((s=l.value)==null||s.setLabelStyle(o.color)),l.value){const r=l.value.getAnnotations();let d=!1;r.forEach(f=>{f.label===o.name&&(f.style||(f.style={}),f.style.strokeColor=o.color,f.style.fillColor=Ee(o.color,.2),d=!0)}),d&&l.value.render()}a("labelChange",u.value),T()},Ne=o=>{o.visible=!o.visible,T()},ze=o=>{const s=u.value.findIndex(r=>r.id===o);s>-1&&(u.value.splice(s,1),a("labelChange",u.value),k.value===o&&(k.value=u.value.length>0?u.value[0].id:"",k.value&&R(u.value[0])),T())};t.watch(()=>n.labels,o=>{const s=JSON.parse(JSON.stringify(o||[]));if(u.value=s,u.value.length>0)if(!k.value||!u.value.find(r=>r.id===k.value))R(u.value[0]);else{const r=u.value.find(d=>d.id===k.value);r&&R(r)}else k.value="";T()},{immediate:!0,deep:!0});const Me=()=>{m.value>0&&(Y(),m.value--,D(),X())},Te=()=>{m.value<n.batchImages.length-1&&(Y(),m.value++,D(),X())},Y=()=>{if(l.value){const o=l.value.getAnnotations();n.batchImages[m.value].annotations=o}},X=()=>{const o=n.batchImages[m.value];a("batchChange",{currentIndex:m.value,total:n.batchImages.length,currentImageUrl:o.imageUrl,currentAnnotations:o.annotations||[]})},et=(o=[])=>{var f;if(!l.value)return;if(b.value=JSON.parse(JSON.stringify(o)),b.value.length===0){C.value="none";return}C.value="loaded";const r=(l.value.getAnnotations()||[]).filter(w=>!w.predictionId),d=b.value.map(w=>{const S=JSON.parse(JSON.stringify(w.annotation));return S.id=S.id||`pred-${w.id}`,S.predictionId=w.id,S.modelRunId=w.modelRunId||S.modelRunId,S.confidence=w.confidence??S.confidence,S.reviewStatus=S.reviewStatus||"draft",S});l.value.setAnnotations([...r,...d]),a("prediction:loaded",{meta:M(),modelRunId:(f=b.value[0])==null?void 0:f.modelRunId,candidates:b.value})},$e=(o,s)=>{var f;if(!l.value)return[];C.value="applying";const d=(l.value.getAnnotations()||[]).filter(w=>w.predictionId&&o.includes(w.predictionId));return d.forEach(w=>{w.reviewStatus="accepted"}),C.value="applied",a("prediction:apply",{meta:M(),modelRunId:(f=d[0])==null?void 0:f.modelRunId,candidateIds:o,threshold:s,acceptedAnnotations:d}),l.value.render(),d},De=(o,s)=>{var f;if(!l.value)return;const r=l.value.getAnnotations()||[],d=r.filter(w=>!(w.predictionId&&o.includes(w.predictionId)));l.value.setAnnotations(d),a("prediction:reject",{meta:M(),modelRunId:(f=r.find(w=>w.predictionId&&o.includes(w.predictionId)))==null?void 0:f.modelRunId,candidateIds:o,reason:s})},Pe=(o,s=[])=>{l.value&&(l.value.loadImage(o.url),l.value.setAnnotations(s))},Le=o=>{var s;(s=l.value)==null||s.setAnnotations(o)},nt=()=>{var o;return((o=l.value)==null?void 0:o.getAnnotations())||[]},He=(o="json")=>{var r,d;const s=nt();return{format:o,image:((r=n.batchImages[m.value])==null?void 0:r.imageUrl)||((d=n.image)==null?void 0:d.url)||"",annotations:s}},ot=o=>{o>=0&&o<n.batchImages.length&&(Y(),m.value=o,D(),X())},Re=o=>{var s;return o===m.value&&l.value?l.value.getAnnotations()||[]:((s=n.batchImages[o])==null?void 0:s.annotations)||[]},Fe=o=>o.type==="rectangle",Ue=o=>o.type==="polygon",Oe=o=>o.type==="point",We=o=>o.type==="rotatedRect",U=o=>{var r,d;const s=(r=u.value.find(f=>f.name===o.label))==null?void 0:r.color;return((d=o.style)==null?void 0:d.strokeColor)||s||"#409eff"},st=o=>{const s=o.coordinates;return(s==null?void 0:s.points)||[]},O=o=>{const s=n.batchImages[o];if(s!=null&&s.width&&(s!=null&&s.height))return{width:s.width,height:s.height};const r=s!=null&&s.imageUrl?V.value[s.imageUrl]:void 0;return r||(s!=null&&s.imageUrl&&P(s.imageUrl),{width:1,height:1})},Je=o=>{const s=n.batchImages[o];return s!=null&&s.width&&(s!=null&&s.height)?!0:s!=null&&s.imageUrl?!!V.value[s.imageUrl]:!1},je=(o,s)=>{const r=s.coordinates,d=O(o),f=U(s),w=Math.min(r.x1,r.x2),S=Math.min(r.y1,r.y2),Ke=Math.max(r.x1,r.x2),Ze=Math.max(r.y1,r.y2);return{left:`${w/d.width*100}%`,top:`${S/d.height*100}%`,width:`${(Ke-w)/d.width*100}%`,height:`${(Ze-S)/d.height*100}%`,borderColor:f,backgroundColor:`${f}22`}},Ye=(o,s)=>{const r=O(o);return st(s).map(d=>`${d.x/r.width*100},${d.y/r.height*100}`).join(" ")},Xe=o=>{const s=U(o);return{fill:`${s}33`,stroke:s,strokeWidth:"1.4"}},qe=(o,s,r)=>{const d=O(o),f=U(r);return{left:`${s.x/d.width*100}%`,top:`${s.y/d.height*100}%`,backgroundColor:f}},Ge=(o,s)=>{const r=s.coordinates,d=O(o),f=U(s),w=Math.abs(r.width),S=Math.abs(r.height);return{left:`${(r.x-w/2)/d.width*100}%`,top:`${(r.y-S/2)/d.height*100}%`,width:`${w/d.width*100}%`,height:`${S/d.height*100}%`,transform:`rotate(${r.angle||0}deg)`,borderColor:f,backgroundColor:`${f}22`}};return e({jumpTo:ot,setImage:Pe,setAnnotations:Le,getAnnotations:nt,selectTool:p,loadPredictionCandidates:et,applyPredictions:$e,rejectPredictions:De,exportAnnotations:He,getAllAnnotations:()=>{var o,s;return n.batchImages.length>0?n.batchImages:[{imageUrl:((o=n.image)==null?void 0:o.url)||"",annotations:((s=l.value)==null?void 0:s.getAnnotations())||[]}]},getCurrentAnnotation:()=>{var o,s,r;return{imageUrl:((o=n.batchImages[m.value])==null?void 0:o.imageUrl)||((s=n.image)==null?void 0:s.url)||"",annotations:((r=l.value)==null?void 0:r.getAnnotations())||[]}}}),t.watch(()=>{var o;return(o=n.image)==null?void 0:o.url},()=>{var o;n.batchImages.length===0&&((o=n.image)!=null&&o.url)&&D()}),t.watch(()=>n.predictionCandidates,o=>{o&&et(o)},{immediate:!0,deep:!0}),t.watch(()=>n.batchImages.map(o=>`${o.imageUrl}:${o.width||""}x${o.height||""}`),()=>{L()},{immediate:!0}),(o,s)=>(t.openBlock(),t.createElementBlock("div",{class:t.normalizeClass(["annotation-container",y.theme])},[y.batchImages&&y.batchImages.length>0?(t.openBlock(),t.createElementBlock("div",At,[t.createElementVNode("div",It,"批量图片("+t.toDisplayString(y.batchImages.length)+")",1),t.createElementVNode("div",St,[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(y.batchImages,(r,d)=>(t.openBlock(),t.createElementBlock("button",{key:`${r.imageUrl}-${d}`,class:t.normalizeClass(["image-list-item",{active:d===m.value}]),onClick:f=>ot(d)},[t.createElementVNode("div",Et,[t.createElementVNode("img",{src:r.imageUrl,alt:`第${d+1}张`,class:"image-list-thumb"},null,8,Vt),Je(d)?(t.openBlock(),t.createElementBlock("div",Nt,[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(Re(d),f=>(t.openBlock(),t.createElementBlock(t.Fragment,{key:f.id},[Fe(f)?(t.openBlock(),t.createElementBlock("div",{key:0,class:"thumb-overlay-rect",style:t.normalizeStyle(je(d,f))},null,4)):Ue(f)?(t.openBlock(),t.createElementBlock("svg",zt,[t.createElementVNode("polygon",{points:Ye(d,f),style:t.normalizeStyle(Xe(f))},null,12,Mt)])):Oe(f)?(t.openBlock(!0),t.createElementBlock(t.Fragment,{key:2},t.renderList(st(f),(w,S)=>(t.openBlock(),t.createElementBlock("div",{key:`${f.id}-${S}`,class:"thumb-overlay-point",style:t.normalizeStyle(qe(d,w,f))},null,4))),128)):We(f)?(t.openBlock(),t.createElementBlock("div",{key:3,class:"thumb-overlay-rotated",style:t.normalizeStyle(Ge(d,f))},null,4)):t.createCommentVNode("",!0)],64))),128))])):t.createCommentVNode("",!0)]),t.createElementVNode("span",Tt,"第 "+t.toDisplayString(d+1)+" 张",1)],10,Bt))),128))])])):t.createCommentVNode("",!0),y.readOnly?t.createCommentVNode("",!0):(t.openBlock(),t.createElementBlock("div",$t,[t.createElementVNode("div",{class:t.normalizeClass(["tool-btn",{active:g.value==="pan"}]),onClick:s[0]||(s[0]=r=>p("pan")),title:"拖动"},[t.createVNode(E,{name:"rank"})],2),t.createElementVNode("div",{class:t.normalizeClass(["tool-btn",{active:g.value==="select"}]),onClick:s[1]||(s[1]=r=>p("select")),title:"选择"},[t.createVNode(E,{name:"pointer"})],2),s[5]||(s[5]=t.createElementVNode("div",{class:"divider"},null,-1)),(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(W.value,r=>(t.openBlock(),t.createElementBlock("div",{key:r,class:t.normalizeClass(["tool-btn",{active:g.value===r}]),onClick:d=>p(r),title:j(r)},[t.createVNode(E,{name:J(r)},null,8,["name"])],10,Dt))),128)),s[6]||(s[6]=t.createElementVNode("div",{class:"divider"},null,-1)),t.createElementVNode("div",{class:"tool-btn",onClick:H,title:"放大"},[t.createVNode(E,{name:"zoom-in"})]),t.createElementVNode("div",{class:"tool-btn",onClick:Q,title:"缩小"},[t.createVNode(E,{name:"zoom-out"})]),s[7]||(s[7]=t.createElementVNode("div",{class:"divider"},null,-1)),$.value?(t.openBlock(),t.createElementBlock("div",{key:0,class:"tool-btn",onClick:v,title:"删除选中"},[t.createVNode(E,{name:"delete"})])):t.createCommentVNode("",!0)])),t.createElementVNode("div",Pt,[y.readOnly?t.createCommentVNode("",!0):(t.openBlock(),t.createElementBlock("div",Lt,[t.createElementVNode("div",Ht,[s[8]||(s[8]=t.createElementVNode("span",{class:"label-text"},"当前标签:",-1)),t.createElementVNode("div",Rt,[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(u.value,r=>(t.openBlock(),t.createElementBlock("div",{key:r.id,class:t.normalizeClass(["tag-chip",{active:k.value===r.id}]),style:t.normalizeStyle({backgroundColor:r.color,borderColor:r.color}),onClick:d=>R(r)},t.toDisplayString(r.name),15,Ft))),128)),u.value.length===0?(t.openBlock(),t.createElementBlock("div",Ut,"请在右侧创建标签")):t.createCommentVNode("",!0)])])])),t.createElementVNode("div",{class:"canvas-wrapper",ref_key:"canvasWrapper",ref:c,onWheel:s[2]||(s[2]=t.withModifiers(()=>{},["prevent"]))},[t.createElementVNode("canvas",{ref_key:"canvasRef",ref:h},null,512)],544),y.batchImages&&y.batchImages.length>0?(t.openBlock(),t.createElementBlock("div",Ot,[t.createElementVNode("button",{onClick:Me,disabled:m.value<=0},[t.createVNode(E,{name:"back"}),s[9]||(s[9]=t.createTextVNode(" 上一张 ",-1))],8,Wt),t.createElementVNode("span",null,t.toDisplayString(m.value+1)+" / "+t.toDisplayString(y.batchImages.length),1),t.createElementVNode("button",{onClick:Te,disabled:m.value>=y.batchImages.length-1},[s[10]||(s[10]=t.createTextVNode(" 下一张 ",-1)),t.createVNode(E,{name:"right"})],8,Jt)])):t.createCommentVNode("",!0)]),y.readOnly?t.createCommentVNode("",!0):(t.openBlock(),t.createElementBlock("div",jt,[t.createElementVNode("div",{class:"sidebar-header"},[s[11]||(s[11]=t.createElementVNode("h3",null,"标签管理",-1)),t.createElementVNode("button",{class:"add-btn",onClick:Se},"添加标签")]),t.createElementVNode("div",Yt,[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(u.value,r=>(t.openBlock(),t.createElementBlock("div",{key:r.id,class:"label-item"},[t.createElementVNode("div",Xt,[t.createElementVNode("label",{class:"color-wrapper",style:t.normalizeStyle({backgroundColor:r.color})},[t.withDirectives(t.createElementVNode("input",{type:"color","onUpdate:modelValue":d=>r.color=d,onChange:d=>Ve(r),style:{visibility:"hidden",width:"0",height:"0"}},null,40,qt),[[t.vModelText,r.color]])],4),t.createElementVNode("span",{class:"label-name",title:r.name},t.toDisplayString(r.name),9,Gt),t.createElementVNode("span",{class:"action-icon eye",onClick:d=>Ne(r)},[r.visible?(t.openBlock(),t.createBlock(E,{key:0,name:"view"})):(t.openBlock(),t.createBlock(E,{key:1,name:"hide"}))],8,Kt),t.createElementVNode("div",Zt,[s[12]||(s[12]=t.createElementVNode("span",{class:"dots"},"•••",-1)),t.createElementVNode("span",{class:"delete-btn",onClick:d=>ze(r.id),title:"删除"},[t.createVNode(E,{name:"delete"})],8,Qt)])])]))),128))])])),N.value?(t.openBlock(),t.createElementBlock("div",te,[t.createElementVNode("div",ee,[s[15]||(s[15]=t.createElementVNode("h3",null,"新增标签",-1)),t.createElementVNode("div",ne,[s[13]||(s[13]=t.createElementVNode("label",null,"名称",-1)),t.withDirectives(t.createElementVNode("input",{"onUpdate:modelValue":s[3]||(s[3]=r=>_.value.name=r),placeholder:"请输入标签名称",class:"modal-input"},null,512),[[t.vModelText,_.value.name]])]),t.createElementVNode("div",oe,[s[14]||(s[14]=t.createElementVNode("label",null,"颜色",-1)),t.createElementVNode("div",se,[t.withDirectives(t.createElementVNode("input",{type:"color","onUpdate:modelValue":s[4]||(s[4]=r=>_.value.color=r),class:"modal-color-picker"},null,512),[[t.vModelText,_.value.color]]),t.createElementVNode("span",null,t.toDisplayString(_.value.color),1)])]),t.createElementVNode("div",{class:"modal-actions"},[t.createElementVNode("button",{onClick:tt,class:"cancel-btn"},"取消"),t.createElementVNode("button",{onClick:Be,class:"confirm-btn"},"确认")])])])):t.createCommentVNode("",!0)],2))}}),[["__scopeId","data-v-ccc538f3"]]),ie={class:"thumbnail-wrapper",ref:"wrapper"},ae=["src","alt"],le=["viewBox","preserveAspectRatio"],re=["x","y","width","height","stroke","stroke-width"],ce=["points","stroke","stroke-width"],he=["x","y","fill","font-size"],de={key:1,class:"loading-placeholder"},ge=F(t.defineComponent({__name:"AnnotationThumbnail",props:{src:{},annotations:{},alt:{},labels:{},fit:{},strokeWidth:{},fontSize:{}},setup(y){const e=y,i=t.ref(null),n=t.ref(!1),a=t.ref(0),h=t.ref(0),c=()=>{i.value&&(a.value=i.value.naturalWidth,h.value=i.value.naturalHeight,n.value=!0)},l=t.computed(()=>e.fit==="contain"?"xMidYMid meet":"xMidYMid slice"),g=t.computed(()=>e.strokeWidth??10),m=t.computed(()=>e.fontSize??30),x=_=>{var C;if((C=_.style)!=null&&C.strokeColor)return _.style.strokeColor;if(e.labels){const b=e.labels.find(V=>V.name===_.label);if(b)return b.color}return"#FF0000"},u=_=>{const C=_.coordinates,b=Math.min(C.x1,C.x2),V=Math.min(C.y1,C.y2),$=Math.abs(C.x1-C.x2),P=Math.abs(C.y1-C.y2);return{x:b,y:V,width:$,height:P}},k=_=>_.coordinates.points.map(b=>`${b.x},${b.y}`).join(" "),N=_=>{if(_.type==="rectangle"){const C=u(_);return{x:C.x,y:C.y-5}}else if(_.type==="polygon"){const C=_.coordinates.points;if(C.length>0)return{x:C[0].x,y:C[0].y-5}}return{x:0,y:0}};return(_,C)=>(t.openBlock(),t.createElementBlock("div",ie,[t.createElementVNode("img",{ref_key:"img",ref:i,src:y.src,class:"thumbnail-image",style:t.normalizeStyle({objectFit:y.fit}),onLoad:c,alt:y.alt},null,44,ae),n.value?(t.openBlock(),t.createElementBlock("svg",{key:0,class:"annotation-overlay",viewBox:`0 0 ${a.value} ${h.value}`,preserveAspectRatio:l.value},[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(y.annotations,b=>(t.openBlock(),t.createElementBlock(t.Fragment,{key:b.id},[b.type==="rectangle"?(t.openBlock(),t.createElementBlock("rect",{key:0,x:u(b).x,y:u(b).y,width:u(b).width,height:u(b).height,stroke:x(b),"stroke-width":g.value,fill:"transparent"},null,8,re)):t.createCommentVNode("",!0),b.type==="polygon"?(t.openBlock(),t.createElementBlock("polygon",{key:1,points:k(b),stroke:x(b),"stroke-width":g.value,fill:"transparent"},null,8,ce)):t.createCommentVNode("",!0),b.label?(t.openBlock(),t.createElementBlock("text",{key:2,x:N(b).x,y:N(b).y,fill:x(b),"font-size":m.value,"font-weight":"bold",class:"anno-label"},t.toDisplayString(b.label),9,he)):t.createCommentVNode("",!0)],64))),128))],8,le)):(t.openBlock(),t.createElementBlock("div",de,"Loading..."))],512))}}),[["__scopeId","data-v-d2fd08ec"]]),me={key:0,class:"gallery-view"},fe={class:"gallery-header"},ue={class:"label-summary"},pe=["onClick"],ye={class:"thumbnail-wrapper"},ve={class:"img-meta"},xe={class:"img-index"},be={class:"anno-count"},we={key:0,class:"bottom-bar"},ke={key:1,class:"editor-view"},Ce={class:"editor-header"},_e={class:"header-left"},Ae={class:"editor-title"},Ie={class:"editor-content"},K=F(t.defineComponent({__name:"BatchAnnotator",props:{images:{},labels:{},actionBar:{},clickToEnterEditor:{type:Boolean},thumbStrokeWidth:{},thumbFontSize:{}},emits:["export","update:images","imageClick","update:labels"],setup(y,{expose:e,emit:i}){const n=y,a=i,h=t.ref("gallery"),c=t.ref([]),l=t.ref([]),g=t.ref(0),m=t.ref(null),x=t.ref(null),u=t.ref(null),k=t.computed(()=>{var p,v;return((v=(p=n.actionBar)==null?void 0:p.annotateButton)==null?void 0:v.show)===!0}),N=t.computed(()=>{var p,v;return((v=(p=n.actionBar)==null?void 0:p.exportButton)==null?void 0:v.show)===!0}),_=t.computed(()=>k.value||N.value),C=t.computed(()=>{var p,v;return((v=(p=n.actionBar)==null?void 0:p.annotateButton)==null?void 0:v.text)||"手动标注"}),b=t.computed(()=>{var p,v;return((v=(p=n.actionBar)==null?void 0:p.exportButton)==null?void 0:v.text)||"导出"}),V=t.computed(()=>n.clickToEnterEditor!==!1);t.watch(()=>n.images,p=>{c.value=JSON.parse(JSON.stringify(p))},{immediate:!0,deep:!0}),t.watch(()=>n.labels,p=>{l.value=JSON.parse(JSON.stringify(p||[]))},{immediate:!0,deep:!0});const $=p=>{g.value=p,h.value="editor",u.value&&(u.value.scrollTop=0),t.nextTick(()=>{x.value&&(x.value.scrollTop=0),window.scrollTo(0,0),requestAnimationFrame(()=>{var v,I;(I=(v=m.value)==null?void 0:v.jumpTo)==null||I.call(v,p)})})},P=(p,v)=>{if(V.value){$(p);return}a("imageClick",{index:p,imageId:v.id,image:v})},L=p=>c.value.findIndex(v=>v.id===p);e({openImageById:p=>{const v=L(p);return v<0?!1:($(v),!0)},triggerImageClickById:p=>{const v=L(p);if(v<0)return!1;const I=c.value[v];return I?(a("imageClick",{index:v,imageId:I.id,image:I}),!0):!1},getFinalData:()=>({images:JSON.parse(JSON.stringify(c.value)),labels:JSON.parse(JSON.stringify(l.value))})});const W=()=>{if(m.value&&m.value.getCurrentAnnotation){const p=m.value.getCurrentAnnotation();c.value[g.value]&&(c.value[g.value].annotations=p.annotations)}h.value="gallery"},J=()=>{a("export",c.value)},j=p=>{g.value=p.currentIndex,c.value[p.currentIndex]&&(c.value[p.currentIndex].annotations=p.currentAnnotations)},T=p=>{if(m.value&&m.value.getCurrentAnnotation){const v=m.value.getCurrentAnnotation();c.value[g.value]&&(c.value[g.value].annotations=v.annotations,a("update:images",c.value))}},D=p=>{l.value=JSON.parse(JSON.stringify(p||[])),a("update:labels",l.value)};return(p,v)=>(t.openBlock(),t.createElementBlock("div",{ref_key:"batchRootRef",ref:x,class:"batch-annotator"},[h.value==="gallery"?(t.openBlock(),t.createElementBlock("div",me,[t.createElementVNode("div",fe,[t.createElementVNode("h3",null,"批量查看与标注 ("+t.toDisplayString(c.value.length)+" 张)",1),t.createElementVNode("div",ue,[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(l.value,I=>(t.openBlock(),t.createElementBlock("span",{key:I.id,class:"label-badge",style:t.normalizeStyle({backgroundColor:I.color})},t.toDisplayString(I.name),5))),128))])]),t.createElementVNode("div",{ref_key:"galleryGridRef",ref:u,class:"gallery-grid"},[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(c.value,(I,H)=>(t.openBlock(),t.createElementBlock("div",{key:H,class:"gallery-item",onClick:Q=>P(H,I)},[t.createElementVNode("div",ye,[t.createVNode(ge,{src:I.imageUrl,annotations:I.annotations||[],labels:l.value,fit:"cover",strokeWidth:n.thumbStrokeWidth,fontSize:n.thumbFontSize},null,8,["src","annotations","labels","strokeWidth","fontSize"])]),t.createElementVNode("div",ve,[t.createElementVNode("span",xe,"#"+t.toDisplayString(H+1),1),t.createElementVNode("span",be,t.toDisplayString((I.annotations||[]).length)+" 标注",1)])],8,pe))),128))],512),_.value?(t.openBlock(),t.createElementBlock("div",we,[k.value?(t.openBlock(),t.createElementBlock("button",{key:0,class:"action-btn primary",onClick:v[0]||(v[0]=I=>$(0))},[t.createVNode(E,{name:"edit"}),t.createTextVNode(" "+t.toDisplayString(C.value),1)])):t.createCommentVNode("",!0),N.value?(t.openBlock(),t.createElementBlock("button",{key:1,class:"action-btn success",onClick:J},[t.createVNode(E,{name:"download"}),t.createTextVNode(" "+t.toDisplayString(b.value),1)])):t.createCommentVNode("",!0)])):t.createCommentVNode("",!0)])):(t.openBlock(),t.createElementBlock("div",ke,[t.createElementVNode("div",Ce,[t.createElementVNode("div",_e,[t.createElementVNode("button",{class:"back-btn",onClick:W},[t.createVNode(E,{name:"back"}),v[1]||(v[1]=t.createTextVNode(" 返回列表 ",-1))]),t.createElementVNode("span",Ae,"正在标注: "+t.toDisplayString(g.value+1)+" / "+t.toDisplayString(c.value.length),1)])]),t.createElementVNode("div",Ie,[t.createVNode(G,{ref_key:"annotatorRef",ref:m,batchImages:c.value,labels:l.value,annotationTypes:["rectangle","polygon","point","rotatedRect"],onBatchChange:j,onAnnotationChange:T,onLabelChange:D},null,8,["batchImages","labels"])])]))],512))}}),[["__scopeId","data-v-0ae1040a"]]);B.BatchAnnotator=K,B.ImageAnnotator=G,B.default=K,Object.defineProperties(B,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "luo-image-annotator",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "description": "A simple image annotation component for Vue 3",
5
5
  "scripts": {
6
6
  "dev": "vite",
@@ -518,6 +518,12 @@ const onImageClick = (payload: { index: number; image: BatchImage }) => {
518
518
  - `clickToEnterEditor`: `boolean`
519
519
  - 默认 `true`,点击缩略图进入编辑页
520
520
  - 配置 `false` 时,点击缩略图不跳转,仅触发 `imageClick` 事件供业务自定义
521
+ - `thumbStrokeWidth`: `number`
522
+ - 列表页缩略图标注描边宽度(SVG 坐标系),默认 `10`
523
+ - 仅影响缩略图叠加的显示,不影响编辑器内样式
524
+ - `thumbFontSize`: `number`
525
+ - 列表页缩略图标签文字字号(SVG 坐标系),默认 `30`
526
+ - 仅影响缩略图叠加的显示,不影响编辑器内样式
521
527
 
522
528
  #### 8.3.2 BatchAnnotator 出参(Events)
523
529
 
@@ -539,6 +545,9 @@ const onImageClick = (payload: { index: number; image: BatchImage }) => {
539
545
  - `triggerImageClickById(id: string | number): boolean`
540
546
  - 外部按 `id` 主动触发 `imageClick` 事件
541
547
  - 触发成功返回 `true`,未找到返回 `false`
548
+ - `getFinalData(): { images: BatchImageItem[]; labels: LabelDefinition[] }`
549
+ - 获取当前最新的批量图片与标注数组、以及标签数组
550
+ - 返回结构与入参一致,内容为最终修改后的结果
542
551
 
543
552
  #### 8.3.4 BatchAnnotator 详细引用示例(可直接复制)
544
553
 
@@ -550,9 +559,14 @@ const onImageClick = (payload: { index: number; image: BatchImage }) => {
550
559
  :images="images"
551
560
  :labels="labels"
552
561
  :clickToEnterEditor="false"
562
+ :thumbStrokeWidth="30"
563
+ :thumbFontSize="200"
564
+ :thumbStrokeWidth="30"
565
+ :thumbFontSize="200"
553
566
  @update:images="handleImagesUpdate"
554
567
  @export="handleExport"
555
568
  @imageClick="handleImageClick"
569
+ <button @click="callExportMethod">导出最终结果</button>
556
570
  />
557
571
  <button @click="jumpByImageId">外部传 id 进入详情页</button>
558
572
  </div>
@@ -561,8 +575,6 @@ const onImageClick = (payload: { index: number; image: BatchImage }) => {
561
575
  <script setup lang="ts">
562
576
  import { ref } from 'vue'
563
577
  import { BatchAnnotator } from 'luo-image-annotator'
564
- import type { AnnotationItem, BatchAnnotatorExpose, LabelDefinition } from 'luo-image-annotator'
565
- import 'luo-image-annotator/style.css'
566
578
 
567
579
  type BatchImageItem = {
568
580
  id?: string | number
@@ -622,6 +634,11 @@ const persistDraft = (payload: BatchImageItem[]) => {
622
634
  const submitTask = (payload: BatchImageItem[]) => {
623
635
  console.log('提交任务', payload)
624
636
  }
637
+
638
+ const callExportMethod = () => {
639
+ const data = batchRef.value?.getFinalData()
640
+ console.log('导出结果', data) // { images: BatchImageItem[], labels: LabelDefinition[] }
641
+ }
625
642
  </script>
626
643
  ```
627
644