luo-image-annotator 0.0.3 → 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,71 +1,71 @@
1
- var rt = Object.defineProperty;
2
- var ct = (v, t, e) => t in v ? rt(v, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : v[t] = e;
3
- var b = (v, t, e) => ct(v, typeof t != "symbol" ? t + "" : t, e);
4
- import { defineComponent as R, ref as C, watchEffect as ht, openBlock as p, createElementBlock as x, normalizeClass as T, computed as gt, onMounted as dt, watch as q, createElementVNode as h, createVNode as S, Fragment as P, renderList as D, createCommentVNode as H, normalizeStyle as j, toDisplayString as z, createTextVNode as F, withDirectives as N, vModelText as J, createBlock as Y, nextTick as vt } from "vue";
5
- const W = (v, t) => Math.sqrt(Math.pow(v.x - t.x, 2) + Math.pow(v.y - t.y, 2)), ut = (v, t) => {
6
- let e = !1;
7
- for (let s = 0, a = t.length - 1; s < t.length; a = s++) {
8
- const n = t[s].x, o = t[s].y, i = t[a].x, r = t[a].y;
9
- o > v.y != r > v.y && v.x < (i - n) * (v.y - o) / (r - o) + n && (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
- }, K = (v, t, e) => {
13
- const s = e * (Math.PI / 180), a = Math.cos(s), n = Math.sin(s), o = v.x - t.x, i = v.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 - i * n),
16
- y: t.y + (o * n + i * a)
15
+ x: t.x + (r * a - i * o),
16
+ y: t.y + (r * o + i * a)
17
17
  };
18
18
  };
19
- class mt {
19
+ class Pt {
20
20
  constructor(t) {
21
- b(this, "canvas");
22
- b(this, "ctx");
23
- b(this, "img");
24
- b(this, "annotations", []);
21
+ C(this, "canvas");
22
+ C(this, "ctx");
23
+ C(this, "img");
24
+ C(this, "annotations", []);
25
25
  // 状态
26
- b(this, "currentTool", null);
27
- b(this, "activeAnnotation", null);
28
- b(this, "hoverAnnotation", null);
29
- b(this, "isDrawing", !1);
30
- b(this, "isDragging", !1);
31
- b(this, "isPanning", !1);
26
+ C(this, "currentTool", null);
27
+ C(this, "activeAnnotation", null);
28
+ C(this, "hoverAnnotation", null);
29
+ C(this, "isDrawing", !1);
30
+ C(this, "isDragging", !1);
31
+ C(this, "isPanning", !1);
32
32
  // 平移模式
33
- b(this, "panStartPoint", null);
33
+ C(this, "panStartPoint", null);
34
34
  // 平移起点
35
- b(this, "dragStartPoint", null);
36
- b(this, "dragStartAnnotation", null);
35
+ C(this, "dragStartPoint", null);
36
+ C(this, "dragStartAnnotation", null);
37
37
  // 快照用于撤销/diff
38
- b(this, "lastMouseMovePoint", null);
38
+ C(this, "lastMouseMovePoint", null);
39
39
  // 用于绘制辅助线
40
- b(this, "isHoveringStartPoint", !1);
40
+ C(this, "isHoveringStartPoint", !1);
41
41
  // 多边形闭合吸附状态
42
42
  // 设置
43
- b(this, "currentLabelColor", "#FF4081");
43
+ C(this, "currentLabelColor", "#FF4081");
44
44
  // 当前选中标签颜色
45
- b(this, "visibleLabels", /* @__PURE__ */ new Set());
45
+ C(this, "visibleLabels", /* @__PURE__ */ new Set());
46
46
  // 可见标签集合 (如果为空则全部可见,或者由外部控制渲染列表)
47
47
  // 交互
48
- b(this, "selectedHandleIndex", -1);
48
+ C(this, "selectedHandleIndex", -1);
49
49
  // -1: 主体, >=0: 顶点索引, -2: 旋转手柄
50
- b(this, "hoverHandleIndex", -1);
50
+ C(this, "hoverHandleIndex", -1);
51
51
  // 视口
52
- b(this, "scale", 1);
53
- b(this, "offset", { x: 0, y: 0 });
54
- b(this, "listeners", {});
55
- b(this, "imageUrl", "");
52
+ C(this, "scale", 1);
53
+ C(this, "offset", { x: 0, y: 0 });
54
+ C(this, "listeners", {});
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((s) => s(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 mt {
86
86
  this.visibleLabels = new Set(t), this.render();
87
87
  }
88
88
  zoom(t) {
89
- const s = t > 0 ? this.scale * 1.1 : this.scale / 1.1;
90
- if (s < 0.1 || s > 10) return;
91
- const a = this.canvas.width / 2, n = this.canvas.height / 2, o = this.toImageCoords(a, n);
92
- this.scale = s, this.offset.x = a - o.x * this.scale, this.offset.y = n - 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, s = this.canvas.height / this.img.height;
115
- this.scale = Math.min(e, s), 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 mt {
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((s) => s.id === t);
127
- if (e > -1) {
128
- const s = 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: s,
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(), s = t.clientX - e.left, a = t.clientY - e.top, n = this.toImageCoords(s, 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: s, 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(s, a, this.activeAnnotation);
144
- if (r !== -100) {
145
- this.isDragging = !0, this.dragStartPoint = n, 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(s, 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 i = this.getHitAnnotation(n);
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 && W(n, 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(n);
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(n);
167
+ this.startDrawing(o);
168
168
  return;
169
169
  }
170
170
  if (i) {
171
- this.activeAnnotation = i, this.isDragging = !0, this.dragStartPoint = n, this.selectedHandleIndex = -1, this.dragStartAnnotation = JSON.parse(JSON.stringify(i)), this.emit("annotationChange", { action: "select", changedItem: i, imageUrl: this.imageUrl }), this.render();
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(n);
175
- } else i ? (this.activeAnnotation = i, this.isDragging = !0, this.dragStartPoint = n, 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());
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
176
  } else if (i) {
177
177
  if (!(this.visibleLabels.size > 0 && !this.visibleLabels.has(i.label))) {
178
- this.activeAnnotation = i, this.isDragging = !0, this.dragStartPoint = n, this.selectedHandleIndex = -1, this.dragStartAnnotation = JSON.parse(JSON.stringify(i)), this.emit("annotationChange", { action: "select", changedItem: i, imageUrl: this.imageUrl }), this.render();
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(), s = t.clientX - e.left, a = t.clientY - e.top, n = this.toImageCoords(s, 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 = s - this.panStartPoint.x, i = a - this.panStartPoint.y;
188
- this.offset.x += o, this.offset.y += i, this.panStartPoint = { x: s, 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 = n, 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 i = o.points[0], r = W(n, i);
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(n);
201
- } else this.isDragging && this.activeAnnotation && this.dragStartPoint ? this.updateDragging(n) : this.checkHover(s, a, n);
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 mt {
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 s = parseInt(t.slice(1, 3), 16), a = parseInt(t.slice(3, 5), 16), n = parseInt(t.slice(5, 7), 16);
227
- return `rgba(${s}, ${a}, ${n}, ${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 mt {
239
239
  style: { strokeColor: this.currentLabelColor }
240
240
  };
241
241
  else if (this.currentTool === "point") {
242
- const s = {
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(s), this.emit("annotationChange", { action: "add", changedItem: s, imageUrl: this.imageUrl }), this.activeAnnotation = s;
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 s = {
260
- id: e,
259
+ const e = {
260
+ id: n,
261
261
  type: "category",
262
262
  label: "",
263
263
  // 将被填充
@@ -265,9 +265,9 @@ class mt {
265
265
  // 或位置?
266
266
  style: { strokeColor: this.currentLabelColor }
267
267
  };
268
- this.annotations.push(s), this.emit("annotationChange", { action: "add", changedItem: s, imageUrl: this.imageUrl }), this.activeAnnotation = s;
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 mt {
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, s = Math.abs(t.x - this.dragStartPoint.x), a = Math.abs(t.y - this.dragStartPoint.y);
284
- e.width = s * 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 mt {
292
292
  this.activeAnnotation = null, this.isDrawing = !1;
293
293
  return;
294
294
  }
295
- const e = Math.min(t.x1, t.x2), s = Math.max(t.x1, t.x2), a = Math.min(t.y1, t.y2), n = Math.max(t.y1, t.y2);
296
- t.x1 = e, t.x2 = s, t.y1 = a, t.y2 = n, 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 mt {
314
314
  }
315
315
  updateDragging(t) {
316
316
  if (!this.activeAnnotation || !this.dragStartPoint || !this.dragStartAnnotation) return;
317
- const e = t.x - this.dragStartPoint.x, s = t.y - this.dragStartPoint.y;
318
- this.selectedHandleIndex === -1 ? this.moveAnnotation(this.activeAnnotation, this.dragStartAnnotation, e, s) : 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, s, a) {
320
+ moveAnnotation(t, n, e, a) {
321
321
  if (t.type === "rectangle") {
322
- const n = e.coordinates, o = t.coordinates;
323
- o.x1 = n.x1 + s, o.x2 = n.x2 + s, o.y1 = n.y1 + a, o.y2 = n.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 n = e.coordinates, o = t.coordinates;
326
- o.points = n.points.map((i) => ({ x: i.x + s, y: i.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 n = e.coordinates, o = t.coordinates;
329
- o.x = n.x + s, o.y = n.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 n = e.coordinates, o = t.coordinates;
332
- o.points = n.points.map((i) => ({ x: i.x + s, y: i.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, s, a) {
335
+ resizeAnnotation(t, n, e, a) {
336
336
  if (t.type === "rectangle") {
337
- const n = t.coordinates;
338
- s === 0 && (n.x1 = a.x, n.y1 = a.y), s === 1 && (n.x2 = a.x, n.y1 = a.y), s === 2 && (n.x2 = a.x, n.y2 = a.y), s === 3 && (n.x1 = a.x, n.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 n = t.coordinates;
341
- s >= 0 && s < n.points.length && (n.points[s] = 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 n = t.coordinates;
344
- s >= 0 && s < n.points.length && (n.points[s] = 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 n = t.coordinates;
347
- if (s === -2) {
348
- const o = n.x, i = n.y, r = a.x - o, m = a.y - i;
349
- let d = Math.atan2(m, r) * 180 / Math.PI;
350
- d += 90, n.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 = n.angle * Math.PI / 180, i = Math.cos(-o), r = Math.sin(-o), m = a.x - n.x, d = a.y - n.y, u = m * i - d * r, f = m * r + d * i;
353
- (s === 0 || s === 3) && (n.width / 2, n.width = Math.abs(u) * 2), (s === 1 || s === 2) && (n.width = Math.abs(u) * 2), (s === 0 || s === 1) && (n.height = Math.abs(f) * 2), (s === 2 || s === 3) && (n.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 s = this.annotations[e];
361
- if (this.isPointInAnnotation(t, s))
362
- return s;
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 s = e.coordinates;
369
- return t.x >= s.x1 && t.x <= s.x2 && t.y >= s.y1 && t.y <= s.y2;
370
- } else if (e.type === "polygon") {
371
- const s = e.coordinates;
372
- return ut(t, s.points);
373
- } else if (e.type === "rotatedRect") {
374
- const s = e.coordinates, a = K(t, { x: s.x, y: s.y }, -s.angle), n = s.width / 2, o = s.height / 2;
375
- return a.x >= s.x - n && a.x <= s.x + n && a.y >= s.y - o && a.y <= s.y + o;
376
- } else if (e.type === "point")
377
- return e.coordinates.points.some((a) => W(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, s) {
381
- const a = this.getAnnotationHandles(s), n = 6;
382
- for (let o = 0; o < a.length; o++) {
383
- const i = a[o], r = this.toScreenCoords(i.x, i.y);
384
- if (Math.abs(t - r.x) < n && Math.abs(e - r.y) < n)
385
- return s.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 mt {
405
405
  if (t.type === "point")
406
406
  return t.coordinates.points;
407
407
  if (t.type === "rotatedRect") {
408
- const e = t.coordinates, s = { x: e.x, y: e.y }, a = e.width / 2, n = e.height / 2, o = { x: e.x - a, y: e.y - n }, i = { x: e.x + a, y: e.y - n }, r = { x: e.x + a, y: e.y + n }, m = { x: e.x - a, y: e.y + n }, d = { x: e.x, y: e.y - n - 20 / this.scale };
409
- return [o, i, r, m, d].map((u) => K(u, s, 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, s) {
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 n = this.getHitAnnotation(s);
425
- n ? (this.canvas.style.cursor = "move", this.hoverAnnotation = n) : (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,158 +430,158 @@ class mt {
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 s = 10, a = 8, n = 4, o = 24, i = 8;
438
- t.forEach((r) => {
439
- const m = r.label || "Unlabeled", d = this.ctx.measureText(m).width + a * 2, u = this.activeAnnotation === r, f = this.hoverAnnotation === r;
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(e, s, d, o), this.ctx.fill(), this.ctx.stroke(), this.ctx.fillStyle = u ? "#1976D2" : "#333", this.ctx.fillText(m, e + a, s + n), e += d + i;
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 s = this.annotations.filter((d) => d.type === "category");
445
- if (s.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 n = 10, o = 8, i = 24, r = 8;
448
+ const o = 10, r = 8, i = 24, h = 8;
449
449
  let m = null;
450
- for (const d of s) {
451
- const u = d.label || "Unlabeled", f = this.ctx.measureText(u).width + o * 2;
452
- if (t >= a && t <= a + f && e >= n && e <= n + i) {
453
- m = d;
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
458
  return this.ctx.restore(), m;
459
459
  }
460
- drawItem(t, e) {
461
- var n;
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 s = ((n = t.style) == null ? void 0 : n.strokeColor) || "#FF4081", a = e ? "#00E5FF" : s;
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(s, 0.2), t.type === "rectangle") {
467
- const o = t.coordinates, i = this.toScreenCoords(o.x1, o.y1), r = this.toScreenCoords(o.x2, o.y2), m = Math.min(i.x, r.x), d = Math.min(i.y, r.y), u = Math.abs(i.x - r.x), f = Math.abs(i.y - r.y);
468
- this.ctx.strokeRect(m, d, u, f), this.ctx.fillStyle = e ? "rgba(0, 229, 255, 0.2)" : "rgba(255, 64, 129, 0.2)", this.ctx.fillRect(m, d, u, 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 i = this.toScreenCoords(o.points[0].x, o.points[0].y);
476
+ const i = this.toScreenCoords(r.points[0].x, r.points[0].y);
477
477
  this.ctx.moveTo(i.x, i.y);
478
- for (let r = 1; r < o.points.length; r++) {
479
- const m = this.toScreenCoords(o.points[r].x, o.points[r].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
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 m = this.toScreenCoords(r.x, r.y);
491
+ const m = this.toScreenCoords(h.x, h.y);
492
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 i = o.width * this.scale, r = o.height * this.scale;
499
- this.ctx.strokeRect(-i / 2, -r / 2, i, r), this.ctx.fillStyle = e ? "rgba(0, 229, 255, 0.2)" : "rgba(255, 64, 129, 0.2)", this.ctx.fillRect(-i / 2, -r / 2, i, 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));
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
500
  } else t.type === "point" && t.coordinates.points.forEach((i) => {
501
- const r = this.toScreenCoords(i.x, i.y);
502
- this.ctx.beginPath(), this.ctx.arc(r.x, r.y, 5, 0, Math.PI * 2), this.ctx.fillStyle = e ? "#00E5FF" : s, this.ctx.fill(), this.ctx.stroke();
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 s = this.toScreenCoords(e.x, e.y);
509
- this.ctx.fillRect(s.x - 4, s.y - 4, 8, 8), this.ctx.strokeRect(s.x - 4, s.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 ft = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
513
+ const Lt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
514
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>`, yt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
515
+ </svg>`, Tt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
516
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>`, pt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
517
+ </svg>`, $t = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
518
518
  <path d="M704 192h160v160h-160z m-64-64v288h288V128H640zM160 672h160v160H160z m-64-64v288h288V608H96z m256-320h320v64H352z" fill="currentColor"/>\r
519
- </svg>`, xt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
519
+ </svg>`, Dt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
520
520
  <path d="M256 256h512v512H256z m-64-64v640h640V192H192z" fill="currentColor"/>\r
521
- </svg>`, bt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
521
+ </svg>`, Rt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
522
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>`, wt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
523
+ </svg>`, Ut = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
524
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>`, Ct = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
525
+ </svg>`, Ft = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
526
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>`, _t = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
527
+ </svg>`, Bt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
528
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>`, At = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
529
+ </svg>`, Ot = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
530
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>`, kt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
531
+ </svg>`, Et = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
532
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>`, St = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
533
+ </svg>`, Vt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
534
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>`, It = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
535
+ </svg>`, Nt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
536
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>`, zt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
537
+ </svg>`, Jt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
538
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>`, Mt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
539
+ </svg>`, jt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
540
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>`, Ht = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
541
+ </svg>`, Wt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
542
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>`, Lt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
543
+ </svg>`, qt = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1em" height="1em">\r
544
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>`, Pt = ["innerHTML"], Tt = /* @__PURE__ */ R({
545
+ </svg>`, Xt = ["innerHTML"], Yt = /* @__PURE__ */ N({
546
546
  __name: "SvgIcon",
547
547
  props: {
548
548
  name: {},
549
549
  size: {}
550
550
  },
551
551
  setup(v) {
552
- const t = v, e = C(""), s = /* @__PURE__ */ Object.assign({ "../assets/svg/aim.svg": ft, "../assets/svg/back.svg": yt, "../assets/svg/connection.svg": pt, "../assets/svg/crop.svg": xt, "../assets/svg/delete.svg": bt, "../assets/svg/download.svg": wt, "../assets/svg/edit.svg": Ct, "../assets/svg/hide.svg": _t, "../assets/svg/pointer.svg": At, "../assets/svg/price-tag.svg": kt, "../assets/svg/rank.svg": St, "../assets/svg/refresh-right.svg": It, "../assets/svg/right.svg": zt, "../assets/svg/view.svg": Mt, "../assets/svg/zoom-in.svg": Ht, "../assets/svg/zoom-out.svg": Lt });
553
- return ht(() => {
554
- const a = `../assets/svg/${t.name}.svg`, n = s[a];
555
- n ? e.value = n : (console.warn(`Icon ${t.name} not found at path ${a}`), e.value = "");
556
- }), (a, n) => (p(), x("i", {
557
- class: T(["svg-icon", [v.size ? `size-${v.size}` : ""]]),
558
- innerHTML: e.value
559
- }, null, 10, Pt));
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
560
  }
561
- }), B = (v, t) => {
562
- const e = v.__vccOpts || v;
563
- for (const [s, a] of t)
564
- e[s] = a;
565
- return e;
566
- }, k = /* @__PURE__ */ B(Tt, [["__scopeId", "data-v-3928607b"]]), Dt = {
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 = {
567
567
  key: 0,
568
568
  class: "left-sidebar"
569
- }, $t = ["onClick", "title"], Ut = { class: "center-area" }, Ft = {
569
+ }, Zt = ["onClick", "title"], Gt = { class: "center-area" }, Qt = {
570
570
  key: 0,
571
571
  class: "top-bar"
572
- }, Rt = { class: "label-selector" }, Bt = { class: "tags-row" }, Ot = ["onClick"], Vt = {
572
+ }, te = { class: "label-selector" }, ee = { class: "tags-row" }, ne = ["onClick"], se = {
573
573
  key: 0,
574
574
  class: "no-labels"
575
- }, Et = {
575
+ }, ie = {
576
576
  key: 1,
577
577
  class: "batch-nav"
578
- }, Nt = ["disabled"], Jt = ["disabled"], Wt = {
578
+ }, oe = ["disabled"], ae = ["disabled"], le = {
579
579
  key: 1,
580
580
  class: "right-sidebar"
581
- }, jt = { class: "label-list" }, Xt = { class: "label-row" }, Yt = ["onUpdate:modelValue", "onChange"], Kt = ["title"], qt = ["onClick"], Gt = { class: "action-icon more-actions" }, Qt = ["onClick"], Zt = {
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 = {
582
582
  key: 2,
583
583
  class: "modal-overlay"
584
- }, te = { class: "modal-content" }, ee = { class: "form-group" }, se = { class: "form-group" }, ne = { class: "color-input-wrapper" }, ie = /* @__PURE__ */ R({
584
+ }, fe = { class: "modal-content" }, ye = { class: "form-group" }, pe = { class: "form-group" }, xe = { class: "color-input-wrapper" }, be = /* @__PURE__ */ N({
585
585
  __name: "ImageAnnotator",
586
586
  props: {
587
587
  annotationTypes: { default: () => ["rectangle", "polygon", "point", "rotatedRect"] },
@@ -589,348 +589,494 @@ const ft = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" widt
589
589
  labels: { default: () => [] },
590
590
  defaultActiveType: {},
591
591
  theme: { default: "light" },
592
- 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: {}
593
600
  },
594
- emits: ["annotationChange", "batchChange", "labelChange"],
595
- setup(v, { expose: t, emit: e }) {
596
- const s = v, a = e, n = C(null), o = C(null), i = C(null), r = C(null), m = C(0), d = C([]), u = C(""), f = C(!1), y = C({ name: "", color: "#FF0000" }), w = gt(() => s.annotationTypes.filter((l) => l !== "category")), A = (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) => ({
597
626
  rectangle: "crop",
598
627
  polygon: "connection",
599
628
  point: "aim",
600
629
  rotatedRect: "refresh-right",
601
630
  category: "price-tag"
602
- })[l] || l, I = (l) => ({
631
+ })[s] || s, ot = (s) => ({
603
632
  rectangle: "矩形框",
604
633
  polygon: "多边形",
605
634
  point: "关键点",
606
635
  rotatedRect: "旋转矩形",
607
636
  category: "分类标签"
608
- })[l] || l;
609
- dt(() => {
610
- if (n.value) {
611
- i.value = new mt(n.value), i.value.on("annotationChange", (c) => {
612
- if (c.action === "add" && c.changedItem) {
613
- const g = d.value.find((_) => _.id === u.value);
614
- g && (c.changedItem.label = g.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);
615
644
  }
616
- a("annotationChange", c);
617
- }), $(), L();
618
- const l = new ResizeObserver(() => {
619
- var c;
620
- (c = i.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();
621
650
  });
622
- o.value && l.observe(o.value);
651
+ r.value && s.observe(r.value), e.defaultActiveType && F(e.defaultActiveType), a("ready", { meta: I() });
623
652
  }
624
653
  });
625
- const L = () => {
654
+ const E = () => {
626
655
  if (!i.value) return;
627
- const l = d.value.find((g) => g.id === u.value);
628
- l && i.value.setLabelStyle(l.color);
629
- const c = d.value.filter((g) => g.visible).map((g) => g.name);
630
- i.value.setVisibleLabels(c);
631
- }, $ = () => {
632
- if (i.value && s.batchImages.length > 0) {
633
- const l = s.batchImages[m.value];
634
- i.value.loadImage(l.imageUrl), l.annotations && i.value.setAnnotations(l.annotations);
635
- }
636
- }, O = (l) => {
637
- var c, g;
638
- if (r.value = l, l !== "pan" && l !== "select" && d.value.length === 0) {
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) {
639
670
  alert("请先创建标签!");
640
671
  return;
641
672
  }
642
- l === "pan" || l === "select" ? (c = i.value) == null || c.setTool(l) : (g = i.value) == null || g.setTool(l);
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);
643
677
  }, G = () => {
644
- var l;
645
- (l = i.value) != null && l.activeAnnotation && i.value.deleteAnnotation(i.value.activeAnnotation.id);
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;
646
691
  }, Q = () => {
647
- var l;
648
- return (l = i.value) == null ? void 0 : l.zoom(1);
649
- }, Z = () => {
650
- var l;
651
- return (l = i.value) == null ? void 0 : l.zoom(-1);
652
- }, tt = () => {
653
- y.value = { name: "", color: "#2196F3" }, f.value = !0;
654
- }, X = () => {
655
692
  f.value = !1;
656
- }, et = () => {
657
- if (!y.value.name.trim()) {
693
+ }, ht = () => {
694
+ if (!p.value.name.trim()) {
658
695
  alert("请输入标签名称");
659
696
  return;
660
697
  }
661
- const c = {
698
+ const l = {
662
699
  id: Date.now().toString(),
663
- name: y.value.name,
664
- color: y.value.color,
700
+ name: p.value.name,
701
+ color: p.value.color,
665
702
  visible: !0
666
703
  };
667
- d.value.push(c), a("labelChange", d.value), d.value.length === 1 && U(c), X();
668
- }, U = (l) => {
669
- var c;
670
- u.value = l.id, (c = i.value) == null || c.setLabelStyle(l.color);
671
- }, st = (l, c) => {
672
- if (!l.startsWith("#")) return l;
673
- let g = 0, _ = 0, M = 0;
674
- return l.length === 4 ? (g = parseInt(l[1] + l[1], 16), _ = parseInt(l[2] + l[2], 16), M = parseInt(l[3] + l[3], 16)) : l.length === 7 && (g = parseInt(l.slice(1, 3), 16), _ = parseInt(l.slice(3, 5), 16), M = parseInt(l.slice(5, 7), 16)), `rgba(${g}, ${_}, ${M}, ${c})`;
675
- }, nt = (l) => {
676
- var c;
677
- if (l.id === u.value && ((c = i.value) == null || c.setLabelStyle(l.color)), i.value) {
678
- const g = i.value.getAnnotations();
679
- let _ = !1;
680
- g.forEach((M) => {
681
- M.label === l.name && (M.style || (M.style = {}), M.style.strokeColor = l.color, M.style.fillColor = st(l.color, 0.2), _ = !0);
682
- }), _ && i.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();
683
720
  }
684
- a("labelChange", d.value);
685
- }, it = (l) => {
686
- l.visible = !l.visible, L();
687
- }, ot = (l) => {
688
- const c = d.value.findIndex((g) => g.id === l);
689
- c > -1 && (d.value.splice(c, 1), a("labelChange", d.value), u.value === l && (u.value = d.value.length > 0 ? d.value[0].id : "", u.value && U(d.value[0])), L());
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());
690
727
  };
691
- q(() => s.labels, (l) => {
692
- const c = JSON.parse(JSON.stringify(l || []));
693
- if (d.value = c, d.value.length > 0)
694
- if (!u.value || !d.value.find((g) => g.id === u.value))
695
- U(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]);
696
733
  else {
697
- const g = d.value.find((_) => _.id === u.value);
698
- g && U(g);
734
+ const c = g.value.find((y) => y.id === u.value);
735
+ c && B(c);
699
736
  }
700
737
  else
701
738
  u.value = "";
702
- L();
739
+ E();
703
740
  }, { immediate: !0, deep: !0 });
704
- const at = () => {
705
- m.value > 0 && (V(), m.value--, $(), E());
706
- }, lt = () => {
707
- m.value < s.batchImages.length - 1 && (V(), m.value++, $(), E());
708
- }, V = () => {
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 = () => {
709
746
  if (i.value) {
710
- const l = i.value.getAnnotations();
711
- s.batchImages[m.value].annotations = l;
747
+ const s = i.value.getAnnotations();
748
+ e.batchImages[m.value].annotations = s;
712
749
  }
713
- }, E = () => {
714
- const l = s.batchImages[m.value];
750
+ }, W = () => {
751
+ const s = e.batchImages[m.value];
715
752
  a("batchChange", {
716
753
  currentIndex: m.value,
717
- total: s.batchImages.length,
718
- currentImageUrl: l.imageUrl,
719
- currentAnnotations: l.annotations || []
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
774
+ });
775
+ }, yt = (s) => {
776
+ w.value = "loading", a("prediction:request", {
777
+ meta: I(),
778
+ threshold: s
720
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()) || [];
721
834
  };
722
835
  return t({
723
- jumpTo: (l) => {
724
- l >= 0 && l < s.batchImages.length && (V(), m.value = l, $(), E());
836
+ jumpTo: (s) => {
837
+ s >= 0 && s < e.batchImages.length && (j(), m.value = s, U(), W());
725
838
  },
726
- getAllAnnotations: () => s.batchImages,
727
- getCurrentAnnotation: () => {
728
- var l;
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();
729
852
  return {
730
- imageUrl: s.batchImages[m.value].imageUrl,
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) || "",
731
862
  annotations: ((l = i.value) == null ? void 0 : l.getAnnotations()) || []
863
+ }];
864
+ },
865
+ getCurrentAnnotation: () => {
866
+ var s, l, c;
867
+ return {
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()) || []
732
870
  };
733
871
  }
734
- }), (l, c) => (p(), x("div", {
735
- class: T(["annotation-container", v.theme])
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])
736
882
  }, [
737
- v.readOnly ? H("", !0) : (p(), x("div", Dt, [
738
- h("div", {
739
- class: T(["tool-btn", { active: r.value === "pan" }]),
740
- onClick: c[0] || (c[0] = (g) => O("pan")),
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")),
741
887
  title: "拖动"
742
888
  }, [
743
- S(k, { name: "rank" })
889
+ z(M, { name: "rank" })
744
890
  ], 2),
745
- h("div", {
746
- class: T(["tool-btn", { active: r.value === "select" }]),
747
- onClick: c[1] || (c[1] = (g) => O("select")),
891
+ d("div", {
892
+ class: $(["tool-btn", { active: h.value === "select" }]),
893
+ onClick: l[1] || (l[1] = (c) => F("select")),
748
894
  title: "选择"
749
895
  }, [
750
- S(k, { name: "pointer" })
896
+ z(M, { name: "pointer" })
751
897
  ], 2),
752
- c[4] || (c[4] = h("div", { class: "divider" }, null, -1)),
753
- (p(!0), x(P, null, D(w.value, (g) => (p(), x("div", {
754
- key: g,
755
- class: T(["tool-btn", { active: r.value === g }]),
756
- onClick: (_) => O(g),
757
- title: I(g)
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)
758
904
  }, [
759
- S(k, {
760
- name: A(g)
905
+ z(M, {
906
+ name: it(c)
761
907
  }, null, 8, ["name"])
762
- ], 10, $t))), 128)),
763
- c[5] || (c[5] = h("div", { class: "divider" }, null, -1)),
764
- h("div", {
908
+ ], 10, Zt))), 128)),
909
+ l[5] || (l[5] = d("div", { class: "divider" }, null, -1)),
910
+ d("div", {
765
911
  class: "tool-btn",
766
- onClick: Q,
912
+ onClick: lt,
767
913
  title: "放大"
768
914
  }, [
769
- S(k, { name: "zoom-in" })
915
+ z(M, { name: "zoom-in" })
770
916
  ]),
771
- h("div", {
917
+ d("div", {
772
918
  class: "tool-btn",
773
- onClick: Z,
919
+ onClick: rt,
774
920
  title: "缩小"
775
921
  }, [
776
- S(k, { name: "zoom-out" })
922
+ z(M, { name: "zoom-out" })
777
923
  ]),
778
- c[6] || (c[6] = h("div", { class: "divider" }, null, -1)),
779
- h("div", {
924
+ l[6] || (l[6] = d("div", { class: "divider" }, null, -1)),
925
+ d("div", {
780
926
  class: "tool-btn",
781
- onClick: G,
927
+ onClick: at,
782
928
  title: "删除选中"
783
929
  }, [
784
- S(k, { name: "delete" })
930
+ z(M, { name: "delete" })
785
931
  ])
786
932
  ])),
787
- h("div", Ut, [
788
- v.readOnly ? H("", !0) : (p(), x("div", Ft, [
789
- h("div", Rt, [
790
- c[7] || (c[7] = h("span", { class: "label-text" }, "当前标签:", -1)),
791
- h("div", Bt, [
792
- (p(!0), x(P, null, D(d.value, (g) => (p(), x("div", {
793
- key: g.id,
794
- class: T(["tag-chip", { active: u.value === g.id }]),
795
- style: j({ backgroundColor: g.color, borderColor: g.color }),
796
- onClick: (_) => U(g)
797
- }, z(g.name), 15, Ot))), 128)),
798
- d.value.length === 0 ? (p(), x("div", Vt, "请在右侧创建标签")) : H("", !0)
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)
799
945
  ])
800
946
  ])
801
947
  ])),
802
- h("div", {
948
+ d("div", {
803
949
  class: "canvas-wrapper",
804
950
  ref_key: "canvasWrapper",
805
- ref: o
951
+ ref: r
806
952
  }, [
807
- h("canvas", {
953
+ d("canvas", {
808
954
  ref_key: "canvasRef",
809
- ref: n
955
+ ref: o
810
956
  }, null, 512)
811
957
  ], 512),
812
- v.batchImages && v.batchImages.length > 0 ? (p(), x("div", Et, [
813
- h("button", {
814
- onClick: at,
958
+ v.batchImages && v.batchImages.length > 0 ? (x(), b("div", ie, [
959
+ d("button", {
960
+ onClick: mt,
815
961
  disabled: m.value <= 0
816
962
  }, [
817
- S(k, { name: "back" }),
818
- c[8] || (c[8] = F(" 上一张 ", -1))
819
- ], 8, Nt),
820
- h("span", null, z(m.value + 1) + " / " + z(v.batchImages.length), 1),
821
- h("button", {
822
- onClick: lt,
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,
823
969
  disabled: m.value >= v.batchImages.length - 1
824
970
  }, [
825
- c[9] || (c[9] = F(" 下一张 ", -1)),
826
- S(k, { name: "right" })
827
- ], 8, Jt)
828
- ])) : H("", !0)
971
+ l[9] || (l[9] = O(" 下一张 ", -1)),
972
+ z(M, { name: "right" })
973
+ ], 8, ae)
974
+ ])) : L("", !0)
829
975
  ]),
830
- v.readOnly ? H("", !0) : (p(), x("div", Wt, [
831
- h("div", { class: "sidebar-header" }, [
832
- c[10] || (c[10] = h("h3", null, "标签管理", -1)),
833
- h("button", {
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", {
834
980
  class: "add-btn",
835
- onClick: tt
981
+ onClick: ct
836
982
  }, "添加标签")
837
983
  ]),
838
- h("div", jt, [
839
- (p(!0), x(P, null, D(d.value, (g) => (p(), x("div", {
840
- key: g.id,
984
+ d("div", re, [
985
+ (x(!0), b(T, null, D(g.value, (c) => (x(), b("div", {
986
+ key: c.id,
841
987
  class: "label-item"
842
988
  }, [
843
- h("div", Xt, [
844
- h("label", {
989
+ d("div", ce, [
990
+ d("label", {
845
991
  class: "color-wrapper",
846
- style: j({ backgroundColor: g.color })
992
+ style: K({ backgroundColor: c.color })
847
993
  }, [
848
- N(h("input", {
994
+ q(d("input", {
849
995
  type: "color",
850
- "onUpdate:modelValue": (_) => g.color = _,
851
- onChange: (_) => nt(g),
996
+ "onUpdate:modelValue": (y) => c.color = y,
997
+ onChange: (y) => gt(c),
852
998
  style: { visibility: "hidden", width: "0", height: "0" }
853
- }, null, 40, Yt), [
854
- [J, g.color]
999
+ }, null, 40, he), [
1000
+ [X, c.color]
855
1001
  ])
856
1002
  ], 4),
857
- h("span", {
1003
+ d("span", {
858
1004
  class: "label-name",
859
- title: g.name
860
- }, z(g.name), 9, Kt),
861
- h("span", {
1005
+ title: c.name
1006
+ }, H(c.name), 9, de),
1007
+ d("span", {
862
1008
  class: "action-icon eye",
863
- onClick: (_) => it(g)
1009
+ onClick: (y) => vt(c)
864
1010
  }, [
865
- g.visible ? (p(), Y(k, {
1011
+ c.visible ? (x(), nt(M, {
866
1012
  key: 0,
867
1013
  name: "view"
868
- })) : (p(), Y(k, {
1014
+ })) : (x(), nt(M, {
869
1015
  key: 1,
870
1016
  name: "hide"
871
1017
  }))
872
- ], 8, qt),
873
- h("div", Gt, [
874
- c[11] || (c[11] = h("span", { class: "dots" }, "•••", -1)),
875
- h("span", {
1018
+ ], 8, ge),
1019
+ d("div", ve, [
1020
+ l[11] || (l[11] = d("span", { class: "dots" }, "•••", -1)),
1021
+ d("span", {
876
1022
  class: "delete-btn",
877
- onClick: (_) => ot(g.id),
1023
+ onClick: (y) => ut(c.id),
878
1024
  title: "删除"
879
1025
  }, [
880
- S(k, { name: "delete" })
881
- ], 8, Qt)
1026
+ z(M, { name: "delete" })
1027
+ ], 8, ue)
882
1028
  ])
883
1029
  ])
884
1030
  ]))), 128))
885
1031
  ])
886
1032
  ])),
887
- f.value ? (p(), x("div", Zt, [
888
- h("div", te, [
889
- c[14] || (c[14] = h("h3", null, "新增标签", -1)),
890
- h("div", ee, [
891
- c[12] || (c[12] = h("label", null, "名称", -1)),
892
- N(h("input", {
893
- "onUpdate:modelValue": c[2] || (c[2] = (g) => y.value.name = g),
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),
894
1040
  placeholder: "请输入标签名称",
895
1041
  class: "modal-input"
896
1042
  }, null, 512), [
897
- [J, y.value.name]
1043
+ [X, p.value.name]
898
1044
  ])
899
1045
  ]),
900
- h("div", se, [
901
- c[13] || (c[13] = h("label", null, "颜色", -1)),
902
- h("div", ne, [
903
- N(h("input", {
1046
+ d("div", pe, [
1047
+ l[13] || (l[13] = d("label", null, "颜色", -1)),
1048
+ d("div", xe, [
1049
+ q(d("input", {
904
1050
  type: "color",
905
- "onUpdate:modelValue": c[3] || (c[3] = (g) => y.value.color = g),
1051
+ "onUpdate:modelValue": l[3] || (l[3] = (c) => p.value.color = c),
906
1052
  class: "modal-color-picker"
907
1053
  }, null, 512), [
908
- [J, y.value.color]
1054
+ [X, p.value.color]
909
1055
  ]),
910
- h("span", null, z(y.value.color), 1)
1056
+ d("span", null, H(p.value.color), 1)
911
1057
  ])
912
1058
  ]),
913
- h("div", { class: "modal-actions" }, [
914
- h("button", {
915
- onClick: X,
1059
+ d("div", { class: "modal-actions" }, [
1060
+ d("button", {
1061
+ onClick: Q,
916
1062
  class: "cancel-btn"
917
1063
  }, "取消"),
918
- h("button", {
919
- onClick: et,
1064
+ d("button", {
1065
+ onClick: ht,
920
1066
  class: "confirm-btn"
921
1067
  }, "确认")
922
1068
  ])
923
1069
  ])
924
- ])) : H("", !0)
1070
+ ])) : L("", !0)
925
1071
  ], 2));
926
1072
  }
927
- }), oe = /* @__PURE__ */ B(ie, [["__scopeId", "data-v-fe1b36c0"]]), ae = {
1073
+ }), we = /* @__PURE__ */ J(be, [["__scopeId", "data-v-7b013204"]]), Ae = {
928
1074
  class: "thumbnail-wrapper",
929
1075
  ref: "wrapper"
930
- }, le = ["src", "alt"], re = ["viewBox"], ce = ["x", "y", "width", "height", "stroke"], he = ["points", "stroke"], ge = ["x", "y", "fill"], de = {
1076
+ }, Ce = ["src", "alt"], _e = ["viewBox"], Ie = ["x", "y", "width", "height", "stroke"], Se = ["points", "stroke"], ke = ["x", "y", "fill"], Me = {
931
1077
  key: 1,
932
1078
  class: "loading-placeholder"
933
- }, ve = /* @__PURE__ */ R({
1079
+ }, ze = /* @__PURE__ */ N({
934
1080
  __name: "AnnotationThumbnail",
935
1081
  props: {
936
1082
  src: {},
@@ -939,22 +1085,22 @@ const ft = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" widt
939
1085
  labels: {}
940
1086
  },
941
1087
  setup(v) {
942
- const t = v, e = C(null), s = C(!1), a = C(0), n = C(0), o = () => {
943
- e.value && (a.value = e.value.naturalWidth, n.value = e.value.naturalHeight, s.value = !0);
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);
944
1090
  }, i = (u) => {
945
1091
  var f;
946
1092
  if ((f = u.style) != null && f.strokeColor) return u.style.strokeColor;
947
1093
  if (t.labels) {
948
- const y = t.labels.find((w) => w.name === u.label);
949
- if (y) return y.color;
1094
+ const p = t.labels.find((w) => w.name === u.label);
1095
+ if (p) return p.color;
950
1096
  }
951
1097
  return "#FF0000";
952
- }, r = (u) => {
953
- const f = u.coordinates, y = Math.min(f.x1, f.x2), w = Math.min(f.y1, f.y2), A = Math.abs(f.x1 - f.x2), I = Math.abs(f.y1 - f.y2);
954
- return { x: y, y: w, width: A, height: I };
955
- }, m = (u) => u.coordinates.points.map((y) => `${y.x},${y.y}`).join(" "), d = (u) => {
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) => {
956
1102
  if (u.type === "rectangle") {
957
- const f = r(u);
1103
+ const f = h(u);
958
1104
  return { x: f.x, y: f.y - 5 };
959
1105
  } else if (u.type === "polygon") {
960
1106
  const f = u.coordinates.points;
@@ -962,61 +1108,61 @@ const ft = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" widt
962
1108
  }
963
1109
  return { x: 0, y: 0 };
964
1110
  };
965
- return (u, f) => (p(), x("div", ae, [
966
- h("img", {
1111
+ return (u, f) => (x(), b("div", Ae, [
1112
+ d("img", {
967
1113
  ref_key: "img",
968
- ref: e,
1114
+ ref: n,
969
1115
  src: v.src,
970
1116
  class: "thumbnail-image",
971
- onLoad: o,
1117
+ onLoad: r,
972
1118
  alt: v.alt
973
- }, null, 40, le),
974
- s.value ? (p(), x("svg", {
1119
+ }, null, 40, Ce),
1120
+ e.value ? (x(), b("svg", {
975
1121
  key: 0,
976
1122
  class: "annotation-overlay",
977
- viewBox: `0 0 ${a.value} ${n.value}`,
1123
+ viewBox: `0 0 ${a.value} ${o.value}`,
978
1124
  preserveAspectRatio: "none"
979
1125
  }, [
980
- (p(!0), x(P, null, D(v.annotations, (y) => (p(), x(P, {
981
- key: y.id
1126
+ (x(!0), b(T, null, D(v.annotations, (p) => (x(), b(T, {
1127
+ key: p.id
982
1128
  }, [
983
- y.type === "rectangle" ? (p(), x("rect", {
1129
+ p.type === "rectangle" ? (x(), b("rect", {
984
1130
  key: 0,
985
- x: r(y).x,
986
- y: r(y).y,
987
- width: r(y).width,
988
- height: r(y).height,
989
- stroke: i(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),
990
1136
  "stroke-width": "2",
991
1137
  fill: "transparent"
992
- }, null, 8, ce)) : H("", !0),
993
- y.type === "polygon" ? (p(), x("polygon", {
1138
+ }, null, 8, Ie)) : L("", !0),
1139
+ p.type === "polygon" ? (x(), b("polygon", {
994
1140
  key: 1,
995
- points: m(y),
996
- stroke: i(y),
1141
+ points: m(p),
1142
+ stroke: i(p),
997
1143
  "stroke-width": "2",
998
1144
  fill: "transparent"
999
- }, null, 8, he)) : H("", !0),
1000
- y.label ? (p(), x("text", {
1145
+ }, null, 8, Se)) : L("", !0),
1146
+ p.label ? (x(), b("text", {
1001
1147
  key: 2,
1002
- x: d(y).x,
1003
- y: d(y).y,
1004
- fill: i(y),
1148
+ x: g(p).x,
1149
+ y: g(p).y,
1150
+ fill: i(p),
1005
1151
  "font-size": "14",
1006
1152
  "font-weight": "bold",
1007
1153
  class: "anno-label"
1008
- }, z(y.label), 9, ge)) : H("", !0)
1154
+ }, H(p.label), 9, ke)) : L("", !0)
1009
1155
  ], 64))), 128))
1010
- ], 8, re)) : (p(), x("div", de, "Loading..."))
1156
+ ], 8, _e)) : (x(), b("div", Me, "Loading..."))
1011
1157
  ], 512));
1012
1158
  }
1013
- }), ue = /* @__PURE__ */ B(ve, [["__scopeId", "data-v-78bcbe0c"]]), me = { class: "batch-annotator" }, fe = {
1159
+ }), He = /* @__PURE__ */ J(ze, [["__scopeId", "data-v-78bcbe0c"]]), Pe = { class: "batch-annotator" }, Le = {
1014
1160
  key: 0,
1015
1161
  class: "gallery-view"
1016
- }, ye = { class: "gallery-header" }, pe = { class: "label-summary" }, xe = { class: "gallery-grid" }, be = ["onClick"], we = { class: "thumbnail-wrapper" }, Ce = { class: "img-meta" }, _e = { class: "img-index" }, Ae = { class: "anno-count" }, ke = { class: "bottom-bar" }, Se = {
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 = {
1017
1163
  key: 1,
1018
1164
  class: "editor-view"
1019
- }, Ie = { class: "editor-header" }, ze = { class: "header-left" }, Me = { class: "editor-title" }, He = { class: "editor-content" }, Le = /* @__PURE__ */ R({
1165
+ }, Ne = { class: "editor-header" }, Je = { class: "header-left" }, je = { class: "editor-title" }, We = { class: "editor-content" }, qe = /* @__PURE__ */ N({
1020
1166
  __name: "BatchAnnotator",
1021
1167
  props: {
1022
1168
  images: {},
@@ -1024,109 +1170,109 @@ const ft = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" widt
1024
1170
  },
1025
1171
  emits: ["export", "update:images"],
1026
1172
  setup(v, { emit: t }) {
1027
- const e = v, s = t, a = C("gallery"), n = C([]), o = C(0), i = C(null);
1028
- q(() => e.images, (w) => {
1029
- n.value = JSON.parse(JSON.stringify(w));
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));
1030
1176
  }, { immediate: !0, deep: !0 });
1031
- const r = (w) => {
1032
- o.value = w, a.value = "editor", vt(() => {
1177
+ const h = (w) => {
1178
+ r.value = w, a.value = "editor", zt(() => {
1033
1179
  i.value && i.value.jumpTo && i.value.jumpTo(w);
1034
1180
  });
1035
1181
  }, m = () => {
1036
1182
  if (i.value && i.value.getCurrentAnnotation) {
1037
1183
  const w = i.value.getCurrentAnnotation();
1038
- n.value[o.value] && (n.value[o.value].annotations = w.annotations);
1184
+ o.value[r.value] && (o.value[r.value].annotations = w.annotations);
1039
1185
  }
1040
1186
  a.value = "gallery";
1041
- }, d = () => {
1042
- s("export", n.value);
1187
+ }, g = () => {
1188
+ e("export", o.value);
1043
1189
  }, u = (w) => {
1044
- o.value = w.currentIndex, n.value[w.currentIndex] && (n.value[w.currentIndex].annotations = w.currentAnnotations);
1190
+ r.value = w.currentIndex, o.value[w.currentIndex] && (o.value[w.currentIndex].annotations = w.currentAnnotations);
1045
1191
  }, f = (w) => {
1046
1192
  if (i.value && i.value.getCurrentAnnotation) {
1047
- const A = i.value.getCurrentAnnotation();
1048
- n.value[o.value] && (n.value[o.value].annotations = A.annotations, s("update:images", n.value));
1193
+ const k = i.value.getCurrentAnnotation();
1194
+ o.value[r.value] && (o.value[r.value].annotations = k.annotations, e("update:images", o.value));
1049
1195
  }
1050
- }, y = (w) => {
1196
+ }, p = (w) => {
1051
1197
  };
1052
- return (w, A) => (p(), x("div", me, [
1053
- a.value === "gallery" ? (p(), x("div", fe, [
1054
- h("div", ye, [
1055
- h("h3", null, "批量查看与标注 (" + z(n.value.length) + " 张)", 1),
1056
- h("div", pe, [
1057
- (p(!0), x(P, null, D(v.labels, (I) => (p(), x("span", {
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", {
1058
1204
  key: I.id,
1059
1205
  class: "label-badge",
1060
- style: j({ backgroundColor: I.color })
1061
- }, z(I.name), 5))), 128))
1206
+ style: K({ backgroundColor: I.color })
1207
+ }, H(I.name), 5))), 128))
1062
1208
  ])
1063
1209
  ]),
1064
- h("div", xe, [
1065
- (p(!0), x(P, null, D(n.value, (I, L) => (p(), x("div", {
1066
- key: L,
1210
+ d("div", De, [
1211
+ (x(!0), b(T, null, D(o.value, (I, R) => (x(), b("div", {
1212
+ key: R,
1067
1213
  class: "gallery-item",
1068
- onClick: ($) => r(L)
1214
+ onClick: (Z) => h(R)
1069
1215
  }, [
1070
- h("div", we, [
1071
- S(ue, {
1216
+ d("div", Ue, [
1217
+ z(He, {
1072
1218
  src: I.imageUrl,
1073
1219
  annotations: I.annotations || [],
1074
1220
  labels: v.labels
1075
1221
  }, null, 8, ["src", "annotations", "labels"])
1076
1222
  ]),
1077
- h("div", Ce, [
1078
- h("span", _e, "#" + z(L + 1), 1),
1079
- h("span", Ae, z((I.annotations || []).length) + " 标注", 1)
1223
+ d("div", Fe, [
1224
+ d("span", Be, "#" + H(R + 1), 1),
1225
+ d("span", Oe, H((I.annotations || []).length) + " 标注", 1)
1080
1226
  ])
1081
- ], 8, be))), 128))
1227
+ ], 8, Re))), 128))
1082
1228
  ]),
1083
- h("div", ke, [
1084
- h("button", {
1229
+ d("div", Ee, [
1230
+ d("button", {
1085
1231
  class: "action-btn primary",
1086
- onClick: A[0] || (A[0] = (I) => r(0))
1232
+ onClick: k[0] || (k[0] = (I) => h(0))
1087
1233
  }, [
1088
- S(k, { name: "edit" }),
1089
- A[1] || (A[1] = F(" 手动标注 ", -1))
1234
+ z(M, { name: "edit" }),
1235
+ k[1] || (k[1] = O(" 手动标注 ", -1))
1090
1236
  ]),
1091
- h("button", {
1237
+ d("button", {
1092
1238
  class: "action-btn success",
1093
- onClick: d
1239
+ onClick: g
1094
1240
  }, [
1095
- S(k, { name: "download" }),
1096
- A[2] || (A[2] = F(" 导出 ", -1))
1241
+ z(M, { name: "download" }),
1242
+ k[2] || (k[2] = O(" 导出 ", -1))
1097
1243
  ])
1098
1244
  ])
1099
- ])) : (p(), x("div", Se, [
1100
- h("div", Ie, [
1101
- h("div", ze, [
1102
- h("button", {
1245
+ ])) : (x(), b("div", Ve, [
1246
+ d("div", Ne, [
1247
+ d("div", Je, [
1248
+ d("button", {
1103
1249
  class: "back-btn",
1104
1250
  onClick: m
1105
1251
  }, [
1106
- S(k, { name: "back" }),
1107
- A[3] || (A[3] = F(" 返回列表 ", -1))
1252
+ z(M, { name: "back" }),
1253
+ k[3] || (k[3] = O(" 返回列表 ", -1))
1108
1254
  ]),
1109
- h("span", Me, "正在标注: " + z(o.value + 1) + " / " + z(n.value.length), 1)
1255
+ d("span", je, "正在标注: " + H(r.value + 1) + " / " + H(o.value.length), 1)
1110
1256
  ])
1111
1257
  ]),
1112
- h("div", He, [
1113
- S(oe, {
1258
+ d("div", We, [
1259
+ z(we, {
1114
1260
  ref_key: "annotatorRef",
1115
1261
  ref: i,
1116
- batchImages: n.value,
1262
+ batchImages: o.value,
1117
1263
  labels: v.labels,
1118
1264
  annotationTypes: ["rectangle", "polygon", "point", "rotatedRect"],
1119
1265
  onBatchChange: u,
1120
1266
  onAnnotationChange: f,
1121
- onLabelChange: y
1267
+ onLabelChange: p
1122
1268
  }, null, 8, ["batchImages", "labels"])
1123
1269
  ])
1124
1270
  ]))
1125
1271
  ]));
1126
1272
  }
1127
- }), $e = /* @__PURE__ */ B(Le, [["__scopeId", "data-v-87f3e002"]]);
1273
+ }), Ge = /* @__PURE__ */ J(qe, [["__scopeId", "data-v-87f3e002"]]);
1128
1274
  export {
1129
- $e as BatchAnnotator,
1130
- oe as ImageAnnotator,
1131
- $e as default
1275
+ Ge as BatchAnnotator,
1276
+ we as ImageAnnotator,
1277
+ Ge as default
1132
1278
  };