luo-image-annotator 0.0.2 → 0.0.4

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,22 +1,22 @@
1
- var pt = Object.defineProperty;
2
- var xt = (u, t, e) => t in u ? pt(u, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : u[t] = e;
3
- var C = (u, t, e) => xt(u, typeof t != "symbol" ? t + "" : t, e);
4
- import { defineComponent as q, ref as k, computed as bt, onMounted as At, watch as it, resolveComponent as P, openBlock as m, createElementBlock as x, normalizeClass as N, createElementVNode as h, createVNode as b, withCtx as I, Fragment as $, renderList as F, createBlock as X, resolveDynamicComponent as Ct, createCommentVNode as L, normalizeStyle as K, toDisplayString as D, createTextVNode as J, withDirectives as j, vModelText as Y, nextTick as wt } from "vue";
5
- const Z = (u, t) => Math.sqrt(Math.pow(u.x - t.x, 2) + Math.pow(u.y - t.y, 2)), _t = (u, t) => {
6
- let e = !1;
7
- for (let n = 0, a = t.length - 1; n < t.length; a = n++) {
8
- const i = t[n].x, o = t[n].y, s = t[a].x, r = t[a].y;
9
- o > u.y != r > u.y && u.x < (s - i) * (u.y - o) / (r - o) + i && (e = !e);
1
+ var _t = Object.defineProperty;
2
+ var It = (v, t, n) => t in v ? _t(v, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : v[t] = n;
3
+ var C = (v, t, n) => It(v, typeof t != "symbol" ? t + "" : t, n);
4
+ import { defineComponent as N, ref as S, watchEffect as St, openBlock as x, createElementBlock as b, normalizeClass as $, computed as kt, onMounted as Mt, watch as V, createElementVNode as d, createVNode as z, Fragment as T, renderList as D, createCommentVNode as L, normalizeStyle as K, toDisplayString as H, createTextVNode as O, withDirectives as q, vModelText as X, createBlock as nt, nextTick as zt } from "vue";
5
+ const Y = (v, t) => Math.sqrt(Math.pow(v.x - t.x, 2) + Math.pow(v.y - t.y, 2)), Ht = (v, t) => {
6
+ let n = !1;
7
+ for (let e = 0, a = t.length - 1; e < t.length; a = e++) {
8
+ const o = t[e].x, r = t[e].y, i = t[a].x, h = t[a].y;
9
+ r > v.y != h > v.y && v.x < (i - o) * (v.y - r) / (h - r) + o && (n = !n);
10
10
  }
11
- return e;
12
- }, nt = (u, t, e) => {
13
- const n = e * (Math.PI / 180), a = Math.cos(n), i = Math.sin(n), o = u.x - t.x, s = u.y - t.y;
11
+ return n;
12
+ }, st = (v, t, n) => {
13
+ const e = n * (Math.PI / 180), a = Math.cos(e), o = Math.sin(e), r = v.x - t.x, i = v.y - t.y;
14
14
  return {
15
- x: t.x + (o * a - s * i),
16
- y: t.y + (o * i + s * a)
15
+ x: t.x + (r * a - i * o),
16
+ y: t.y + (r * o + i * a)
17
17
  };
18
18
  };
19
- class kt {
19
+ class Pt {
20
20
  constructor(t) {
21
21
  C(this, "canvas");
22
22
  C(this, "ctx");
@@ -54,18 +54,18 @@ class kt {
54
54
  C(this, "listeners", {});
55
55
  C(this, "imageUrl", "");
56
56
  this.canvas = t;
57
- const e = t.getContext("2d");
58
- if (!e) throw new Error("Could not get 2d context");
59
- this.ctx = e, this.img = new Image(), this.img.crossOrigin = "Anonymous", this.img.onload = () => {
57
+ const n = t.getContext("2d");
58
+ if (!n) throw new Error("Could not get 2d context");
59
+ this.ctx = n, this.img = new Image(), this.img.crossOrigin = "Anonymous", this.img.onload = () => {
60
60
  this.fitImageToCanvas(), this.render();
61
61
  }, this.bindEvents();
62
62
  }
63
63
  // --- 公共 API ---
64
- on(t, e) {
65
- this.listeners[t] || (this.listeners[t] = []), this.listeners[t].push(e);
64
+ on(t, n) {
65
+ this.listeners[t] || (this.listeners[t] = []), this.listeners[t].push(n);
66
66
  }
67
- emit(t, e) {
68
- this.listeners[t] && this.listeners[t].forEach((n) => n(e));
67
+ emit(t, n) {
68
+ this.listeners[t] && this.listeners[t].forEach((e) => e(n));
69
69
  }
70
70
  loadImage(t) {
71
71
  this.imageUrl = t, this.img.src = t, this.activeAnnotation = null, this.isDrawing = !1;
@@ -86,33 +86,33 @@ class kt {
86
86
  this.visibleLabels = new Set(t), this.render();
87
87
  }
88
88
  zoom(t) {
89
- const n = t > 0 ? this.scale * 1.1 : this.scale / 1.1;
90
- if (n < 0.1 || n > 10) return;
91
- const a = this.canvas.width / 2, i = this.canvas.height / 2, o = this.toImageCoords(a, i);
92
- this.scale = n, this.offset.x = a - o.x * this.scale, this.offset.y = i - o.y * this.scale, this.render();
89
+ const e = t > 0 ? this.scale * 1.1 : this.scale / 1.1;
90
+ if (e < 0.1 || e > 10) return;
91
+ const a = this.canvas.width / 2, o = this.canvas.height / 2, r = this.toImageCoords(a, o);
92
+ this.scale = e, this.offset.x = a - r.x * this.scale, this.offset.y = o - r.y * this.scale, this.render();
93
93
  }
94
94
  resize() {
95
95
  this.fitImageToCanvas(), this.render();
96
96
  }
97
97
  // --- 坐标系统 ---
98
- toImageCoords(t, e) {
98
+ toImageCoords(t, n) {
99
99
  return {
100
100
  x: (t - this.offset.x) / this.scale,
101
- y: (e - this.offset.y) / this.scale
101
+ y: (n - this.offset.y) / this.scale
102
102
  };
103
103
  }
104
- toScreenCoords(t, e) {
104
+ toScreenCoords(t, n) {
105
105
  return {
106
106
  x: t * this.scale + this.offset.x,
107
- y: e * this.scale + this.offset.y
107
+ y: n * this.scale + this.offset.y
108
108
  };
109
109
  }
110
110
  fitImageToCanvas() {
111
111
  const t = this.canvas.parentElement;
112
112
  if (t) {
113
113
  if (this.canvas.width = t.clientWidth, this.canvas.height = t.clientHeight, this.img.width === 0) return;
114
- const e = this.canvas.width / this.img.width, n = this.canvas.height / this.img.height;
115
- this.scale = Math.min(e, 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;
114
+ const n = this.canvas.width / this.img.width, e = this.canvas.height / this.img.height;
115
+ this.scale = Math.min(n, e), this.offset.x = (this.canvas.width - this.img.width * this.scale) / 2, this.offset.y = (this.canvas.height - this.img.height * this.scale) / 2;
116
116
  }
117
117
  }
118
118
  // --- 事件处理 ---
@@ -123,82 +123,82 @@ class kt {
123
123
  (t.key === "Delete" || t.key === "Backspace") && this.activeAnnotation && this.deleteAnnotation(this.activeAnnotation.id);
124
124
  }
125
125
  deleteAnnotation(t) {
126
- const e = this.annotations.findIndex((n) => n.id === t);
127
- if (e > -1) {
128
- const n = this.annotations[e];
129
- this.annotations.splice(e, 1), this.activeAnnotation = null, this.emit("annotationChange", {
126
+ const n = this.annotations.findIndex((e) => e.id === t);
127
+ if (n > -1) {
128
+ const e = this.annotations[n];
129
+ this.annotations.splice(n, 1), this.activeAnnotation = null, this.emit("annotationChange", {
130
130
  action: "delete",
131
- changedItem: n,
131
+ changedItem: e,
132
132
  imageUrl: this.imageUrl
133
133
  }), this.render();
134
134
  }
135
135
  }
136
136
  handleMouseDown(t) {
137
- const e = this.canvas.getBoundingClientRect(), n = t.clientX - e.left, a = t.clientY - e.top, i = this.toImageCoords(n, a);
137
+ const n = this.canvas.getBoundingClientRect(), e = t.clientX - n.left, a = t.clientY - n.top, o = this.toImageCoords(e, a);
138
138
  if (this.canvas.style.cursor === "grab" || this.canvas.style.cursor === "grabbing") {
139
- this.isPanning = !0, this.panStartPoint = { x: n, y: a }, this.canvas.style.cursor = "grabbing";
139
+ this.isPanning = !0, this.panStartPoint = { x: e, y: a }, this.canvas.style.cursor = "grabbing";
140
140
  return;
141
141
  }
142
142
  if (this.activeAnnotation) {
143
- const r = this.getHitHandle(n, a, this.activeAnnotation);
144
- if (r !== -100) {
145
- this.isDragging = !0, this.dragStartPoint = i, this.selectedHandleIndex = r, this.dragStartAnnotation = JSON.parse(JSON.stringify(this.activeAnnotation));
143
+ const h = this.getHitHandle(e, a, this.activeAnnotation);
144
+ if (h !== -100) {
145
+ this.isDragging = !0, this.dragStartPoint = o, this.selectedHandleIndex = h, this.dragStartAnnotation = JSON.parse(JSON.stringify(this.activeAnnotation));
146
146
  return;
147
147
  }
148
148
  }
149
- const o = this.getHitCategory(n, a);
150
- if (o) {
151
- this.activeAnnotation = o, this.isDragging = !1, this.selectedHandleIndex = -1, this.emit("annotationChange", { action: "select", changedItem: o, imageUrl: this.imageUrl }), this.render();
149
+ const r = this.getHitCategory(e, a);
150
+ if (r) {
151
+ this.activeAnnotation = r, this.isDragging = !1, this.selectedHandleIndex = -1, this.emit("annotationChange", { action: "select", changedItem: r, imageUrl: this.imageUrl }), this.render();
152
152
  return;
153
153
  }
154
- const s = this.getHitAnnotation(i);
154
+ const i = this.getHitAnnotation(o);
155
155
  if (this.currentTool) {
156
156
  if (this.isDrawing && this.currentTool === "polygon" && this.activeAnnotation) {
157
- const r = this.activeAnnotation.coordinates;
158
- if (r.points.length > 2 && Z(i, r.points[0]) < 20 / this.scale) {
157
+ const h = this.activeAnnotation.coordinates;
158
+ if (h.points.length > 2 && Y(o, h.points[0]) < 20 / this.scale) {
159
159
  this.finishDrawing();
160
160
  return;
161
161
  }
162
- this.startDrawing(i);
162
+ this.startDrawing(o);
163
163
  return;
164
164
  }
165
165
  if (this.currentTool) {
166
166
  if (this.currentTool === "polygon" && !this.isDrawing) {
167
- this.startDrawing(i);
167
+ this.startDrawing(o);
168
168
  return;
169
169
  }
170
- if (s) {
171
- this.activeAnnotation = s, this.isDragging = !0, this.dragStartPoint = i, this.selectedHandleIndex = -1, this.dragStartAnnotation = JSON.parse(JSON.stringify(s)), this.emit("annotationChange", { action: "select", changedItem: s, imageUrl: this.imageUrl }), this.render();
170
+ if (i) {
171
+ this.activeAnnotation = i, this.isDragging = !0, this.dragStartPoint = o, this.selectedHandleIndex = -1, this.dragStartAnnotation = JSON.parse(JSON.stringify(i)), this.emit("annotationChange", { action: "select", changedItem: i, imageUrl: this.imageUrl }), this.render();
172
172
  return;
173
173
  }
174
- this.startDrawing(i);
175
- } else s ? (this.activeAnnotation = s, this.isDragging = !0, this.dragStartPoint = i, this.selectedHandleIndex = -1, this.dragStartAnnotation = JSON.parse(JSON.stringify(s)), this.emit("annotationChange", { action: "select", changedItem: s, imageUrl: this.imageUrl }), this.render()) : (this.activeAnnotation = null, this.render());
176
- } else if (s) {
177
- if (!(this.visibleLabels.size > 0 && !this.visibleLabels.has(s.label))) {
178
- this.activeAnnotation = s, this.isDragging = !0, this.dragStartPoint = i, this.selectedHandleIndex = -1, this.dragStartAnnotation = JSON.parse(JSON.stringify(s)), this.emit("annotationChange", { action: "select", changedItem: s, imageUrl: this.imageUrl }), this.render();
174
+ this.startDrawing(o);
175
+ } else i ? (this.activeAnnotation = i, this.isDragging = !0, this.dragStartPoint = o, this.selectedHandleIndex = -1, this.dragStartAnnotation = JSON.parse(JSON.stringify(i)), this.emit("annotationChange", { action: "select", changedItem: i, imageUrl: this.imageUrl }), this.render()) : (this.activeAnnotation = null, this.render());
176
+ } else if (i) {
177
+ if (!(this.visibleLabels.size > 0 && !this.visibleLabels.has(i.label))) {
178
+ this.activeAnnotation = i, this.isDragging = !0, this.dragStartPoint = o, this.selectedHandleIndex = -1, this.dragStartAnnotation = JSON.parse(JSON.stringify(i)), this.emit("annotationChange", { action: "select", changedItem: i, imageUrl: this.imageUrl }), this.render();
179
179
  return;
180
180
  }
181
181
  } else
182
182
  this.activeAnnotation = null, this.render();
183
183
  }
184
184
  handleMouseMove(t) {
185
- const e = this.canvas.getBoundingClientRect(), n = t.clientX - e.left, a = t.clientY - e.top, i = this.toImageCoords(n, a);
185
+ const n = this.canvas.getBoundingClientRect(), e = t.clientX - n.left, a = t.clientY - n.top, o = this.toImageCoords(e, a);
186
186
  if (this.isPanning && this.panStartPoint) {
187
- const o = n - this.panStartPoint.x, s = a - this.panStartPoint.y;
188
- this.offset.x += o, this.offset.y += s, this.panStartPoint = { x: n, y: a }, this.render();
187
+ const r = e - this.panStartPoint.x, i = a - this.panStartPoint.y;
188
+ this.offset.x += r, this.offset.y += i, this.panStartPoint = { x: e, y: a }, this.render();
189
189
  return;
190
190
  }
191
- if (this.lastMouseMovePoint = i, this.isDrawing) {
191
+ if (this.lastMouseMovePoint = o, this.isDrawing) {
192
192
  if (this.currentTool === "polygon" && this.activeAnnotation) {
193
- const o = this.activeAnnotation.coordinates;
194
- if (o.points.length > 2) {
195
- const s = o.points[0], r = Z(i, s);
196
- this.isHoveringStartPoint = r < 20 / this.scale;
193
+ const r = this.activeAnnotation.coordinates;
194
+ if (r.points.length > 2) {
195
+ const i = r.points[0], h = Y(o, i);
196
+ this.isHoveringStartPoint = h < 20 / this.scale;
197
197
  } else
198
198
  this.isHoveringStartPoint = !1;
199
199
  }
200
- this.updateDrawing(i);
201
- } else this.isDragging && this.activeAnnotation && this.dragStartPoint ? this.updateDragging(i) : this.checkHover(n, a, i);
200
+ this.updateDrawing(o);
201
+ } else this.isDragging && this.activeAnnotation && this.dragStartPoint ? this.updateDragging(o) : this.checkHover(e, a, o);
202
202
  this.render();
203
203
  }
204
204
  handleMouseUp(t) {
@@ -221,17 +221,17 @@ class kt {
221
221
  }
222
222
  // --- 绘制逻辑 ---
223
223
  // 辅助函数:将 hex 转换为 rgba
224
- hexToRgba(t, e) {
224
+ hexToRgba(t, n) {
225
225
  if (!t.startsWith("#")) return t;
226
- const n = parseInt(t.slice(1, 3), 16), a = parseInt(t.slice(3, 5), 16), i = parseInt(t.slice(5, 7), 16);
227
- return `rgba(${n}, ${a}, ${i}, ${e})`;
226
+ const e = parseInt(t.slice(1, 3), 16), a = parseInt(t.slice(3, 5), 16), o = parseInt(t.slice(5, 7), 16);
227
+ return `rgba(${e}, ${a}, ${o}, ${n})`;
228
228
  }
229
229
  startDrawing(t) {
230
230
  if (!this.currentTool) return;
231
- const e = Date.now().toString();
231
+ const n = Date.now().toString();
232
232
  if (this.hexToRgba(this.currentLabelColor, 0.2), this.currentLabelColor, this.currentTool === "rectangle")
233
233
  this.isDrawing = !0, this.dragStartPoint = t, this.activeAnnotation = {
234
- id: e,
234
+ id: n,
235
235
  type: "rectangle",
236
236
  label: "",
237
237
  // 组件应填充此项
@@ -239,25 +239,25 @@ class kt {
239
239
  style: { strokeColor: this.currentLabelColor }
240
240
  };
241
241
  else if (this.currentTool === "point") {
242
- const n = {
243
- id: e,
242
+ const e = {
243
+ id: n,
244
244
  type: "point",
245
245
  label: "",
246
246
  coordinates: { points: [t] },
247
247
  style: { strokeColor: this.currentLabelColor }
248
248
  };
249
- this.annotations.push(n), this.emit("annotationChange", { action: "add", changedItem: n, imageUrl: this.imageUrl }), this.activeAnnotation = n;
249
+ this.annotations.push(e), this.emit("annotationChange", { action: "add", changedItem: e, imageUrl: this.imageUrl }), this.activeAnnotation = e;
250
250
  } else if (this.currentTool === "polygon")
251
251
  this.activeAnnotation && this.activeAnnotation.type === "polygon" && this.isDrawing ? this.activeAnnotation.coordinates.points.push(t) : (this.isDrawing = !0, this.activeAnnotation = {
252
- id: e,
252
+ id: n,
253
253
  type: "polygon",
254
254
  label: "",
255
255
  coordinates: { points: [t] },
256
256
  style: { strokeColor: this.currentLabelColor }
257
257
  });
258
258
  else if (this.currentTool === "category") {
259
- const n = {
260
- id: e,
259
+ const e = {
260
+ id: n,
261
261
  type: "category",
262
262
  label: "",
263
263
  // 将被填充
@@ -265,9 +265,9 @@ class kt {
265
265
  // 或位置?
266
266
  style: { strokeColor: this.currentLabelColor }
267
267
  };
268
- this.annotations.push(n), this.emit("annotationChange", { action: "add", changedItem: n, imageUrl: this.imageUrl }), this.activeAnnotation = n;
268
+ this.annotations.push(e), this.emit("annotationChange", { action: "add", changedItem: e, imageUrl: this.imageUrl }), this.activeAnnotation = e;
269
269
  } else this.currentTool === "rotatedRect" && (this.isDrawing = !0, this.dragStartPoint = t, this.activeAnnotation = {
270
- id: e,
270
+ id: n,
271
271
  type: "rotatedRect",
272
272
  label: "",
273
273
  coordinates: { x: t.x, y: t.y, width: 0, height: 0, angle: 0 },
@@ -277,11 +277,11 @@ class kt {
277
277
  updateDrawing(t) {
278
278
  if (this.activeAnnotation)
279
279
  if (this.activeAnnotation.type === "rectangle" && this.dragStartPoint) {
280
- const e = this.activeAnnotation.coordinates;
281
- e.x2 = t.x, e.y2 = t.y;
280
+ const n = this.activeAnnotation.coordinates;
281
+ n.x2 = t.x, n.y2 = t.y;
282
282
  } else if (this.activeAnnotation.type === "rotatedRect" && this.dragStartPoint) {
283
- const e = this.activeAnnotation.coordinates, n = Math.abs(t.x - this.dragStartPoint.x), a = Math.abs(t.y - this.dragStartPoint.y);
284
- e.width = n * 2, e.height = a * 2;
283
+ const n = this.activeAnnotation.coordinates, e = Math.abs(t.x - this.dragStartPoint.x), a = Math.abs(t.y - this.dragStartPoint.y);
284
+ n.width = e * 2, n.height = a * 2;
285
285
  } else this.activeAnnotation.type;
286
286
  }
287
287
  finishDrawing() {
@@ -292,8 +292,8 @@ class kt {
292
292
  this.activeAnnotation = null, this.isDrawing = !1;
293
293
  return;
294
294
  }
295
- const e = Math.min(t.x1, t.x2), n = Math.max(t.x1, t.x2), a = Math.min(t.y1, t.y2), i = Math.max(t.y1, t.y2);
296
- t.x1 = e, t.x2 = n, t.y1 = a, t.y2 = i, this.annotations.push(this.activeAnnotation), this.emit("annotationChange", { action: "add", changedItem: this.activeAnnotation, imageUrl: this.imageUrl });
295
+ const n = Math.min(t.x1, t.x2), e = Math.max(t.x1, t.x2), a = Math.min(t.y1, t.y2), o = Math.max(t.y1, t.y2);
296
+ t.x1 = n, t.x2 = e, t.y1 = a, t.y2 = o, this.annotations.push(this.activeAnnotation), this.emit("annotationChange", { action: "add", changedItem: this.activeAnnotation, imageUrl: this.imageUrl });
297
297
  } else if (this.activeAnnotation.type === "polygon") {
298
298
  if (this.activeAnnotation.coordinates.points.length < 3) {
299
299
  this.activeAnnotation = null, this.isDrawing = !1;
@@ -314,89 +314,89 @@ class kt {
314
314
  }
315
315
  updateDragging(t) {
316
316
  if (!this.activeAnnotation || !this.dragStartPoint || !this.dragStartAnnotation) return;
317
- const e = t.x - this.dragStartPoint.x, n = t.y - this.dragStartPoint.y;
318
- this.selectedHandleIndex === -1 ? this.moveAnnotation(this.activeAnnotation, this.dragStartAnnotation, e, n) : this.resizeAnnotation(this.activeAnnotation, this.dragStartAnnotation, this.selectedHandleIndex, t);
317
+ const n = t.x - this.dragStartPoint.x, e = t.y - this.dragStartPoint.y;
318
+ this.selectedHandleIndex === -1 ? this.moveAnnotation(this.activeAnnotation, this.dragStartAnnotation, n, e) : this.resizeAnnotation(this.activeAnnotation, this.dragStartAnnotation, this.selectedHandleIndex, t);
319
319
  }
320
- moveAnnotation(t, e, n, a) {
320
+ moveAnnotation(t, n, e, a) {
321
321
  if (t.type === "rectangle") {
322
- const i = e.coordinates, o = t.coordinates;
323
- o.x1 = i.x1 + n, o.x2 = i.x2 + n, o.y1 = i.y1 + a, o.y2 = i.y2 + a;
322
+ const o = n.coordinates, r = t.coordinates;
323
+ r.x1 = o.x1 + e, r.x2 = o.x2 + e, r.y1 = o.y1 + a, r.y2 = o.y2 + a;
324
324
  } else if (t.type === "point") {
325
- const i = e.coordinates, o = t.coordinates;
326
- o.points = i.points.map((s) => ({ x: s.x + n, y: s.y + a }));
325
+ const o = n.coordinates, r = t.coordinates;
326
+ r.points = o.points.map((i) => ({ x: i.x + e, y: i.y + a }));
327
327
  } else if (t.type === "rotatedRect") {
328
- const i = e.coordinates, o = t.coordinates;
329
- o.x = i.x + n, o.y = i.y + a;
328
+ const o = n.coordinates, r = t.coordinates;
329
+ r.x = o.x + e, r.y = o.y + a;
330
330
  } else if (t.type === "polygon") {
331
- const i = e.coordinates, o = t.coordinates;
332
- o.points = i.points.map((s) => ({ x: s.x + n, y: s.y + a }));
331
+ const o = n.coordinates, r = t.coordinates;
332
+ r.points = o.points.map((i) => ({ x: i.x + e, y: i.y + a }));
333
333
  }
334
334
  }
335
- resizeAnnotation(t, e, n, a) {
335
+ resizeAnnotation(t, n, e, a) {
336
336
  if (t.type === "rectangle") {
337
- const i = t.coordinates;
338
- n === 0 && (i.x1 = a.x, i.y1 = a.y), n === 1 && (i.x2 = a.x, i.y1 = a.y), n === 2 && (i.x2 = a.x, i.y2 = a.y), n === 3 && (i.x1 = a.x, i.y2 = a.y);
337
+ const o = t.coordinates;
338
+ e === 0 && (o.x1 = a.x, o.y1 = a.y), e === 1 && (o.x2 = a.x, o.y1 = a.y), e === 2 && (o.x2 = a.x, o.y2 = a.y), e === 3 && (o.x1 = a.x, o.y2 = a.y);
339
339
  } else if (t.type === "polygon") {
340
- const i = t.coordinates;
341
- n >= 0 && n < i.points.length && (i.points[n] = a);
340
+ const o = t.coordinates;
341
+ e >= 0 && e < o.points.length && (o.points[e] = a);
342
342
  } else if (t.type === "point") {
343
- const i = t.coordinates;
344
- n >= 0 && n < i.points.length && (i.points[n] = a);
343
+ const o = t.coordinates;
344
+ e >= 0 && e < o.points.length && (o.points[e] = a);
345
345
  } else if (t.type === "rotatedRect") {
346
- const i = t.coordinates;
347
- if (n === -2) {
348
- const o = i.x, s = i.y, r = a.x - o, v = a.y - s;
349
- let d = Math.atan2(v, r) * 180 / Math.PI;
350
- d += 90, i.angle = d;
346
+ const o = t.coordinates;
347
+ if (e === -2) {
348
+ const r = o.x, i = o.y, h = a.x - r, m = a.y - i;
349
+ let g = Math.atan2(m, h) * 180 / Math.PI;
350
+ g += 90, o.angle = g;
351
351
  } else {
352
- const o = i.angle * Math.PI / 180, s = Math.cos(-o), r = Math.sin(-o), v = a.x - i.x, d = a.y - i.y, g = v * s - d * r, f = v * r + d * s;
353
- (n === 0 || n === 3) && (i.width / 2, i.width = Math.abs(g) * 2), (n === 1 || n === 2) && (i.width = Math.abs(g) * 2), (n === 0 || n === 1) && (i.height = Math.abs(f) * 2), (n === 2 || n === 3) && (i.height = Math.abs(f) * 2);
352
+ const r = o.angle * Math.PI / 180, i = Math.cos(-r), h = Math.sin(-r), m = a.x - o.x, g = a.y - o.y, u = m * i - g * h, f = m * h + g * i;
353
+ (e === 0 || e === 3) && (o.width / 2, o.width = Math.abs(u) * 2), (e === 1 || e === 2) && (o.width = Math.abs(u) * 2), (e === 0 || e === 1) && (o.height = Math.abs(f) * 2), (e === 2 || e === 3) && (o.height = Math.abs(f) * 2);
354
354
  }
355
355
  }
356
356
  }
357
357
  // --- 命中测试和渲染辅助函数 ---
358
358
  getHitAnnotation(t) {
359
- for (let e = this.annotations.length - 1; e >= 0; e--) {
360
- const n = this.annotations[e];
361
- if (this.isPointInAnnotation(t, n))
362
- return n;
359
+ for (let n = this.annotations.length - 1; n >= 0; n--) {
360
+ const e = this.annotations[n];
361
+ if (this.isPointInAnnotation(t, e))
362
+ return e;
363
363
  }
364
364
  return null;
365
365
  }
366
- isPointInAnnotation(t, e) {
367
- if (e.type === "rectangle") {
368
- const n = e.coordinates;
369
- return t.x >= n.x1 && t.x <= n.x2 && t.y >= n.y1 && t.y <= n.y2;
370
- } else if (e.type === "polygon") {
371
- const n = e.coordinates;
372
- return _t(t, n.points);
373
- } else if (e.type === "rotatedRect") {
374
- const n = e.coordinates, a = nt(t, { x: n.x, y: n.y }, -n.angle), i = n.width / 2, o = n.height / 2;
375
- return a.x >= n.x - i && a.x <= n.x + i && a.y >= n.y - o && a.y <= n.y + o;
376
- } else if (e.type === "point")
377
- return e.coordinates.points.some((a) => Z(t, a) < 10 / this.scale);
366
+ isPointInAnnotation(t, n) {
367
+ if (n.type === "rectangle") {
368
+ const e = n.coordinates;
369
+ return t.x >= e.x1 && t.x <= e.x2 && t.y >= e.y1 && t.y <= e.y2;
370
+ } else if (n.type === "polygon") {
371
+ const e = n.coordinates;
372
+ return Ht(t, e.points);
373
+ } else if (n.type === "rotatedRect") {
374
+ const e = n.coordinates, a = st(t, { x: e.x, y: e.y }, -e.angle), o = e.width / 2, r = e.height / 2;
375
+ return a.x >= e.x - o && a.x <= e.x + o && a.y >= e.y - r && a.y <= e.y + r;
376
+ } else if (n.type === "point")
377
+ return n.coordinates.points.some((a) => Y(t, a) < 10 / this.scale);
378
378
  return !1;
379
379
  }
380
- getHitHandle(t, e, n) {
381
- const a = this.getAnnotationHandles(n), i = 6;
382
- for (let o = 0; o < a.length; o++) {
383
- const s = a[o], r = this.toScreenCoords(s.x, s.y);
384
- if (Math.abs(t - r.x) < i && Math.abs(e - r.y) < i)
385
- return n.type === "rotatedRect" && o === 4 ? -2 : o;
380
+ getHitHandle(t, n, e) {
381
+ const a = this.getAnnotationHandles(e), o = 6;
382
+ for (let r = 0; r < a.length; r++) {
383
+ const i = a[r], h = this.toScreenCoords(i.x, i.y);
384
+ if (Math.abs(t - h.x) < o && Math.abs(n - h.y) < o)
385
+ return e.type === "rotatedRect" && r === 4 ? -2 : r;
386
386
  }
387
387
  return -100;
388
388
  }
389
389
  getAnnotationHandles(t) {
390
390
  if (t.type === "rectangle") {
391
- const e = t.coordinates;
391
+ const n = t.coordinates;
392
392
  return [
393
- { x: e.x1, y: e.y1 },
393
+ { x: n.x1, y: n.y1 },
394
394
  // 左上
395
- { x: e.x2, y: e.y1 },
395
+ { x: n.x2, y: n.y1 },
396
396
  // 右上
397
- { x: e.x2, y: e.y2 },
397
+ { x: n.x2, y: n.y2 },
398
398
  // 右下
399
- { x: e.x1, y: e.y2 }
399
+ { x: n.x1, y: n.y2 }
400
400
  // 左下
401
401
  ];
402
402
  } else {
@@ -405,24 +405,24 @@ class kt {
405
405
  if (t.type === "point")
406
406
  return t.coordinates.points;
407
407
  if (t.type === "rotatedRect") {
408
- const e = t.coordinates, n = { x: e.x, y: e.y }, a = e.width / 2, i = e.height / 2, o = { x: e.x - a, y: e.y - i }, s = { x: e.x + a, y: e.y - i }, r = { x: e.x + a, y: e.y + i }, v = { x: e.x - a, y: e.y + i }, d = { x: e.x, y: e.y - i - 20 / this.scale };
409
- return [o, s, r, v, d].map((g) => nt(g, n, e.angle));
408
+ const n = t.coordinates, e = { x: n.x, y: n.y }, a = n.width / 2, o = n.height / 2, r = { x: n.x - a, y: n.y - o }, i = { x: n.x + a, y: n.y - o }, h = { x: n.x + a, y: n.y + o }, m = { x: n.x - a, y: n.y + o }, g = { x: n.x, y: n.y - o - 20 / this.scale };
409
+ return [r, i, h, m, g].map((u) => st(u, e, n.angle));
410
410
  }
411
411
  }
412
412
  return [];
413
413
  }
414
- checkHover(t, e, n) {
415
- const a = this.getHitCategory(t, e);
414
+ checkHover(t, n, e) {
415
+ const a = this.getHitCategory(t, n);
416
416
  if (a) {
417
417
  this.canvas.style.cursor = "pointer", this.hoverAnnotation = a;
418
418
  return;
419
419
  }
420
- if (this.activeAnnotation && this.getHitHandle(t, e, this.activeAnnotation) !== -100) {
420
+ if (this.activeAnnotation && this.getHitHandle(t, n, this.activeAnnotation) !== -100) {
421
421
  this.canvas.style.cursor = "pointer";
422
422
  return;
423
423
  }
424
- const i = this.getHitAnnotation(n);
425
- i ? (this.canvas.style.cursor = "move", this.hoverAnnotation = i) : (this.canvas.style.cursor = "default", this.hoverAnnotation = null);
424
+ const o = this.getHitAnnotation(e);
425
+ o ? (this.canvas.style.cursor = "move", this.hoverAnnotation = o) : (this.canvas.style.cursor = "default", this.hoverAnnotation = null);
426
426
  }
427
427
  render() {
428
428
  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((t) => {
@@ -430,105 +430,158 @@ class kt {
430
430
  }), this.activeAnnotation && this.drawItem(this.activeAnnotation, !0), this.renderCategories();
431
431
  }
432
432
  renderCategories() {
433
- const t = this.annotations.filter((r) => r.type === "category");
433
+ const t = this.annotations.filter((h) => h.type === "category");
434
434
  if (t.length === 0) return;
435
435
  this.ctx.save(), this.ctx.font = "14px sans-serif", this.ctx.textBaseline = "top";
436
- let e = 10;
437
- const n = 10, a = 8, i = 4, o = 24, s = 8;
438
- t.forEach((r) => {
439
- const v = r.label || "Unlabeled", d = this.ctx.measureText(v).width + a * 2, g = this.activeAnnotation === r, f = this.hoverAnnotation === r;
440
- this.ctx.fillStyle = g ? "#E3F2FD" : f ? "#F5F5F5" : "rgba(255, 255, 255, 0.9)", this.ctx.strokeStyle = g ? "#2196F3" : "#666", this.ctx.lineWidth = g ? 2 : 1, this.ctx.beginPath(), this.ctx.rect(e, n, d, o), this.ctx.fill(), this.ctx.stroke(), this.ctx.fillStyle = g ? "#1976D2" : "#333", this.ctx.fillText(v, e + a, n + i), e += d + s;
436
+ let n = 10;
437
+ const e = 10, a = 8, o = 4, r = 24, i = 8;
438
+ t.forEach((h) => {
439
+ const m = h.label || "Unlabeled", g = this.ctx.measureText(m).width + a * 2, u = this.activeAnnotation === h, f = this.hoverAnnotation === h;
440
+ this.ctx.fillStyle = u ? "#E3F2FD" : f ? "#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(n, e, g, r), this.ctx.fill(), this.ctx.stroke(), this.ctx.fillStyle = u ? "#1976D2" : "#333", this.ctx.fillText(m, n + a, e + o), n += g + i;
441
441
  }), this.ctx.restore();
442
442
  }
443
- getHitCategory(t, e) {
444
- const n = this.annotations.filter((d) => d.type === "category");
445
- if (n.length === 0) return null;
443
+ getHitCategory(t, n) {
444
+ const e = this.annotations.filter((g) => g.type === "category");
445
+ if (e.length === 0) return null;
446
446
  this.ctx.save(), this.ctx.font = "14px sans-serif";
447
447
  let a = 10;
448
- const i = 10, o = 8, s = 24, r = 8;
449
- let v = null;
450
- for (const d of n) {
451
- const g = d.label || "Unlabeled", f = this.ctx.measureText(g).width + o * 2;
452
- if (t >= a && t <= a + f && e >= i && e <= i + s) {
453
- v = d;
448
+ const o = 10, r = 8, i = 24, h = 8;
449
+ let m = null;
450
+ for (const g of e) {
451
+ const u = g.label || "Unlabeled", f = this.ctx.measureText(u).width + r * 2;
452
+ if (t >= a && t <= a + f && n >= o && n <= o + i) {
453
+ m = g;
454
454
  break;
455
455
  }
456
- a += f + r;
456
+ a += f + h;
457
457
  }
458
- return this.ctx.restore(), v;
458
+ return this.ctx.restore(), m;
459
459
  }
460
- drawItem(t, e) {
461
- var i;
462
- if (this.visibleLabels.size > 0 && !this.visibleLabels.has(t.label) && !e)
460
+ drawItem(t, n) {
461
+ var o;
462
+ if (this.visibleLabels.size > 0 && !this.visibleLabels.has(t.label) && !n)
463
463
  return;
464
464
  this.ctx.save();
465
- const n = ((i = t.style) == null ? void 0 : i.strokeColor) || "#FF4081", a = e ? "#00E5FF" : n;
466
- if (this.ctx.strokeStyle = a, this.ctx.lineWidth = 2, e ? this.ctx.fillStyle = "rgba(0, 229, 255, 0.2)" : this.ctx.fillStyle = this.hexToRgba(n, 0.2), t.type === "rectangle") {
467
- const o = t.coordinates, s = this.toScreenCoords(o.x1, o.y1), r = this.toScreenCoords(o.x2, o.y2), v = Math.min(s.x, r.x), d = Math.min(s.y, r.y), g = Math.abs(s.x - r.x), f = Math.abs(s.y - r.y);
468
- this.ctx.strokeRect(v, d, g, f), this.ctx.fillStyle = e ? "rgba(0, 229, 255, 0.2)" : "rgba(255, 64, 129, 0.2)", this.ctx.fillRect(v, d, g, f), e && this.drawHandles(this.getAnnotationHandles(t));
465
+ const e = ((o = t.style) == null ? void 0 : o.strokeColor) || "#FF4081", a = n ? "#00E5FF" : e;
466
+ if (this.ctx.strokeStyle = a, this.ctx.lineWidth = 2, n ? this.ctx.fillStyle = "rgba(0, 229, 255, 0.2)" : this.ctx.fillStyle = this.hexToRgba(e, 0.2), t.type === "rectangle") {
467
+ const r = t.coordinates, i = this.toScreenCoords(r.x1, r.y1), h = this.toScreenCoords(r.x2, r.y2), m = Math.min(i.x, h.x), g = Math.min(i.y, h.y), u = Math.abs(i.x - h.x), f = Math.abs(i.y - h.y);
468
+ this.ctx.strokeRect(m, g, u, f), this.ctx.fillStyle = n ? "rgba(0, 229, 255, 0.2)" : "rgba(255, 64, 129, 0.2)", this.ctx.fillRect(m, g, u, f), n && this.drawHandles(this.getAnnotationHandles(t));
469
469
  } else if (t.type === "polygon") {
470
- const o = t.coordinates;
471
- if (o.points.length === 0) {
470
+ const r = t.coordinates;
471
+ if (r.points.length === 0) {
472
472
  this.ctx.restore();
473
473
  return;
474
474
  }
475
475
  this.ctx.beginPath();
476
- const s = this.toScreenCoords(o.points[0].x, o.points[0].y);
477
- this.ctx.moveTo(s.x, s.y);
478
- for (let r = 1; r < o.points.length; r++) {
479
- const v = this.toScreenCoords(o.points[r].x, o.points[r].y);
480
- this.ctx.lineTo(v.x, v.y);
476
+ const i = this.toScreenCoords(r.points[0].x, r.points[0].y);
477
+ this.ctx.moveTo(i.x, i.y);
478
+ for (let h = 1; h < r.points.length; h++) {
479
+ const m = this.toScreenCoords(r.points[h].x, r.points[h].y);
480
+ this.ctx.lineTo(m.x, m.y);
481
481
  }
482
482
  if (!this.isDrawing || t !== this.activeAnnotation)
483
483
  this.ctx.closePath();
484
484
  else if (this.lastMouseMovePoint) {
485
- let r = this.lastMouseMovePoint;
486
- if (this.isHoveringStartPoint && o.points.length > 0) {
487
- r = o.points[0];
488
- const d = this.toScreenCoords(o.points[0].x, o.points[0].y);
489
- this.ctx.save(), this.ctx.beginPath(), this.ctx.arc(d.x, d.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();
485
+ let h = this.lastMouseMovePoint;
486
+ if (this.isHoveringStartPoint && r.points.length > 0) {
487
+ h = r.points[0];
488
+ const g = this.toScreenCoords(r.points[0].x, r.points[0].y);
489
+ this.ctx.save(), this.ctx.beginPath(), this.ctx.arc(g.x, g.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();
490
490
  }
491
- const v = this.toScreenCoords(r.x, r.y);
492
- this.ctx.lineTo(v.x, v.y);
491
+ const m = this.toScreenCoords(h.x, h.y);
492
+ this.ctx.lineTo(m.x, m.y);
493
493
  }
494
- this.ctx.stroke(), this.ctx.fillStyle = e ? "rgba(0, 229, 255, 0.2)" : "rgba(255, 64, 129, 0.2)", this.ctx.fill(), e && this.drawHandles(this.getAnnotationHandles(t));
494
+ this.ctx.stroke(), this.ctx.fillStyle = n ? "rgba(0, 229, 255, 0.2)" : "rgba(255, 64, 129, 0.2)", this.ctx.fill(), n && this.drawHandles(this.getAnnotationHandles(t));
495
495
  } else if (t.type === "rotatedRect") {
496
- const o = t.coordinates;
497
- this.ctx.translate(this.toScreenCoords(o.x, o.y).x, this.toScreenCoords(o.x, o.y).y), this.ctx.rotate(o.angle * Math.PI / 180);
498
- const s = o.width * this.scale, r = o.height * this.scale;
499
- this.ctx.strokeRect(-s / 2, -r / 2, s, r), this.ctx.fillStyle = e ? "rgba(0, 229, 255, 0.2)" : "rgba(255, 64, 129, 0.2)", this.ctx.fillRect(-s / 2, -r / 2, s, r), this.ctx.rotate(-o.angle * Math.PI / 180), this.ctx.translate(-this.toScreenCoords(o.x, o.y).x, -this.toScreenCoords(o.x, o.y).y), e && this.drawHandles(this.getAnnotationHandles(t));
500
- } else t.type === "point" && t.coordinates.points.forEach((s) => {
501
- const r = this.toScreenCoords(s.x, s.y);
502
- this.ctx.beginPath(), this.ctx.arc(r.x, r.y, 5, 0, Math.PI * 2), this.ctx.fillStyle = e ? "#00E5FF" : n, this.ctx.fill(), this.ctx.stroke();
496
+ const r = t.coordinates;
497
+ this.ctx.translate(this.toScreenCoords(r.x, r.y).x, this.toScreenCoords(r.x, r.y).y), this.ctx.rotate(r.angle * Math.PI / 180);
498
+ const i = r.width * this.scale, h = r.height * this.scale;
499
+ this.ctx.strokeRect(-i / 2, -h / 2, i, h), this.ctx.fillStyle = n ? "rgba(0, 229, 255, 0.2)" : "rgba(255, 64, 129, 0.2)", this.ctx.fillRect(-i / 2, -h / 2, i, h), this.ctx.rotate(-r.angle * Math.PI / 180), this.ctx.translate(-this.toScreenCoords(r.x, r.y).x, -this.toScreenCoords(r.x, r.y).y), n && this.drawHandles(this.getAnnotationHandles(t));
500
+ } else t.type === "point" && t.coordinates.points.forEach((i) => {
501
+ const h = this.toScreenCoords(i.x, i.y);
502
+ this.ctx.beginPath(), this.ctx.arc(h.x, h.y, 5, 0, Math.PI * 2), this.ctx.fillStyle = n ? "#00E5FF" : e, this.ctx.fill(), this.ctx.stroke();
503
503
  });
504
504
  this.ctx.restore();
505
505
  }
506
506
  drawHandles(t) {
507
- this.ctx.fillStyle = "#FFFFFF", this.ctx.strokeStyle = "#000000", this.ctx.lineWidth = 1, t.forEach((e) => {
508
- const n = this.toScreenCoords(e.x, e.y);
509
- this.ctx.fillRect(n.x - 4, n.y - 4, 8, 8), this.ctx.strokeRect(n.x - 4, n.y - 4, 8, 8);
507
+ this.ctx.fillStyle = "#FFFFFF", this.ctx.strokeStyle = "#000000", this.ctx.lineWidth = 1, t.forEach((n) => {
508
+ const e = this.toScreenCoords(n.x, n.y);
509
+ this.ctx.fillRect(e.x - 4, e.y - 4, 8, 8), this.ctx.strokeRect(e.x - 4, e.y - 4, 8, 8);
510
510
  });
511
511
  }
512
512
  }
513
- const St = {
513
+ const Lt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
514
+ <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
515
+ </svg>`, Tt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
516
+ <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
517
+ </svg>`, $t = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
518
+ <path d="M704 192h160v160h-160z m-64-64v288h288V128H640zM160 672h160v160H160z m-64-64v288h288V608H96z m256-320h320v64H352z" fill="currentColor"/>\r
519
+ </svg>`, Dt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
520
+ <path d="M256 256h512v512H256z m-64-64v640h640V192H192z" fill="currentColor"/>\r
521
+ </svg>`, Rt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
522
+ <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
523
+ </svg>`, Ut = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
524
+ <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
525
+ </svg>`, Ft = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
526
+ <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
527
+ </svg>`, Bt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
528
+ <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
529
+ </svg>`, Ot = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
530
+ <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
531
+ </svg>`, Et = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
532
+ <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
533
+ </svg>`, Vt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
534
+ <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
535
+ </svg>`, Nt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
536
+ <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
537
+ </svg>`, Jt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
538
+ <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
539
+ </svg>`, jt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
540
+ <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
541
+ </svg>`, Wt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
542
+ <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
543
+ </svg>`, qt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
544
+ <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
545
+ </svg>`, Xt = ["innerHTML"], Yt = /* @__PURE__ */ N({
546
+ __name: "SvgIcon",
547
+ props: {
548
+ name: {},
549
+ size: {}
550
+ },
551
+ setup(v) {
552
+ const t = v, n = S(""), e = /* @__PURE__ */ Object.assign({ "../assets/svg/aim.svg": Lt, "../assets/svg/back.svg": Tt, "../assets/svg/connection.svg": $t, "../assets/svg/crop.svg": Dt, "../assets/svg/delete.svg": Rt, "../assets/svg/download.svg": Ut, "../assets/svg/edit.svg": Ft, "../assets/svg/hide.svg": Bt, "../assets/svg/pointer.svg": Ot, "../assets/svg/price-tag.svg": Et, "../assets/svg/rank.svg": Vt, "../assets/svg/refresh-right.svg": Nt, "../assets/svg/right.svg": Jt, "../assets/svg/view.svg": jt, "../assets/svg/zoom-in.svg": Wt, "../assets/svg/zoom-out.svg": qt });
553
+ return St(() => {
554
+ const a = `../assets/svg/${t.name}.svg`, o = e[a];
555
+ o ? n.value = o : (console.warn(`Icon ${t.name} not found at path ${a}`), n.value = "");
556
+ }), (a, o) => (x(), b("i", {
557
+ class: $(["svg-icon", [v.size ? `size-${v.size}` : ""]]),
558
+ innerHTML: n.value
559
+ }, null, 10, Xt));
560
+ }
561
+ }), J = (v, t) => {
562
+ const n = v.__vccOpts || v;
563
+ for (const [e, a] of t)
564
+ n[e] = a;
565
+ return n;
566
+ }, M = /* @__PURE__ */ J(Yt, [["__scopeId", "data-v-3928607b"]]), Kt = {
514
567
  key: 0,
515
568
  class: "left-sidebar"
516
- }, It = ["onClick", "title"], Pt = { class: "center-area" }, Dt = {
569
+ }, Zt = ["onClick", "title"], Gt = { class: "center-area" }, Qt = {
517
570
  key: 0,
518
571
  class: "top-bar"
519
- }, Tt = { class: "label-selector" }, Ht = { class: "tags-row" }, Lt = ["onClick"], Mt = {
572
+ }, te = { class: "label-selector" }, ee = { class: "tags-row" }, ne = ["onClick"], se = {
520
573
  key: 0,
521
574
  class: "no-labels"
522
- }, $t = {
575
+ }, ie = {
523
576
  key: 1,
524
577
  class: "batch-nav"
525
- }, Rt = ["disabled"], Ut = ["disabled"], Ft = {
578
+ }, oe = ["disabled"], ae = ["disabled"], le = {
526
579
  key: 1,
527
580
  class: "right-sidebar"
528
- }, Ot = { class: "label-list" }, Et = { class: "label-row" }, zt = ["onUpdate:modelValue", "onChange"], Bt = ["title"], Nt = ["onClick"], Jt = { class: "action-icon more-actions" }, Wt = ["onClick"], Vt = {
581
+ }, re = { class: "label-list" }, ce = { class: "label-row" }, he = ["onUpdate:modelValue", "onChange"], de = ["title"], ge = ["onClick"], ve = { class: "action-icon more-actions" }, ue = ["onClick"], me = {
529
582
  key: 2,
530
583
  class: "modal-overlay"
531
- }, Xt = { class: "modal-content" }, jt = { class: "form-group" }, Yt = { class: "form-group" }, Zt = { class: "color-input-wrapper" }, Kt = /* @__PURE__ */ q({
584
+ }, fe = { class: "modal-content" }, ye = { class: "form-group" }, pe = { class: "form-group" }, xe = { class: "color-input-wrapper" }, be = /* @__PURE__ */ N({
532
585
  __name: "ImageAnnotator",
533
586
  props: {
534
587
  annotationTypes: { default: () => ["rectangle", "polygon", "point", "rotatedRect"] },
@@ -536,403 +589,494 @@ const St = {
536
589
  labels: { default: () => [] },
537
590
  defaultActiveType: {},
538
591
  theme: { default: "light" },
539
- readOnly: { type: Boolean, default: !1 }
592
+ readOnly: { type: Boolean, default: !1 },
593
+ image: {},
594
+ predictionCandidates: {},
595
+ reviewMode: {},
596
+ session: {},
597
+ requestId: {},
598
+ minZoom: {},
599
+ maxZoom: {}
540
600
  },
541
- emits: ["annotationChange", "batchChange", "labelChange"],
542
- setup(u, { expose: t, emit: e }) {
543
- const n = u, a = e, i = k(null), o = k(null), s = k(null), r = k(null), v = k(0), d = k([]), g = k(""), f = k(!1), y = k({ name: "", color: "#FF0000" }), _ = bt(() => n.annotationTypes.filter((l) => l !== "category")), S = (l) => ({
544
- rectangle: "Crop",
545
- polygon: "Connection",
546
- point: "Aim",
547
- rotatedRect: "RefreshRight",
548
- category: "PriceTag"
549
- })[l] || l, O = (l) => ({
601
+ emits: ["annotationChange", "batchChange", "labelChange", "ready", "error", "tool:change", "viewport:change", "annotation:add", "annotation:update", "annotation:delete", "annotation:select", "prediction:request", "prediction:loaded", "prediction:apply", "prediction:reject", "review:action", "qa:issue"],
602
+ setup(v, { expose: t, emit: n }) {
603
+ const e = v, a = n, o = S(null), r = S(null), i = S(null), h = S(null), m = S(0), g = S([]), u = S(""), f = S(!1), p = S({ name: "", color: "#FF0000" }), w = S("none"), k = S([]), I = () => {
604
+ var c, y, _, A;
605
+ const s = e.batchImages[m.value], l = (s == null ? void 0 : s.imageUrl) || ((c = e.image) == null ? void 0 : c.url);
606
+ return {
607
+ eventId: `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`,
608
+ timestamp: Date.now(),
609
+ requestId: e.requestId,
610
+ taskId: (y = e.session) == null ? void 0 : y.taskId,
611
+ imageId: ((_ = e.image) == null ? void 0 : _.id) || l,
612
+ operator: (A = e.session) == null ? void 0 : A.userId
613
+ };
614
+ }, R = (s) => {
615
+ var y;
616
+ const l = s == null ? void 0 : s.action;
617
+ if (!l) return;
618
+ const c = {
619
+ meta: I(),
620
+ action: l,
621
+ current: s == null ? void 0 : s.changedItem,
622
+ source: (y = s == null ? void 0 : s.changedItem) != null && y.predictionId ? "prediction" : "manual"
623
+ };
624
+ l === "add" && a("annotation:add", c), l === "update" && a("annotation:update", c), l === "delete" && a("annotation:delete", c), l === "select" && a("annotation:select", c);
625
+ }, Z = kt(() => e.annotationTypes.filter((s) => s !== "category")), it = (s) => ({
626
+ rectangle: "crop",
627
+ polygon: "connection",
628
+ point: "aim",
629
+ rotatedRect: "refresh-right",
630
+ category: "price-tag"
631
+ })[s] || s, ot = (s) => ({
550
632
  rectangle: "矩形框",
551
633
  polygon: "多边形",
552
634
  point: "关键点",
553
635
  rotatedRect: "旋转矩形",
554
636
  category: "分类标签"
555
- })[l] || l;
556
- At(() => {
557
- if (i.value) {
558
- s.value = new kt(i.value), s.value.on("annotationChange", (c) => {
559
- if (c.action === "add" && c.changedItem) {
560
- const A = d.value.find((w) => w.id === g.value);
561
- A && (c.changedItem.label = A.name);
637
+ })[s] || s;
638
+ Mt(() => {
639
+ if (o.value) {
640
+ i.value = new Pt(o.value), i.value.on("annotationChange", (l) => {
641
+ if (l.action === "add" && l.changedItem) {
642
+ const c = g.value.find((y) => y.id === u.value);
643
+ c && (l.changedItem.label = c.name, l.changedItem.labelId = c.id);
562
644
  }
563
- a("annotationChange", c);
564
- }), R(), M();
565
- const l = new ResizeObserver(() => {
566
- var c;
567
- (c = s.value) == null || c.resize();
645
+ a("annotationChange", l), R(l);
646
+ }), U(), E();
647
+ const s = new ResizeObserver(() => {
648
+ var l;
649
+ (l = i.value) == null || l.resize();
568
650
  });
569
- o.value && l.observe(o.value);
651
+ r.value && s.observe(r.value), e.defaultActiveType && F(e.defaultActiveType), a("ready", { meta: I() });
570
652
  }
571
653
  });
572
- const M = () => {
573
- if (!s.value) return;
574
- const l = d.value.find((A) => A.id === g.value);
575
- l && s.value.setLabelStyle(l.color);
576
- const c = d.value.filter((A) => A.visible).map((A) => A.name);
577
- s.value.setVisibleLabels(c);
578
- }, R = () => {
579
- if (s.value && n.batchImages.length > 0) {
580
- const l = n.batchImages[v.value];
581
- s.value.loadImage(l.imageUrl), l.annotations && s.value.setAnnotations(l.annotations);
582
- }
583
- }, E = (l) => {
584
- var c, A;
585
- if (r.value = l, l !== "pan" && l !== "select" && d.value.length === 0) {
654
+ const E = () => {
655
+ if (!i.value) return;
656
+ const s = g.value.find((c) => c.id === u.value);
657
+ s && i.value.setLabelStyle(s.color);
658
+ const l = g.value.filter((c) => c.visible).map((c) => c.name);
659
+ i.value.setVisibleLabels(l);
660
+ }, U = () => {
661
+ var s;
662
+ if (i.value)
663
+ if (e.batchImages.length > 0) {
664
+ const l = e.batchImages[m.value];
665
+ i.value.loadImage(l.imageUrl), l.annotations ? i.value.setAnnotations(l.annotations) : i.value.setAnnotations([]);
666
+ } else (s = e.image) != null && s.url && i.value.loadImage(e.image.url);
667
+ }, F = (s) => {
668
+ var l, c;
669
+ if (h.value = s, s !== "pan" && s !== "select" && g.value.length === 0) {
586
670
  alert("请先创建标签!");
587
671
  return;
588
672
  }
589
- l === "pan" || l === "select" ? (c = s.value) == null || c.setTool(l) : (A = s.value) == null || A.setTool(l);
590
- }, H = () => {
591
- var l;
592
- (l = s.value) != null && l.activeAnnotation && s.value.deleteAnnotation(s.value.activeAnnotation.id);
593
- }, z = () => {
594
- var l;
595
- return (l = s.value) == null ? void 0 : l.zoom(1);
673
+ s === "pan" || s === "select" ? (l = i.value) == null || l.setTool(s) : (c = i.value) == null || c.setTool(s), a("tool:change", { meta: I(), tool: s });
674
+ }, at = () => {
675
+ var s;
676
+ (s = i.value) != null && s.activeAnnotation && i.value.deleteAnnotation(i.value.activeAnnotation.id);
677
+ }, G = () => {
678
+ i.value && a("viewport:change", {
679
+ meta: I(),
680
+ scale: i.value.scale,
681
+ offset: { ...i.value.offset }
682
+ });
683
+ }, lt = () => {
684
+ var s;
685
+ (s = i.value) == null || s.zoom(1), G();
686
+ }, rt = () => {
687
+ var s;
688
+ (s = i.value) == null || s.zoom(-1), G();
689
+ }, ct = () => {
690
+ p.value = { name: "", color: "#2196F3" }, f.value = !0;
596
691
  }, Q = () => {
597
- var l;
598
- return (l = s.value) == null ? void 0 : l.zoom(-1);
599
- }, st = () => {
600
- y.value = { name: "", color: "#2196F3" }, f.value = !0;
601
- }, tt = () => {
602
692
  f.value = !1;
603
- }, ot = () => {
604
- if (!y.value.name.trim()) {
693
+ }, ht = () => {
694
+ if (!p.value.name.trim()) {
605
695
  alert("请输入标签名称");
606
696
  return;
607
697
  }
608
- const c = {
698
+ const l = {
609
699
  id: Date.now().toString(),
610
- name: y.value.name,
611
- color: y.value.color,
700
+ name: p.value.name,
701
+ color: p.value.color,
612
702
  visible: !0
613
703
  };
614
- d.value.push(c), a("labelChange", d.value), d.value.length === 1 && B(c), tt();
615
- }, B = (l) => {
616
- var c;
617
- g.value = l.id, (c = s.value) == null || c.setLabelStyle(l.color);
618
- }, at = (l, c) => {
619
- if (!l.startsWith("#")) return l;
620
- let A = 0, w = 0, T = 0;
621
- return l.length === 4 ? (A = parseInt(l[1] + l[1], 16), w = parseInt(l[2] + l[2], 16), T = parseInt(l[3] + l[3], 16)) : l.length === 7 && (A = parseInt(l.slice(1, 3), 16), w = parseInt(l.slice(3, 5), 16), T = parseInt(l.slice(5, 7), 16)), `rgba(${A}, ${w}, ${T}, ${c})`;
622
- }, lt = (l) => {
623
- var c;
624
- if (l.id === g.value && ((c = s.value) == null || c.setLabelStyle(l.color)), s.value) {
625
- const A = s.value.getAnnotations();
626
- let w = !1;
627
- A.forEach((T) => {
628
- T.label === l.name && (T.style || (T.style = {}), T.style.strokeColor = l.color, T.style.fillColor = at(l.color, 0.2), w = !0);
629
- }), w && s.value.render();
704
+ g.value.push(l), a("labelChange", g.value), g.value.length === 1 && B(l), Q();
705
+ }, B = (s) => {
706
+ var l;
707
+ u.value = s.id, (l = i.value) == null || l.setLabelStyle(s.color);
708
+ }, dt = (s, l) => {
709
+ if (!s.startsWith("#")) return s;
710
+ let c = 0, y = 0, _ = 0;
711
+ return s.length === 4 ? (c = parseInt(s[1] + s[1], 16), y = parseInt(s[2] + s[2], 16), _ = parseInt(s[3] + s[3], 16)) : s.length === 7 && (c = parseInt(s.slice(1, 3), 16), y = parseInt(s.slice(3, 5), 16), _ = parseInt(s.slice(5, 7), 16)), `rgba(${c}, ${y}, ${_}, ${l})`;
712
+ }, gt = (s) => {
713
+ var l;
714
+ if (s.id === u.value && ((l = i.value) == null || l.setLabelStyle(s.color)), i.value) {
715
+ const c = i.value.getAnnotations();
716
+ let y = !1;
717
+ c.forEach((_) => {
718
+ _.label === s.name && (_.style || (_.style = {}), _.style.strokeColor = s.color, _.style.fillColor = dt(s.color, 0.2), y = !0);
719
+ }), y && i.value.render();
630
720
  }
631
- a("labelChange", d.value);
632
- }, rt = (l) => {
633
- l.visible = !l.visible, M();
634
- }, ct = (l) => {
635
- const c = d.value.findIndex((A) => A.id === l);
636
- c > -1 && (d.value.splice(c, 1), a("labelChange", d.value), g.value === l && (g.value = d.value.length > 0 ? d.value[0].id : "", g.value && B(d.value[0])), M());
721
+ a("labelChange", g.value);
722
+ }, vt = (s) => {
723
+ s.visible = !s.visible, E();
724
+ }, ut = (s) => {
725
+ const l = g.value.findIndex((c) => c.id === s);
726
+ l > -1 && (g.value.splice(l, 1), a("labelChange", g.value), u.value === s && (u.value = g.value.length > 0 ? g.value[0].id : "", u.value && B(g.value[0])), E());
637
727
  };
638
- it(() => n.labels, (l) => {
639
- const c = JSON.parse(JSON.stringify(l || []));
640
- if (d.value = c, d.value.length > 0)
641
- if (!g.value || !d.value.find((A) => A.id === g.value))
642
- B(d.value[0]);
728
+ V(() => e.labels, (s) => {
729
+ const l = JSON.parse(JSON.stringify(s || []));
730
+ if (g.value = l, g.value.length > 0)
731
+ if (!u.value || !g.value.find((c) => c.id === u.value))
732
+ B(g.value[0]);
643
733
  else {
644
- const A = d.value.find((w) => w.id === g.value);
645
- A && B(A);
734
+ const c = g.value.find((y) => y.id === u.value);
735
+ c && B(c);
646
736
  }
647
737
  else
648
- g.value = "";
649
- M();
738
+ u.value = "";
739
+ E();
650
740
  }, { immediate: !0, deep: !0 });
651
- const ht = () => {
652
- v.value > 0 && (W(), v.value--, R(), V());
653
- }, dt = () => {
654
- v.value < n.batchImages.length - 1 && (W(), v.value++, R(), V());
655
- }, W = () => {
656
- if (s.value) {
657
- const l = s.value.getAnnotations();
658
- n.batchImages[v.value].annotations = l;
741
+ const mt = () => {
742
+ m.value > 0 && (j(), m.value--, U(), W());
743
+ }, ft = () => {
744
+ m.value < e.batchImages.length - 1 && (j(), m.value++, U(), W());
745
+ }, j = () => {
746
+ if (i.value) {
747
+ const s = i.value.getAnnotations();
748
+ e.batchImages[m.value].annotations = s;
659
749
  }
660
- }, V = () => {
661
- const l = n.batchImages[v.value];
750
+ }, W = () => {
751
+ const s = e.batchImages[m.value];
662
752
  a("batchChange", {
663
- currentIndex: v.value,
664
- total: n.batchImages.length,
665
- currentImageUrl: l.imageUrl,
666
- currentAnnotations: l.annotations || []
753
+ currentIndex: m.value,
754
+ total: e.batchImages.length,
755
+ currentImageUrl: s.imageUrl,
756
+ currentAnnotations: s.annotations || []
757
+ });
758
+ }, tt = (s = []) => {
759
+ var _;
760
+ if (!i.value) return;
761
+ if (k.value = JSON.parse(JSON.stringify(s)), k.value.length === 0) {
762
+ w.value = "none";
763
+ return;
764
+ }
765
+ w.value = "loaded";
766
+ const c = (i.value.getAnnotations() || []).filter((A) => !A.predictionId), y = k.value.map((A) => {
767
+ const P = JSON.parse(JSON.stringify(A.annotation));
768
+ return P.id = P.id || `pred-${A.id}`, P.predictionId = A.id, P.modelRunId = A.modelRunId || P.modelRunId, P.confidence = A.confidence ?? P.confidence, P.reviewStatus = P.reviewStatus || "draft", P;
769
+ });
770
+ i.value.setAnnotations([...c, ...y]), a("prediction:loaded", {
771
+ meta: I(),
772
+ modelRunId: (_ = k.value[0]) == null ? void 0 : _.modelRunId,
773
+ candidates: k.value
667
774
  });
775
+ }, yt = (s) => {
776
+ w.value = "loading", a("prediction:request", {
777
+ meta: I(),
778
+ threshold: s
779
+ });
780
+ }, pt = (s, l) => {
781
+ var _;
782
+ if (!i.value) return [];
783
+ w.value = "applying";
784
+ const y = (i.value.getAnnotations() || []).filter((A) => A.predictionId && s.includes(A.predictionId));
785
+ return y.forEach((A) => {
786
+ A.reviewStatus = "accepted";
787
+ }), w.value = "applied", a("prediction:apply", {
788
+ meta: I(),
789
+ modelRunId: (_ = y[0]) == null ? void 0 : _.modelRunId,
790
+ candidateIds: s,
791
+ threshold: l,
792
+ acceptedAnnotations: y
793
+ }), i.value.render(), y;
794
+ }, xt = (s, l) => {
795
+ var _;
796
+ if (!i.value) return;
797
+ const c = i.value.getAnnotations() || [], y = c.filter((A) => !(A.predictionId && s.includes(A.predictionId)));
798
+ i.value.setAnnotations(y), a("prediction:reject", {
799
+ meta: I(),
800
+ modelRunId: (_ = c.find((A) => A.predictionId && s.includes(A.predictionId))) == null ? void 0 : _.modelRunId,
801
+ candidateIds: s,
802
+ reason: l
803
+ });
804
+ }, bt = (s, l, c) => {
805
+ if (!i.value) return;
806
+ const y = i.value.getAnnotations() || [], _ = {
807
+ pass: "accepted",
808
+ reject: "rejected",
809
+ revise: "needs_fix"
810
+ };
811
+ y.forEach((A) => {
812
+ l.includes(A.id) && (A.reviewStatus = _[s]);
813
+ }), i.value.render(), a("review:action", {
814
+ meta: I(),
815
+ reviewAction: s,
816
+ targetAnnotationIds: l,
817
+ comment: c
818
+ });
819
+ }, wt = (s, l, c) => {
820
+ a("qa:issue", {
821
+ meta: I(),
822
+ issueType: s,
823
+ targetAnnotationIds: l,
824
+ detail: c
825
+ });
826
+ }, At = (s, l = []) => {
827
+ i.value && (i.value.loadImage(s.url), i.value.setAnnotations(l));
828
+ }, Ct = (s) => {
829
+ var l;
830
+ (l = i.value) == null || l.setAnnotations(s);
831
+ }, et = () => {
832
+ var s;
833
+ return ((s = i.value) == null ? void 0 : s.getAnnotations()) || [];
668
834
  };
669
835
  return t({
670
- jumpTo: (l) => {
671
- l >= 0 && l < n.batchImages.length && (W(), v.value = l, R(), V());
836
+ jumpTo: (s) => {
837
+ s >= 0 && s < e.batchImages.length && (j(), m.value = s, U(), W());
838
+ },
839
+ setImage: At,
840
+ setAnnotations: Ct,
841
+ getAnnotations: et,
842
+ selectTool: F,
843
+ loadPredictionCandidates: tt,
844
+ requestPrediction: yt,
845
+ applyPredictions: pt,
846
+ rejectPredictions: xt,
847
+ reviewAction: bt,
848
+ reportQaIssue: wt,
849
+ exportAnnotations: (s = "json") => {
850
+ var c, y;
851
+ const l = et();
852
+ return {
853
+ format: s,
854
+ image: ((c = e.batchImages[m.value]) == null ? void 0 : c.imageUrl) || ((y = e.image) == null ? void 0 : y.url) || "",
855
+ annotations: l
856
+ };
857
+ },
858
+ getAllAnnotations: () => {
859
+ var s, l;
860
+ return e.batchImages.length > 0 ? e.batchImages : [{
861
+ imageUrl: ((s = e.image) == null ? void 0 : s.url) || "",
862
+ annotations: ((l = i.value) == null ? void 0 : l.getAnnotations()) || []
863
+ }];
672
864
  },
673
- getAllAnnotations: () => n.batchImages,
674
865
  getCurrentAnnotation: () => {
675
- var l;
866
+ var s, l, c;
676
867
  return {
677
- imageUrl: n.batchImages[v.value].imageUrl,
678
- annotations: ((l = s.value) == null ? void 0 : l.getAnnotations()) || []
868
+ imageUrl: ((s = e.batchImages[m.value]) == null ? void 0 : s.imageUrl) || ((l = e.image) == null ? void 0 : l.url) || "",
869
+ annotations: ((c = i.value) == null ? void 0 : c.getAnnotations()) || []
679
870
  };
680
871
  }
681
- }), (l, c) => {
682
- const A = P("Rank"), w = P("el-icon"), T = P("Pointer"), gt = P("ZoomIn"), ut = P("ZoomOut"), et = P("Delete"), vt = P("Back"), ft = P("Right"), yt = P("View"), mt = P("Hide");
683
- return m(), x("div", {
684
- class: N(["annotation-container", u.theme])
685
- }, [
686
- u.readOnly ? L("", !0) : (m(), x("div", St, [
687
- h("div", {
688
- class: N(["tool-btn", { active: r.value === "pan" }]),
689
- onClick: c[0] || (c[0] = (p) => E("pan")),
690
- title: "拖动"
691
- }, [
692
- b(w, null, {
693
- default: I(() => [
694
- b(A)
695
- ]),
696
- _: 1
697
- })
698
- ], 2),
699
- h("div", {
700
- class: N(["tool-btn", { active: r.value === "select" }]),
701
- onClick: c[1] || (c[1] = (p) => E("select")),
702
- title: "选择"
703
- }, [
704
- b(w, null, {
705
- default: I(() => [
706
- b(T)
707
- ]),
708
- _: 1
709
- })
710
- ], 2),
711
- c[4] || (c[4] = h("div", { class: "divider" }, null, -1)),
712
- (m(!0), x($, null, F(_.value, (p) => (m(), x("div", {
713
- key: p,
714
- class: N(["tool-btn", { active: r.value === p }]),
715
- onClick: (U) => E(p),
716
- title: O(p)
717
- }, [
718
- b(w, null, {
719
- default: I(() => [
720
- (m(), X(Ct(S(p))))
721
- ]),
722
- _: 2
723
- }, 1024)
724
- ], 10, It))), 128)),
725
- c[5] || (c[5] = h("div", { class: "divider" }, null, -1)),
726
- h("div", {
727
- class: "tool-btn",
728
- onClick: z,
729
- title: "放大"
730
- }, [
731
- b(w, null, {
732
- default: I(() => [
733
- b(gt)
734
- ]),
735
- _: 1
736
- })
737
- ]),
738
- h("div", {
739
- class: "tool-btn",
740
- onClick: Q,
741
- title: "缩小"
742
- }, [
743
- b(w, null, {
744
- default: I(() => [
745
- b(ut)
746
- ]),
747
- _: 1
748
- })
749
- ]),
750
- c[6] || (c[6] = h("div", { class: "divider" }, null, -1)),
751
- h("div", {
752
- class: "tool-btn",
753
- onClick: H,
754
- title: "删除选中"
755
- }, [
756
- b(w, null, {
757
- default: I(() => [
758
- b(et)
759
- ]),
760
- _: 1
761
- })
872
+ }), V(() => {
873
+ var s;
874
+ return (s = e.image) == null ? void 0 : s.url;
875
+ }, () => {
876
+ var s;
877
+ e.batchImages.length === 0 && ((s = e.image) != null && s.url) && U();
878
+ }), V(() => e.predictionCandidates, (s) => {
879
+ s && tt(s);
880
+ }, { immediate: !0, deep: !0 }), (s, l) => (x(), b("div", {
881
+ class: $(["annotation-container", v.theme])
882
+ }, [
883
+ v.readOnly ? L("", !0) : (x(), b("div", Kt, [
884
+ d("div", {
885
+ class: $(["tool-btn", { active: h.value === "pan" }]),
886
+ onClick: l[0] || (l[0] = (c) => F("pan")),
887
+ title: "拖动"
888
+ }, [
889
+ z(M, { name: "rank" })
890
+ ], 2),
891
+ d("div", {
892
+ class: $(["tool-btn", { active: h.value === "select" }]),
893
+ onClick: l[1] || (l[1] = (c) => F("select")),
894
+ title: "选择"
895
+ }, [
896
+ z(M, { name: "pointer" })
897
+ ], 2),
898
+ l[4] || (l[4] = d("div", { class: "divider" }, null, -1)),
899
+ (x(!0), b(T, null, D(Z.value, (c) => (x(), b("div", {
900
+ key: c,
901
+ class: $(["tool-btn", { active: h.value === c }]),
902
+ onClick: (y) => F(c),
903
+ title: ot(c)
904
+ }, [
905
+ z(M, {
906
+ name: it(c)
907
+ }, null, 8, ["name"])
908
+ ], 10, Zt))), 128)),
909
+ l[5] || (l[5] = d("div", { class: "divider" }, null, -1)),
910
+ d("div", {
911
+ class: "tool-btn",
912
+ onClick: lt,
913
+ title: "放大"
914
+ }, [
915
+ z(M, { name: "zoom-in" })
916
+ ]),
917
+ d("div", {
918
+ class: "tool-btn",
919
+ onClick: rt,
920
+ title: "缩小"
921
+ }, [
922
+ z(M, { name: "zoom-out" })
923
+ ]),
924
+ l[6] || (l[6] = d("div", { class: "divider" }, null, -1)),
925
+ d("div", {
926
+ class: "tool-btn",
927
+ onClick: at,
928
+ title: "删除选中"
929
+ }, [
930
+ z(M, { name: "delete" })
931
+ ])
932
+ ])),
933
+ d("div", Gt, [
934
+ v.readOnly ? L("", !0) : (x(), b("div", Qt, [
935
+ d("div", te, [
936
+ l[7] || (l[7] = d("span", { class: "label-text" }, "当前标签:", -1)),
937
+ d("div", ee, [
938
+ (x(!0), b(T, null, D(g.value, (c) => (x(), b("div", {
939
+ key: c.id,
940
+ class: $(["tag-chip", { active: u.value === c.id }]),
941
+ style: K({ backgroundColor: c.color, borderColor: c.color }),
942
+ onClick: (y) => B(c)
943
+ }, H(c.name), 15, ne))), 128)),
944
+ g.value.length === 0 ? (x(), b("div", se, "请在右侧创建标签")) : L("", !0)
945
+ ])
762
946
  ])
763
947
  ])),
764
- h("div", Pt, [
765
- u.readOnly ? L("", !0) : (m(), x("div", Dt, [
766
- h("div", Tt, [
767
- c[7] || (c[7] = h("span", { class: "label-text" }, "当前标签:", -1)),
768
- h("div", Ht, [
769
- (m(!0), x($, null, F(d.value, (p) => (m(), x("div", {
770
- key: p.id,
771
- class: N(["tag-chip", { active: g.value === p.id }]),
772
- style: K({ backgroundColor: p.color, borderColor: p.color }),
773
- onClick: (U) => B(p)
774
- }, D(p.name), 15, Lt))), 128)),
775
- d.value.length === 0 ? (m(), x("div", Mt, "请在右侧创建标签")) : L("", !0)
776
- ])
777
- ])
778
- ])),
779
- h("div", {
780
- class: "canvas-wrapper",
781
- ref_key: "canvasWrapper",
948
+ d("div", {
949
+ class: "canvas-wrapper",
950
+ ref_key: "canvasWrapper",
951
+ ref: r
952
+ }, [
953
+ d("canvas", {
954
+ ref_key: "canvasRef",
782
955
  ref: o
956
+ }, null, 512)
957
+ ], 512),
958
+ v.batchImages && v.batchImages.length > 0 ? (x(), b("div", ie, [
959
+ d("button", {
960
+ onClick: mt,
961
+ disabled: m.value <= 0
783
962
  }, [
784
- h("canvas", {
785
- ref_key: "canvasRef",
786
- ref: i
787
- }, null, 512)
788
- ], 512),
789
- u.batchImages && u.batchImages.length > 0 ? (m(), x("div", $t, [
790
- h("button", {
791
- onClick: ht,
792
- disabled: v.value <= 0
793
- }, [
794
- b(w, null, {
795
- default: I(() => [
796
- b(vt)
797
- ]),
798
- _: 1
799
- }),
800
- c[8] || (c[8] = J(" 上一张 ", -1))
801
- ], 8, Rt),
802
- h("span", null, D(v.value + 1) + " / " + D(u.batchImages.length), 1),
803
- h("button", {
804
- onClick: dt,
805
- disabled: v.value >= u.batchImages.length - 1
806
- }, [
807
- c[9] || (c[9] = J(" 下一张 ", -1)),
808
- b(w, null, {
809
- default: I(() => [
810
- b(ft)
811
- ]),
812
- _: 1
813
- })
814
- ], 8, Ut)
815
- ])) : L("", !0)
963
+ z(M, { name: "back" }),
964
+ l[8] || (l[8] = O(" 上一张 ", -1))
965
+ ], 8, oe),
966
+ d("span", null, H(m.value + 1) + " / " + H(v.batchImages.length), 1),
967
+ d("button", {
968
+ onClick: ft,
969
+ disabled: m.value >= v.batchImages.length - 1
970
+ }, [
971
+ l[9] || (l[9] = O(" 下一张 ", -1)),
972
+ z(M, { name: "right" })
973
+ ], 8, ae)
974
+ ])) : L("", !0)
975
+ ]),
976
+ v.readOnly ? L("", !0) : (x(), b("div", le, [
977
+ d("div", { class: "sidebar-header" }, [
978
+ l[10] || (l[10] = d("h3", null, "标签管理", -1)),
979
+ d("button", {
980
+ class: "add-btn",
981
+ onClick: ct
982
+ }, "添加标签")
816
983
  ]),
817
- u.readOnly ? L("", !0) : (m(), x("div", Ft, [
818
- h("div", { class: "sidebar-header" }, [
819
- c[10] || (c[10] = h("h3", null, "标签管理", -1)),
820
- h("button", {
821
- class: "add-btn",
822
- onClick: st
823
- }, "添加标签")
824
- ]),
825
- h("div", Ot, [
826
- (m(!0), x($, null, F(d.value, (p) => (m(), x("div", {
827
- key: p.id,
828
- class: "label-item"
829
- }, [
830
- h("div", Et, [
831
- h("label", {
832
- class: "color-wrapper",
833
- style: K({ backgroundColor: p.color })
834
- }, [
835
- j(h("input", {
836
- type: "color",
837
- "onUpdate:modelValue": (U) => p.color = U,
838
- onChange: (U) => lt(p),
839
- style: { visibility: "hidden", width: "0", height: "0" }
840
- }, null, 40, zt), [
841
- [Y, p.color]
842
- ])
843
- ], 4),
844
- h("span", {
845
- class: "label-name",
846
- title: p.name
847
- }, D(p.name), 9, Bt),
848
- h("span", {
849
- class: "action-icon eye",
850
- onClick: (U) => rt(p)
851
- }, [
852
- p.visible ? (m(), X(w, { key: 0 }, {
853
- default: I(() => [
854
- b(yt)
855
- ]),
856
- _: 1
857
- })) : (m(), X(w, { key: 1 }, {
858
- default: I(() => [
859
- b(mt)
860
- ]),
861
- _: 1
862
- }))
863
- ], 8, Nt),
864
- h("div", Jt, [
865
- c[11] || (c[11] = h("span", { class: "dots" }, "•••", -1)),
866
- h("span", {
867
- class: "delete-btn",
868
- onClick: (U) => ct(p.id),
869
- title: "删除"
870
- }, [
871
- b(w, null, {
872
- default: I(() => [
873
- b(et)
874
- ]),
875
- _: 1
876
- })
877
- ], 8, Wt)
984
+ d("div", re, [
985
+ (x(!0), b(T, null, D(g.value, (c) => (x(), b("div", {
986
+ key: c.id,
987
+ class: "label-item"
988
+ }, [
989
+ d("div", ce, [
990
+ d("label", {
991
+ class: "color-wrapper",
992
+ style: K({ backgroundColor: c.color })
993
+ }, [
994
+ q(d("input", {
995
+ type: "color",
996
+ "onUpdate:modelValue": (y) => c.color = y,
997
+ onChange: (y) => gt(c),
998
+ style: { visibility: "hidden", width: "0", height: "0" }
999
+ }, null, 40, he), [
1000
+ [X, c.color]
878
1001
  ])
1002
+ ], 4),
1003
+ d("span", {
1004
+ class: "label-name",
1005
+ title: c.name
1006
+ }, H(c.name), 9, de),
1007
+ d("span", {
1008
+ class: "action-icon eye",
1009
+ onClick: (y) => vt(c)
1010
+ }, [
1011
+ c.visible ? (x(), nt(M, {
1012
+ key: 0,
1013
+ name: "view"
1014
+ })) : (x(), nt(M, {
1015
+ key: 1,
1016
+ name: "hide"
1017
+ }))
1018
+ ], 8, ge),
1019
+ d("div", ve, [
1020
+ l[11] || (l[11] = d("span", { class: "dots" }, "•••", -1)),
1021
+ d("span", {
1022
+ class: "delete-btn",
1023
+ onClick: (y) => ut(c.id),
1024
+ title: "删除"
1025
+ }, [
1026
+ z(M, { name: "delete" })
1027
+ ], 8, ue)
879
1028
  ])
880
- ]))), 128))
881
- ])
882
- ])),
883
- f.value ? (m(), x("div", Vt, [
884
- h("div", Xt, [
885
- c[14] || (c[14] = h("h3", null, "新增标签", -1)),
886
- h("div", jt, [
887
- c[12] || (c[12] = h("label", null, "名称", -1)),
888
- j(h("input", {
889
- "onUpdate:modelValue": c[2] || (c[2] = (p) => y.value.name = p),
890
- placeholder: "请输入标签名称",
891
- class: "modal-input"
1029
+ ])
1030
+ ]))), 128))
1031
+ ])
1032
+ ])),
1033
+ f.value ? (x(), b("div", me, [
1034
+ d("div", fe, [
1035
+ l[14] || (l[14] = d("h3", null, "新增标签", -1)),
1036
+ d("div", ye, [
1037
+ l[12] || (l[12] = d("label", null, "名称", -1)),
1038
+ q(d("input", {
1039
+ "onUpdate:modelValue": l[2] || (l[2] = (c) => p.value.name = c),
1040
+ placeholder: "请输入标签名称",
1041
+ class: "modal-input"
1042
+ }, null, 512), [
1043
+ [X, p.value.name]
1044
+ ])
1045
+ ]),
1046
+ d("div", pe, [
1047
+ l[13] || (l[13] = d("label", null, "颜色", -1)),
1048
+ d("div", xe, [
1049
+ q(d("input", {
1050
+ type: "color",
1051
+ "onUpdate:modelValue": l[3] || (l[3] = (c) => p.value.color = c),
1052
+ class: "modal-color-picker"
892
1053
  }, null, 512), [
893
- [Y, y.value.name]
894
- ])
895
- ]),
896
- h("div", Yt, [
897
- c[13] || (c[13] = h("label", null, "颜色", -1)),
898
- h("div", Zt, [
899
- j(h("input", {
900
- type: "color",
901
- "onUpdate:modelValue": c[3] || (c[3] = (p) => y.value.color = p),
902
- class: "modal-color-picker"
903
- }, null, 512), [
904
- [Y, y.value.color]
905
- ]),
906
- h("span", null, D(y.value.color), 1)
907
- ])
908
- ]),
909
- h("div", { class: "modal-actions" }, [
910
- h("button", {
911
- onClick: tt,
912
- class: "cancel-btn"
913
- }, "取消"),
914
- h("button", {
915
- onClick: ot,
916
- class: "confirm-btn"
917
- }, "确认")
1054
+ [X, p.value.color]
1055
+ ]),
1056
+ d("span", null, H(p.value.color), 1)
918
1057
  ])
1058
+ ]),
1059
+ d("div", { class: "modal-actions" }, [
1060
+ d("button", {
1061
+ onClick: Q,
1062
+ class: "cancel-btn"
1063
+ }, "取消"),
1064
+ d("button", {
1065
+ onClick: ht,
1066
+ class: "confirm-btn"
1067
+ }, "确认")
919
1068
  ])
920
- ])) : L("", !0)
921
- ], 2);
922
- };
1069
+ ])
1070
+ ])) : L("", !0)
1071
+ ], 2));
923
1072
  }
924
- }), G = (u, t) => {
925
- const e = u.__vccOpts || u;
926
- for (const [n, a] of t)
927
- e[n] = a;
928
- return e;
929
- }, qt = /* @__PURE__ */ G(Kt, [["__scopeId", "data-v-d3dc5a63"]]), Gt = {
1073
+ }), we = /* @__PURE__ */ J(be, [["__scopeId", "data-v-7b013204"]]), Ae = {
930
1074
  class: "thumbnail-wrapper",
931
1075
  ref: "wrapper"
932
- }, Qt = ["src", "alt"], te = ["viewBox"], ee = ["x", "y", "width", "height", "stroke"], ne = ["points", "stroke"], ie = ["x", "y", "fill"], se = {
1076
+ }, Ce = ["src", "alt"], _e = ["viewBox"], Ie = ["x", "y", "width", "height", "stroke"], Se = ["points", "stroke"], ke = ["x", "y", "fill"], Me = {
933
1077
  key: 1,
934
1078
  class: "loading-placeholder"
935
- }, oe = /* @__PURE__ */ q({
1079
+ }, ze = /* @__PURE__ */ N({
936
1080
  __name: "AnnotationThumbnail",
937
1081
  props: {
938
1082
  src: {},
@@ -940,213 +1084,195 @@ const St = {
940
1084
  alt: {},
941
1085
  labels: {}
942
1086
  },
943
- setup(u) {
944
- const t = u, e = k(null), n = k(!1), a = k(0), i = k(0), o = () => {
945
- e.value && (a.value = e.value.naturalWidth, i.value = e.value.naturalHeight, n.value = !0);
946
- }, s = (g) => {
1087
+ setup(v) {
1088
+ const t = v, n = S(null), e = S(!1), a = S(0), o = S(0), r = () => {
1089
+ n.value && (a.value = n.value.naturalWidth, o.value = n.value.naturalHeight, e.value = !0);
1090
+ }, i = (u) => {
947
1091
  var f;
948
- if ((f = g.style) != null && f.strokeColor) return g.style.strokeColor;
1092
+ if ((f = u.style) != null && f.strokeColor) return u.style.strokeColor;
949
1093
  if (t.labels) {
950
- const y = t.labels.find((_) => _.name === g.label);
951
- if (y) return y.color;
1094
+ const p = t.labels.find((w) => w.name === u.label);
1095
+ if (p) return p.color;
952
1096
  }
953
1097
  return "#FF0000";
954
- }, r = (g) => {
955
- const f = g.coordinates, y = Math.min(f.x1, f.x2), _ = Math.min(f.y1, f.y2), S = Math.abs(f.x1 - f.x2), O = Math.abs(f.y1 - f.y2);
956
- return { x: y, y: _, width: S, height: O };
957
- }, v = (g) => g.coordinates.points.map((y) => `${y.x},${y.y}`).join(" "), d = (g) => {
958
- if (g.type === "rectangle") {
959
- const f = r(g);
1098
+ }, h = (u) => {
1099
+ const f = u.coordinates, p = Math.min(f.x1, f.x2), w = Math.min(f.y1, f.y2), k = Math.abs(f.x1 - f.x2), I = Math.abs(f.y1 - f.y2);
1100
+ return { x: p, y: w, width: k, height: I };
1101
+ }, m = (u) => u.coordinates.points.map((p) => `${p.x},${p.y}`).join(" "), g = (u) => {
1102
+ if (u.type === "rectangle") {
1103
+ const f = h(u);
960
1104
  return { x: f.x, y: f.y - 5 };
961
- } else if (g.type === "polygon") {
962
- const f = g.coordinates.points;
1105
+ } else if (u.type === "polygon") {
1106
+ const f = u.coordinates.points;
963
1107
  if (f.length > 0) return { x: f[0].x, y: f[0].y - 5 };
964
1108
  }
965
1109
  return { x: 0, y: 0 };
966
1110
  };
967
- return (g, f) => (m(), x("div", Gt, [
968
- h("img", {
1111
+ return (u, f) => (x(), b("div", Ae, [
1112
+ d("img", {
969
1113
  ref_key: "img",
970
- ref: e,
971
- src: u.src,
1114
+ ref: n,
1115
+ src: v.src,
972
1116
  class: "thumbnail-image",
973
- onLoad: o,
974
- alt: u.alt
975
- }, null, 40, Qt),
976
- n.value ? (m(), x("svg", {
1117
+ onLoad: r,
1118
+ alt: v.alt
1119
+ }, null, 40, Ce),
1120
+ e.value ? (x(), b("svg", {
977
1121
  key: 0,
978
1122
  class: "annotation-overlay",
979
- viewBox: `0 0 ${a.value} ${i.value}`,
1123
+ viewBox: `0 0 ${a.value} ${o.value}`,
980
1124
  preserveAspectRatio: "none"
981
1125
  }, [
982
- (m(!0), x($, null, F(u.annotations, (y) => (m(), x($, {
983
- key: y.id
1126
+ (x(!0), b(T, null, D(v.annotations, (p) => (x(), b(T, {
1127
+ key: p.id
984
1128
  }, [
985
- y.type === "rectangle" ? (m(), x("rect", {
1129
+ p.type === "rectangle" ? (x(), b("rect", {
986
1130
  key: 0,
987
- x: r(y).x,
988
- y: r(y).y,
989
- width: r(y).width,
990
- height: r(y).height,
991
- stroke: s(y),
1131
+ x: h(p).x,
1132
+ y: h(p).y,
1133
+ width: h(p).width,
1134
+ height: h(p).height,
1135
+ stroke: i(p),
992
1136
  "stroke-width": "2",
993
1137
  fill: "transparent"
994
- }, null, 8, ee)) : L("", !0),
995
- y.type === "polygon" ? (m(), x("polygon", {
1138
+ }, null, 8, Ie)) : L("", !0),
1139
+ p.type === "polygon" ? (x(), b("polygon", {
996
1140
  key: 1,
997
- points: v(y),
998
- stroke: s(y),
1141
+ points: m(p),
1142
+ stroke: i(p),
999
1143
  "stroke-width": "2",
1000
1144
  fill: "transparent"
1001
- }, null, 8, ne)) : L("", !0),
1002
- y.label ? (m(), x("text", {
1145
+ }, null, 8, Se)) : L("", !0),
1146
+ p.label ? (x(), b("text", {
1003
1147
  key: 2,
1004
- x: d(y).x,
1005
- y: d(y).y,
1006
- fill: s(y),
1148
+ x: g(p).x,
1149
+ y: g(p).y,
1150
+ fill: i(p),
1007
1151
  "font-size": "14",
1008
1152
  "font-weight": "bold",
1009
1153
  class: "anno-label"
1010
- }, D(y.label), 9, ie)) : L("", !0)
1154
+ }, H(p.label), 9, ke)) : L("", !0)
1011
1155
  ], 64))), 128))
1012
- ], 8, te)) : (m(), x("div", se, "Loading..."))
1156
+ ], 8, _e)) : (x(), b("div", Me, "Loading..."))
1013
1157
  ], 512));
1014
1158
  }
1015
- }), ae = /* @__PURE__ */ G(oe, [["__scopeId", "data-v-78bcbe0c"]]), le = { class: "batch-annotator" }, re = {
1159
+ }), He = /* @__PURE__ */ J(ze, [["__scopeId", "data-v-78bcbe0c"]]), Pe = { class: "batch-annotator" }, Le = {
1016
1160
  key: 0,
1017
1161
  class: "gallery-view"
1018
- }, ce = { class: "gallery-header" }, he = { class: "label-summary" }, de = { class: "gallery-grid" }, ge = ["onClick"], ue = { class: "thumbnail-wrapper" }, ve = { class: "img-meta" }, fe = { class: "img-index" }, ye = { class: "anno-count" }, me = { class: "bottom-bar" }, pe = {
1162
+ }, Te = { class: "gallery-header" }, $e = { class: "label-summary" }, De = { class: "gallery-grid" }, Re = ["onClick"], Ue = { class: "thumbnail-wrapper" }, Fe = { class: "img-meta" }, Be = { class: "img-index" }, Oe = { class: "anno-count" }, Ee = { class: "bottom-bar" }, Ve = {
1019
1163
  key: 1,
1020
1164
  class: "editor-view"
1021
- }, xe = { class: "editor-header" }, be = { class: "header-left" }, Ae = { class: "editor-title" }, Ce = { class: "editor-content" }, we = /* @__PURE__ */ q({
1165
+ }, Ne = { class: "editor-header" }, Je = { class: "header-left" }, je = { class: "editor-title" }, We = { class: "editor-content" }, qe = /* @__PURE__ */ N({
1022
1166
  __name: "BatchAnnotator",
1023
1167
  props: {
1024
1168
  images: {},
1025
1169
  labels: {}
1026
1170
  },
1027
1171
  emits: ["export", "update:images"],
1028
- setup(u, { emit: t }) {
1029
- const e = u, n = t, a = k("gallery"), i = k([]), o = k(0), s = k(null);
1030
- it(() => e.images, (_) => {
1031
- i.value = JSON.parse(JSON.stringify(_));
1172
+ setup(v, { emit: t }) {
1173
+ const n = v, e = t, a = S("gallery"), o = S([]), r = S(0), i = S(null);
1174
+ V(() => n.images, (w) => {
1175
+ o.value = JSON.parse(JSON.stringify(w));
1032
1176
  }, { immediate: !0, deep: !0 });
1033
- const r = (_) => {
1034
- o.value = _, a.value = "editor", wt(() => {
1035
- s.value && s.value.jumpTo && s.value.jumpTo(_);
1177
+ const h = (w) => {
1178
+ r.value = w, a.value = "editor", zt(() => {
1179
+ i.value && i.value.jumpTo && i.value.jumpTo(w);
1036
1180
  });
1037
- }, v = () => {
1038
- if (s.value && s.value.getCurrentAnnotation) {
1039
- const _ = s.value.getCurrentAnnotation();
1040
- i.value[o.value] && (i.value[o.value].annotations = _.annotations);
1181
+ }, m = () => {
1182
+ if (i.value && i.value.getCurrentAnnotation) {
1183
+ const w = i.value.getCurrentAnnotation();
1184
+ o.value[r.value] && (o.value[r.value].annotations = w.annotations);
1041
1185
  }
1042
1186
  a.value = "gallery";
1043
- }, d = () => {
1044
- n("export", i.value);
1045
- }, g = (_) => {
1046
- o.value = _.currentIndex, i.value[_.currentIndex] && (i.value[_.currentIndex].annotations = _.currentAnnotations);
1047
- }, f = (_) => {
1048
- if (s.value && s.value.getCurrentAnnotation) {
1049
- const S = s.value.getCurrentAnnotation();
1050
- i.value[o.value] && (i.value[o.value].annotations = S.annotations, n("update:images", i.value));
1187
+ }, g = () => {
1188
+ e("export", o.value);
1189
+ }, u = (w) => {
1190
+ r.value = w.currentIndex, o.value[w.currentIndex] && (o.value[w.currentIndex].annotations = w.currentAnnotations);
1191
+ }, f = (w) => {
1192
+ if (i.value && i.value.getCurrentAnnotation) {
1193
+ const k = i.value.getCurrentAnnotation();
1194
+ o.value[r.value] && (o.value[r.value].annotations = k.annotations, e("update:images", o.value));
1051
1195
  }
1052
- }, y = (_) => {
1196
+ }, p = (w) => {
1053
1197
  };
1054
- return (_, S) => {
1055
- const O = P("Edit"), M = P("el-icon"), R = P("Download"), E = P("Back");
1056
- return m(), x("div", le, [
1057
- a.value === "gallery" ? (m(), x("div", re, [
1058
- h("div", ce, [
1059
- h("h3", null, "批量查看与标注 (" + D(i.value.length) + " 张)", 1),
1060
- h("div", he, [
1061
- (m(!0), x($, null, F(u.labels, (H) => (m(), x("span", {
1062
- key: H.id,
1063
- class: "label-badge",
1064
- style: K({ backgroundColor: H.color })
1065
- }, D(H.name), 5))), 128))
1198
+ return (w, k) => (x(), b("div", Pe, [
1199
+ a.value === "gallery" ? (x(), b("div", Le, [
1200
+ d("div", Te, [
1201
+ d("h3", null, "批量查看与标注 (" + H(o.value.length) + " 张)", 1),
1202
+ d("div", $e, [
1203
+ (x(!0), b(T, null, D(v.labels, (I) => (x(), b("span", {
1204
+ key: I.id,
1205
+ class: "label-badge",
1206
+ style: K({ backgroundColor: I.color })
1207
+ }, H(I.name), 5))), 128))
1208
+ ])
1209
+ ]),
1210
+ d("div", De, [
1211
+ (x(!0), b(T, null, D(o.value, (I, R) => (x(), b("div", {
1212
+ key: R,
1213
+ class: "gallery-item",
1214
+ onClick: (Z) => h(R)
1215
+ }, [
1216
+ d("div", Ue, [
1217
+ z(He, {
1218
+ src: I.imageUrl,
1219
+ annotations: I.annotations || [],
1220
+ labels: v.labels
1221
+ }, null, 8, ["src", "annotations", "labels"])
1222
+ ]),
1223
+ d("div", Fe, [
1224
+ d("span", Be, "#" + H(R + 1), 1),
1225
+ d("span", Oe, H((I.annotations || []).length) + " 标注", 1)
1066
1226
  ])
1227
+ ], 8, Re))), 128))
1228
+ ]),
1229
+ d("div", Ee, [
1230
+ d("button", {
1231
+ class: "action-btn primary",
1232
+ onClick: k[0] || (k[0] = (I) => h(0))
1233
+ }, [
1234
+ z(M, { name: "edit" }),
1235
+ k[1] || (k[1] = O(" 手动标注 ", -1))
1067
1236
  ]),
1068
- h("div", de, [
1069
- (m(!0), x($, null, F(i.value, (H, z) => (m(), x("div", {
1070
- key: z,
1071
- class: "gallery-item",
1072
- onClick: (Q) => r(z)
1073
- }, [
1074
- h("div", ue, [
1075
- b(ae, {
1076
- src: H.imageUrl,
1077
- annotations: H.annotations || [],
1078
- labels: u.labels
1079
- }, null, 8, ["src", "annotations", "labels"])
1080
- ]),
1081
- h("div", ve, [
1082
- h("span", fe, "#" + D(z + 1), 1),
1083
- h("span", ye, D((H.annotations || []).length) + " 标注", 1)
1084
- ])
1085
- ], 8, ge))), 128))
1086
- ]),
1087
- h("div", me, [
1088
- h("button", {
1089
- class: "action-btn primary",
1090
- onClick: S[0] || (S[0] = (H) => r(0))
1237
+ d("button", {
1238
+ class: "action-btn success",
1239
+ onClick: g
1240
+ }, [
1241
+ z(M, { name: "download" }),
1242
+ k[2] || (k[2] = O(" 导出 ", -1))
1243
+ ])
1244
+ ])
1245
+ ])) : (x(), b("div", Ve, [
1246
+ d("div", Ne, [
1247
+ d("div", Je, [
1248
+ d("button", {
1249
+ class: "back-btn",
1250
+ onClick: m
1091
1251
  }, [
1092
- b(M, null, {
1093
- default: I(() => [
1094
- b(O)
1095
- ]),
1096
- _: 1
1097
- }),
1098
- S[1] || (S[1] = J(" 手动标注 ", -1))
1252
+ z(M, { name: "back" }),
1253
+ k[3] || (k[3] = O(" 返回列表 ", -1))
1099
1254
  ]),
1100
- h("button", {
1101
- class: "action-btn success",
1102
- onClick: d
1103
- }, [
1104
- b(M, null, {
1105
- default: I(() => [
1106
- b(R)
1107
- ]),
1108
- _: 1
1109
- }),
1110
- S[2] || (S[2] = J(" 导出 ", -1))
1111
- ])
1255
+ d("span", je, "正在标注: " + H(r.value + 1) + " / " + H(o.value.length), 1)
1112
1256
  ])
1113
- ])) : (m(), x("div", pe, [
1114
- h("div", xe, [
1115
- h("div", be, [
1116
- h("button", {
1117
- class: "back-btn",
1118
- onClick: v
1119
- }, [
1120
- b(M, null, {
1121
- default: I(() => [
1122
- b(E)
1123
- ]),
1124
- _: 1
1125
- }),
1126
- S[3] || (S[3] = J(" 返回列表 ", -1))
1127
- ]),
1128
- h("span", Ae, "正在标注: " + D(o.value + 1) + " / " + D(i.value.length), 1)
1129
- ])
1130
- ]),
1131
- h("div", Ce, [
1132
- b(qt, {
1133
- ref_key: "annotatorRef",
1134
- ref: s,
1135
- batchImages: i.value,
1136
- labels: u.labels,
1137
- annotationTypes: ["rectangle", "polygon", "point", "rotatedRect"],
1138
- onBatchChange: g,
1139
- onAnnotationChange: f,
1140
- onLabelChange: y
1141
- }, null, 8, ["batchImages", "labels"])
1142
- ])
1143
- ]))
1144
- ]);
1145
- };
1257
+ ]),
1258
+ d("div", We, [
1259
+ z(we, {
1260
+ ref_key: "annotatorRef",
1261
+ ref: i,
1262
+ batchImages: o.value,
1263
+ labels: v.labels,
1264
+ annotationTypes: ["rectangle", "polygon", "point", "rotatedRect"],
1265
+ onBatchChange: u,
1266
+ onAnnotationChange: f,
1267
+ onLabelChange: p
1268
+ }, null, 8, ["batchImages", "labels"])
1269
+ ])
1270
+ ]))
1271
+ ]));
1146
1272
  }
1147
- }), Ie = /* @__PURE__ */ G(we, [["__scopeId", "data-v-4cf50076"]]);
1273
+ }), Ge = /* @__PURE__ */ J(qe, [["__scopeId", "data-v-87f3e002"]]);
1148
1274
  export {
1149
- Ie as BatchAnnotator,
1150
- qt as ImageAnnotator,
1151
- Ie as default
1275
+ Ge as BatchAnnotator,
1276
+ we as ImageAnnotator,
1277
+ Ge as default
1152
1278
  };