From 400ca77e5119e04880fd2c8dd1b5658a1c76cbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=88=E5=85=86=E5=A2=9E?= <你的邮箱@example.com> Date: Wed, 29 Jul 2026 15:56:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=99=BA=E8=83=BD=E9=97=AE?= =?UTF-8?q?=E7=AD=94=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/assets/svg/PDF.svg | 24 + frontend/src/assets/svg/add.svg | 6 + frontend/src/assets/svg/docx.svg | 22 + frontend/src/assets/svg/upload.svg | 6 + frontend/src/assets/svg/xlsx.svg | 19 + frontend/src/modules/IntelligentQA/index.vue | 1424 +++++++++++++++++ .../MapStudio/components/RightDrawer.vue | 13 + .../MapStudio/composables/useDrawTools.ts | 132 +- frontend/src/modules/MapStudio/types/index.ts | 3 + frontend/src/styles/index.scss | 9 +- .../views/zhiNengFenXi/zhiNengWenDa/index.vue | 7 + 11 files changed, 1630 insertions(+), 35 deletions(-) create mode 100644 frontend/src/assets/svg/PDF.svg create mode 100644 frontend/src/assets/svg/add.svg create mode 100644 frontend/src/assets/svg/docx.svg create mode 100644 frontend/src/assets/svg/upload.svg create mode 100644 frontend/src/assets/svg/xlsx.svg create mode 100644 frontend/src/modules/IntelligentQA/index.vue create mode 100644 frontend/src/views/zhiNengFenXi/zhiNengWenDa/index.vue diff --git a/frontend/src/assets/svg/PDF.svg b/frontend/src/assets/svg/PDF.svg new file mode 100644 index 00000000..3e068d41 --- /dev/null +++ b/frontend/src/assets/svg/PDF.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + diff --git a/frontend/src/assets/svg/add.svg b/frontend/src/assets/svg/add.svg new file mode 100644 index 00000000..b23e7e48 --- /dev/null +++ b/frontend/src/assets/svg/add.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/frontend/src/assets/svg/docx.svg b/frontend/src/assets/svg/docx.svg new file mode 100644 index 00000000..1a2ac353 --- /dev/null +++ b/frontend/src/assets/svg/docx.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + diff --git a/frontend/src/assets/svg/upload.svg b/frontend/src/assets/svg/upload.svg new file mode 100644 index 00000000..e2efc3a6 --- /dev/null +++ b/frontend/src/assets/svg/upload.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/frontend/src/assets/svg/xlsx.svg b/frontend/src/assets/svg/xlsx.svg new file mode 100644 index 00000000..92fac535 --- /dev/null +++ b/frontend/src/assets/svg/xlsx.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/frontend/src/modules/IntelligentQA/index.vue b/frontend/src/modules/IntelligentQA/index.vue new file mode 100644 index 00000000..b54bd773 --- /dev/null +++ b/frontend/src/modules/IntelligentQA/index.vue @@ -0,0 +1,1424 @@ + + + + + diff --git a/frontend/src/modules/MapStudio/components/RightDrawer.vue b/frontend/src/modules/MapStudio/components/RightDrawer.vue index 9c313fae..c9fb6bcf 100644 --- a/frontend/src/modules/MapStudio/components/RightDrawer.vue +++ b/frontend/src/modules/MapStudio/components/RightDrawer.vue @@ -1467,6 +1467,19 @@ +
+
+ + + 三角 + 开放 + 菱形 + +
+
diff --git a/frontend/src/modules/MapStudio/composables/useDrawTools.ts b/frontend/src/modules/MapStudio/composables/useDrawTools.ts index 4056e2dc..a6f991bf 100644 --- a/frontend/src/modules/MapStudio/composables/useDrawTools.ts +++ b/frontend/src/modules/MapStudio/composables/useDrawTools.ts @@ -35,6 +35,46 @@ function nextDrawId(): string { return `draw_${Date.now()}_${++drawIdCounter}`; } +/** 根据箭头样式创建箭头图片 */ +function createArrowImage( + shape: string, + radius: number, + rotation: number, + color: string, + strokeWidth: number +) { + // endAngle 是地图坐标系角度(atan2 dy/dx, y朝上) + // 屏幕坐标系 y 朝下,转换: screenAngle = -endAngle + // RegularShape 默认顶点朝上,再 +π/2 → 正确屏幕方向 + const rot = Math.PI / 2 - rotation; + if (shape === 'diamond') { + return new RegularShape({ + points: 4, + radius, + rotation: rot, + fill: new Fill({ color }), + stroke: new Stroke({ color, width: 1 }) + }); + } + if (shape === 'chevron') { + return new RegularShape({ + points: 3, + radius, + rotation: rot, + // 开放箭头:只描边不填充 + stroke: new Stroke({ color, width: Math.max(strokeWidth, 2) }) + }); + } + // triangle(默认) + return new RegularShape({ + points: 3, + radius, + rotation: rot, + fill: new Fill({ color }), + stroke: new Stroke({ color, width: 1 }) + }); +} + /** Feature 上存储单个样式对象的属性 key */ const DS_FEATURE_KEY = '_drawPerStyle'; @@ -161,6 +201,7 @@ export function useDrawTools(mapInstance: Ref) { const arrowPosition = perStyle?.arrowPosition ?? drawStyle.value.arrowPosition; const arrowSize = perStyle?.arrowSize ?? drawStyle.value.arrowSize; + const arrowShape = perStyle?.arrowShape ?? drawStyle.value.arrowShape; const fontSize = perStyle?.fontSize ?? drawStyle.value.fontSize; const fontFamily = perStyle?.fontFamily ?? drawStyle.value.fontFamily; const textColor = perStyle?.textColor ?? drawStyle.value.textColor; @@ -233,44 +274,67 @@ export function useDrawTools(mapInstance: Ref) { const arrowR = arrowSize === 'small' ? 6 : arrowSize === 'large' ? 12 : 9; - // 结束箭头 - const last = coords[coords.length - 1]; - const prev = coords[coords.length - 2]; - const endAngle = Math.atan2(last[1] - prev[1], last[0] - prev[0]); - styles.push( - new Style({ - geometry: new Point(last), - image: new RegularShape({ - points: 3, - radius: arrowR, - rotation: endAngle - Math.PI / 2, - fill: new Fill({ color: strokeColor }), - stroke: new Stroke({ color: strokeColor, width: 1 }) - }) - }) - ); - - // 起始箭头 - if (arrowPosition === 'both' && coords.length >= 2) { - const first = coords[0]; - const second = coords[1]; - const startAngle = Math.atan2( - first[1] - second[1], - first[0] - second[0] + // 结束箭头 —— 跳过双重点产生的零长度段 + const endLast = coords[coords.length - 1]; + let endPrevIdx = coords.length - 2; + while ( + endPrevIdx >= 0 && + coords[endPrevIdx][0] === endLast[0] && + coords[endPrevIdx][1] === endLast[1] + ) { + endPrevIdx--; + } + if (endPrevIdx >= 0) { + const endPrev = coords[endPrevIdx]; + const endAngle = Math.atan2( + endLast[1] - endPrev[1], + endLast[0] - endPrev[0] ); styles.push( new Style({ - geometry: new Point(first), - image: new RegularShape({ - points: 3, - radius: arrowR, - rotation: startAngle - Math.PI / 2, - fill: new Fill({ color: strokeColor }), - stroke: new Stroke({ color: strokeColor, width: 1 }) - }) + geometry: new Point(endLast), + image: createArrowImage( + arrowShape, + arrowR, + endAngle, + strokeColor, + strokeWidth + ) }) ); } + + // 起始箭头 —— 同理跳过重复点 + if (arrowPosition === 'both' && coords.length >= 2) { + const startFirst = coords[0]; + let startSecondIdx = 1; + while ( + startSecondIdx < coords.length && + coords[startSecondIdx][0] === startFirst[0] && + coords[startSecondIdx][1] === startFirst[1] + ) { + startSecondIdx++; + } + if (startSecondIdx < coords.length) { + const startSecond = coords[startSecondIdx]; + const startAngle = Math.atan2( + startFirst[1] - startSecond[1], + startFirst[0] - startSecond[0] + ); + styles.push( + new Style({ + geometry: new Point(startFirst), + image: createArrowImage( + arrowShape, + arrowR, + startAngle, + strokeColor, + strokeWidth + ) + }) + ); + } + } } } } @@ -354,6 +418,7 @@ export function useDrawTools(mapInstance: Ref) { showArrow: stored?.showArrow ?? drawStyle.value.showArrow, arrowPosition: stored?.arrowPosition ?? drawStyle.value.arrowPosition, arrowSize: stored?.arrowSize ?? drawStyle.value.arrowSize, + arrowShape: stored?.arrowShape ?? drawStyle.value.arrowShape, fontSize: stored?.fontSize ?? drawStyle.value.fontSize, fontFamily: stored?.fontFamily ?? drawStyle.value.fontFamily, textColor: stored?.textColor ?? drawStyle.value.textColor, @@ -388,6 +453,7 @@ export function useDrawTools(mapInstance: Ref) { showArrow: s.showArrow, arrowPosition: s.arrowPosition, arrowSize: s.arrowSize, + arrowShape: s.arrowShape, fontSize: s.fontSize, fontFamily: s.fontFamily, textColor: s.textColor, @@ -806,6 +872,7 @@ export function useDrawTools(mapInstance: Ref) { showArrow: drawStyle.value.showArrow, arrowPosition: drawStyle.value.arrowPosition, arrowSize: drawStyle.value.arrowSize, + arrowShape: drawStyle.value.arrowShape, fontSize: drawStyle.value.fontSize, fontFamily: drawStyle.value.fontFamily, textColor: drawStyle.value.textColor, @@ -865,6 +932,7 @@ export function useDrawTools(mapInstance: Ref) { showArrow: drawStyle.value.showArrow, arrowPosition: drawStyle.value.arrowPosition, arrowSize: drawStyle.value.arrowSize, + arrowShape: drawStyle.value.arrowShape, fontSize: drawStyle.value.fontSize, fontFamily: drawStyle.value.fontFamily, textColor: drawStyle.value.textColor, diff --git a/frontend/src/modules/MapStudio/types/index.ts b/frontend/src/modules/MapStudio/types/index.ts index e37e162c..bb70f8e0 100644 --- a/frontend/src/modules/MapStudio/types/index.ts +++ b/frontend/src/modules/MapStudio/types/index.ts @@ -163,6 +163,8 @@ export interface DrawStyle { arrowPosition: 'end' | 'both'; /** 箭头大小 */ arrowSize: 'small' | 'medium' | 'large'; + /** 箭头样式 */ + arrowShape: 'triangle' | 'chevron' | 'diamond'; /** 字号 */ fontSize: number; /** 字体 */ @@ -187,6 +189,7 @@ export const DEFAULT_DRAW_STYLE: DrawStyle = { showArrow: true, arrowPosition: 'end', arrowSize: 'medium', + arrowShape: 'triangle', fontSize: 14, fontFamily: 'Microsoft YaHei', textColor: '#ffffff', diff --git a/frontend/src/styles/index.scss b/frontend/src/styles/index.scss index d09926ac..431b807c 100644 --- a/frontend/src/styles/index.scss +++ b/frontend/src/styles/index.scss @@ -118,8 +118,11 @@ svg { .ant-select-tree-node-selected { background-color: #bae7ff !important; } -.ant-empty{ - p{ - text-indent: 0em !important; +.ant-empty { + p { + text-indent: 0em !important; } } +.ant-dropdown { + z-index: 9999 !important; +} diff --git a/frontend/src/views/zhiNengFenXi/zhiNengWenDa/index.vue b/frontend/src/views/zhiNengFenXi/zhiNengWenDa/index.vue new file mode 100644 index 00000000..ec924cd6 --- /dev/null +++ b/frontend/src/views/zhiNengFenXi/zhiNengWenDa/index.vue @@ -0,0 +1,7 @@ + + +