From fb39a7bb69cc55d2e1ce61d47e0677aa40540f95 Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Fri, 30 Jan 2026 16:20:33 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 applications/drone-command/src/views/areaManage/partition/FormDiaLog copy.vue |  671 +++----------------------------------------------------
 1 files changed, 42 insertions(+), 629 deletions(-)

diff --git a/applications/drone-command/src/views/areaManage/partition/FormDiaLog copy.vue b/applications/drone-command/src/views/areaManage/partition/FormDiaLog copy.vue
index cc492ca..302d14e 100644
--- a/applications/drone-command/src/views/areaManage/partition/FormDiaLog copy.vue
+++ b/applications/drone-command/src/views/areaManage/partition/FormDiaLog copy.vue
@@ -12,54 +12,6 @@
 					:layer-mode="4"
 					:boundary="false"
 				/>
-				<div
-					v-if="showTypePanel && !readonly"
-					class="shape-type-panel"
-				>
-					<div class="panel-header">
-						<span>{{ drawTypeLabelMap[currentShapeType] || '区域' }}</span>
-						<el-icon class="panel-close" @click.stop="handleTypePanelClose"><Close /></el-icon>
-					</div>
-					<div class="panel-body">
-						<span class="panel-label">区域类型</span>
-						<el-select
-							class="command-select"
-							popper-class="command-select-popper"
-							v-model="formData.areaType"
-							placeholder="请选择"
-							@change="handleAreaTypeChange"
-						>
-							<el-option
-								v-for="item in dictObj.areaType"
-								:key="item.dictKey"
-								:label="item.dictValue"
-								:value="item.dictKey"
-							/>
-						</el-select>
-					</div>
-				</div>
-				<div class="map-toolbar">
-					<button class="tool-btn" type="button" @click="handleDraw('polygon')">
-						<span class="tool-icon polygon"></span>
-						<span class="tool-text">多边形</span>
-					</button>
-					<button class="tool-btn" type="button" @click="handleDraw('rectangle')">
-						<span class="tool-icon rect"></span>
-						<span class="tool-text">矩形</span>
-					</button>
-					<button class="tool-btn" type="button" @click="handleDraw('ellipse')">
-						<span class="tool-icon ellipse"></span>
-						<span class="tool-text">椭圆</span>
-					</button>
-					<button class="tool-btn" type="button" @click="handleDraw('buffer')">
-						<span class="tool-icon buffer"></span>
-						<span class="tool-text">缓冲圆</span>
-					</button>
-					<button class="tool-btn danger" type="button" @click="handleClearShape">
-						<span class="tool-icon trash"></span>
-						<span class="tool-text">删除</span>
-					</button>
-				</div>
 			</div>
 
 			<div class="right-container">
@@ -180,28 +132,6 @@
 						</el-select>
 					</el-form-item>
 
-					<div class="shape-table-container">
-						<div class="shape-table-title">绘制区域列表</div>
-						<el-table class="command-table" :data="shapeList" row-key="id" height="360">
-							<el-table-column prop="areaType" label="类型" width="120">
-								<template v-slot="{ row }">
-									{{ getDictLabel(row.areaType, dictObj.areaType) }}
-								</template>
-							</el-table-column>
-							<el-table-column prop="drawType" label="绘制类型" width="120">
-								<template v-slot="{ row }">
-									{{ drawTypeLabelMap[row.drawType] || '-' }}
-								</template>
-							</el-table-column>
-							<el-table-column label="操作" class-name="operation-btns">
-								<template v-slot="{ row }">
-									<el-link @click="handleShapeEdit(row)">编辑</el-link>
-									<el-link @click="handleShapeDelete(row)">删除</el-link>
-								</template>
-							</el-table-column>
-						</el-table>
-					</div>
-
 					<div class="search-table-container">
 						<div class="search-box">
 							<div class="label">
@@ -243,17 +173,15 @@
 <script setup>
 import { Close } from '@element-plus/icons-vue'
 
-import { computed, inject, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
+import { computed, inject, nextTick, onMounted, ref, watch } from 'vue'
 import { ElMessage } from 'element-plus'
 import { fwAreaDivideDetailApi, fwAreaDivideSubmitApi } from './partitionApi'
 import { saveOperationLog } from '@ztzf/apis'
 import { useRoute } from 'vue-router'
 import { fieldRules, geomAnalysis, getDictLabel } from '@ztzf/utils'
 import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
-import { DrawManager } from './shapeTools/DrawManager'
-import { EditManager } from './shapeTools/EditManager'
+import { DrawPolygon } from '@/utils/cesium/DrawPolygon'
 import { cartesian3Convert } from '@/utils/cesium/mapUtil'
-import { buildEllipsePositions } from './shapeTools/shapeUtils'
 import * as turf from '@turf/turf'
 import * as Cesium from 'cesium'
 import { fwPoliceStationListApi } from '@/views/areaManage/precinctInfo/precinctInfoApi'
@@ -291,39 +219,9 @@
 const deviceOptions = ref([]) // 关联设备
 const dictObj = inject('dictObj')
 const mapRef = ref(null)
-const currentShapeType = ref('polygon')
-const shapeList = ref([])
-const activeShapeId = ref(null)
-const drawTypeLabelMap = {
-	polygon: '多边形',
-	rectangle: '矩形',
-	ellipse: '椭圆',
-	buffer: '缓冲圆',
-}
-const showTypePanel = ref(false)
-const suppressTypePanelOnce = ref(false)
-const areaTypeStyleMap = {
-	'1': {
-		fill: Cesium.Color.fromBytes(25, 178, 230, 128),
-		outline: Cesium.Color.fromBytes(0, 251, 255, 255),
-	},
-	'2': {
-		fill: Cesium.Color.fromBytes(255, 235, 59, 128),
-		outline: Cesium.Color.fromBytes(255, 235, 59, 255),
-	},
-	'3': {
-		fill: Cesium.Color.fromBytes(247, 20, 20, 128),
-		outline: Cesium.Color.fromBytes(255, 0, 0, 255),
-	},
-}
 let viewer
-let drawManager
-let editManager
-let activeTool
+let drawPolygonExample
 let pointList = []
-let viewEntity
-let shapeDisplaySource
-const activeToolMode = ref('')
 
 const rules = {
 	areaName: fieldRules(true, 50),
@@ -408,24 +306,6 @@
 		formData.value.flyDateEnd = flyDateRange.value[1] || ''
 	}
 )
-watch(
-	() => visible.value,
-	val => {
-		if (!val) {
-			viewEntity && viewer?.entities?.remove(viewEntity)
-			viewEntity = null
-			clearActiveTool()
-			hideTypePanel()
-			clearShapeDisplay()
-		}
-	}
-)
-watch(
-	() => formData.value.areaType,
-	val => {
-		updateActiveShapeAreaType(val)
-	}
-)
 
 // 加载详情
 async function loadDetail () {
@@ -454,191 +334,14 @@
 	viewer = map?.viewer || null
 }
 
-function ensureShapeDisplaySource () {
-	if (!viewer) return null
-	if (!shapeDisplaySource) {
-		shapeDisplaySource = new Cesium.CustomDataSource('partition-shape-display')
-		viewer.dataSources.add(shapeDisplaySource)
-	}
-	return shapeDisplaySource
-}
-
-function clearShapeDisplay () {
-	if (!shapeDisplaySource) return
-	shapeDisplaySource.entities.removeAll()
-}
-
-function normalizeShapePoint (point) {
-	const lng = point?.lng ?? point?.longitude
-	const lat = point?.lat ?? point?.latitude
-	if (!Number.isFinite(Number(lng)) || !Number.isFinite(Number(lat))) return null
-	return {
-		lng: Number(lng),
-		lat: Number(lat),
-		height: Number.isFinite(Number(point?.height)) ? Number(point.height) : 0,
-	}
-}
-
-function buildShapePositions (points = []) {
-	const normalized = points.map(normalizeShapePoint).filter(Boolean)
-	return normalized.map(point =>
-		Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height)
-	)
-}
-
-function getAreaTypeStyle (areaType) {
-	return areaTypeStyleMap?.[String(areaType)] || {
-		fill: Cesium.Color.fromBytes(45, 140, 240, 99),
-		outline: Cesium.Color.fromBytes(45, 140, 240, 255),
-	}
-}
-
-function renderShapeList () {
-	if (!viewer || !visible.value || readonly.value) {
-		clearShapeDisplay()
-		return
-	}
-	const dataSource = ensureShapeDisplaySource()
-	if (!dataSource) return
-	dataSource.entities.removeAll()
-	shapeList.value.forEach(shape => {
-		if (!shape?.points?.length) return
-		if (activeToolMode.value === 'edit' && shape.id === activeShapeId.value) return
-		if (shape.drawType === 'buffer' && shape.meta?.bufferRadii?.length && shape.meta?.center) {
-			const center = shape.meta.center
-			const centerCartesian = Cesium.Cartesian3.fromDegrees(center.lng, center.lat, center.height || 0)
-			const [radius1, radius2, radius3] = shape.meta.bufferRadii
-			const radii = [radius1, radius2, radius3].filter(item => Number.isFinite(item) && item > 0)
-			if (radii.length) {
-				const styles = [
-					{
-						fill: Cesium.Color.fromBytes(247, 20, 20, 128),
-						outline: Cesium.Color.fromBytes(255, 0, 0, 255),
-					},
-					{
-						fill: Cesium.Color.fromBytes(255, 235, 59, 128),
-						outline: Cesium.Color.fromBytes(255, 235, 59, 255),
-					},
-					{
-						fill: Cesium.Color.fromBytes(25, 178, 230, 128),
-						outline: Cesium.Color.fromBytes(0, 251, 255, 255),
-					},
-				]
-				radii.forEach((radius, index) => {
-					const style = styles[index] || styles[styles.length - 1]
-					dataSource.entities.add({
-						name: 'shape-display',
-						customData: { shapeId: shape.id, drawType: shape.drawType, level: index + 1 },
-						position: centerCartesian,
-						ellipse: {
-							semiMajorAxis: radius,
-							semiMinorAxis: radius,
-							material: style.fill,
-							outline: false,
-							heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
-						},
-					})
-					const positions = buildEllipsePositions(centerCartesian, radius, radius)
-					dataSource.entities.add({
-						name: 'shape-display',
-						customData: { shapeId: shape.id, drawType: shape.drawType, level: index + 1, outline: true },
-						polyline: {
-							positions: positions.length ? [...positions, positions[0]] : positions,
-							clampToGround: true,
-							width: 2,
-							material: style.outline,
-						},
-					})
-				})
-			}
-			return
-		}
-
-		const positions = buildShapePositions(shape.points)
-		if (positions.length < 3) return
-		const style = getAreaTypeStyle(shape.areaType)
-		dataSource.entities.add({
-			name: 'shape-display',
-			customData: { shapeId: shape.id, drawType: shape.drawType },
-			polygon: {
-				hierarchy: new Cesium.PolygonHierarchy(positions),
-				material: style.fill,
-				outline: false,
-				heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
-			},
-			polyline: {
-				positions: positions.length ? [...positions, positions[0]] : positions,
-				clampToGround: true,
-				width: 2,
-				material: style.outline,
-			},
-		})
-	})
-}
-
 // 绘制完成回调
 const drawFinished = async data => {
-	const positions = Array.isArray(data?.positions) ? data.positions : data
-	if (!Array.isArray(positions) || positions.length < 3) {
-		pointList = []
-		formData.value.areaSize = null
-		formData.value.longitude = null
-		formData.value.latitude = null
-		hideTypePanel()
-		return
-	}
-	const meta = data?.meta
-	const bufferRadii = Array.isArray(meta?.bufferRadii) ? meta.bufferRadii : null
-	const centerCartesian = meta?.center
-	const centerLngLat = centerCartesian ? cartesian3Convert(centerCartesian, viewer) : null
-	pointList = _.cloneDeep(positions).map(item => {
+	pointList = _.cloneDeep(data).map(item => {
 		const val = cartesian3Convert(item, viewer)
 		return { ...val, lng: val.longitude, lat: val.latitude }
 	})
-	applyPolygonMetrics(pointList)
-	if (!formData.value.areaType) {
-		const detectAreaType = getDetectAreaTypeKey()
-		if (detectAreaType) {
-			formData.value.areaType = detectAreaType
-		}
-	}
-	if (!suppressTypePanelOnce.value) {
-		showTypePanelAtCurrent()
-	}
-	suppressTypePanelOnce.value = false
-
-	if (!activeShapeId.value) {
-		activeShapeId.value = `shape_${Date.now()}_${Math.random().toString(16).slice(2, 6)}`
-	}
-	const targetIndex = shapeList.value.findIndex(item => item.id === activeShapeId.value)
-	const shapePayload = {
-		id: activeShapeId.value,
-		areaType: formData.value.areaType,
-		drawType: currentShapeType.value,
-		points: _.cloneDeep(pointList),
-		meta: bufferRadii && centerLngLat
-			? {
-				bufferRadii,
-				center: {
-					lng: centerLngLat.longitude,
-					lat: centerLngLat.latitude,
-					height: centerLngLat.height ?? 0,
-				},
-			}
-			: null,
-	}
-	if (targetIndex === -1) {
-		shapeList.value.push(shapePayload)
-	} else {
-		shapeList.value.splice(targetIndex, 1, shapePayload)
-	}
-	renderShapeList()
-}
-
-function applyPolygonMetrics(points) {
-	if (!points?.length) return
 	const polygon = turf.polygon([
-		[...points.map(item => [item.longitude, item.latitude]), [points[0].longitude, points[0].latitude]],
+		[...pointList.map(item => [item.longitude, item.latitude]), [pointList[0].longitude, pointList[0].latitude]],
 	])
 	const center = turf.centerOfMass(polygon)
 	const areaSqm = turf.area(polygon) // 平方米
@@ -647,152 +350,41 @@
 	formData.value.latitude = center.geometry.coordinates[1]
 }
 
-function getDetectAreaTypeKey () {
-	const areaTypeOptions = Array.isArray(dictObj?.value?.areaType)
-		? dictObj.value.areaType
-		: dictObj?.areaType
-	if (!Array.isArray(areaTypeOptions)) return ''
-	const target = areaTypeOptions.find(item => item?.dictKey === '1')
-	return target?.dictKey ?? ''
+// 新增模式绘制
+function addPolygon () {
+	drawPolygonExample = new DrawPolygon(viewer)
+	drawPolygonExample.initHandler(viewer)
+	drawPolygonExample.subscribe('getPolygonPositions', drawFinished)
 }
 
-function showTypePanelAtCurrent () {
-	if (readonly.value) return
-	showTypePanel.value = true
-}
-
-function hideTypePanel () {
-	showTypePanel.value = false
-}
-
-function handleTypePanelClose () {
-	hideTypePanel()
-	if (readonly.value) return
-	if (activeToolMode.value !== 'edit') return
-	const positions = activeTool?.getPositions?.()
-	if (Array.isArray(positions) && positions.length >= 3) {
-		suppressTypePanelOnce.value = true
-		drawFinished(positions)
-	}
-	clearActiveTool()
-}
-
-function handleAreaTypeChange (value) {
-	updateActiveShapeAreaType(value)
-}
-
-function updateActiveShapeAreaType (value) {
-	if (currentShapeType.value !== 'buffer') {
-		activeTool?.setStyle?.(getAreaTypeStyle(value))
-	}
-	if (!activeShapeId.value) return
-	const targetIndex = shapeList.value.findIndex(item => item.id === activeShapeId.value)
-	if (targetIndex === -1) return
-	const target = shapeList.value[targetIndex]
-	shapeList.value.splice(targetIndex, 1, {
-		...target,
-		areaType: value,
-	})
-	renderShapeList()
-}
-
-// Tool lifecycle
-function clearActiveTool () {
-	activeTool?.destroy?.()
-	activeTool = null
-	drawManager?.destroy()
-	editManager?.destroy()
-	activeToolMode.value = ''
-	renderShapeList()
-}
-
-function startDraw (type) {
-	currentShapeType.value = type
-	activeToolMode.value = 'draw'
-	drawManager ||= new DrawManager(viewer)
-	activeTool = drawManager.start(type, { style: getAreaTypeStyle(formData.value.areaType) })
-	activeTool?.subscribe('getPolygonPositions', drawFinished)
-}
-
-function startEdit (type, points) {
-	currentShapeType.value = type
-	activeToolMode.value = 'edit'
-	editManager ||= new EditManager(viewer)
-	activeTool = editManager.start(type, points, { style: getAreaTypeStyle(formData.value.areaType) })
-	activeTool?.subscribe('getPolygonPositions', drawFinished)
-}
-
-function handleDraw (type) {
-	if (readonly.value) return
-	if (!viewer) return
-	clearActiveTool()
-	viewEntity && viewer?.entities?.remove(viewEntity)
-	viewEntity = null
-	hideTypePanel()
-	renderShapeList()
-	if (dialogMode.value === 'edit' && pointList.length >= 3) {
-		const editPoints = _.cloneDeep(pointList)
-		if (editPoints.length > 1) {
-			const first = editPoints[0]
-			const last = editPoints[editPoints.length - 1]
-			if (first.longitude === last.longitude && first.latitude === last.latitude) {
-				editPoints.pop()
-			}
+// 编辑面
+function editPolygon () {
+	if (!formData.value?.geom) return
+	pointList = geomAnalysis(formData.value.geom)
+	drawPolygonExample?.destroy()
+	drawPolygonExample = new DrawPolygon(viewer)
+	let pointList1 = _.cloneDeep(pointList)
+	pointList1.pop()
+	drawPolygonExample.initPolygon(
+		viewer,
+		pointList.map(item => ({ lng: item.longitude, lat: item.latitude }))
+	)
+	drawPolygonExample.subscribe('getPolygonPositions', drawFinished)
+	if (pointList1.length) {
+		const result = pointList1.map(item => [item.longitude, item.latitude]).flat()
+		const tempEntity = viewer.entities?.add({
+			position: Cesium.Cartesian3.fromDegrees(result[0], result[1]),
+			polyline: {
+				positions: Cesium.Cartesian3.fromDegreesArray(result),
+				clampToGround: true,
+				width: 1,
+				material: Cesium.Color.TRANSPARENT,
+			},
+		})
+		if (tempEntity) {
+			viewer.flyTo(tempEntity, { duration: 0 })
+			viewer.entities.remove(tempEntity)
 		}
-		activeShapeId.value = activeShapeId.value || (shapeList.value[0]?.id ?? null)
-		startEdit(type, editPoints)
-		return
-	}
-	const defaultAreaType = getDetectAreaTypeKey()
-	if (defaultAreaType) {
-		formData.value.areaType = defaultAreaType
-	}
-	activeShapeId.value = null
-	startDraw(type)
-}
-
-function handleClearShape () {
-	if (readonly.value) return
-	clearActiveTool()
-	viewEntity && viewer?.entities?.remove(viewEntity)
-	viewEntity = null
-	pointList = []
-	shapeList.value = []
-	activeShapeId.value = null
-	formData.value.areaSize = null
-	formData.value.longitude = null
-	formData.value.latitude = null
-	hideTypePanel()
-	clearShapeDisplay()
-}
-
-function handleShapeEdit (row) {
-	if (!row?.points?.length) return
-	if (activeToolMode.value === 'edit' && activeShapeId.value === row.id) return
-	activeShapeId.value = row.id
-	currentShapeType.value = row.drawType
-	formData.value.areaType = row.areaType
-	pointList = _.cloneDeep(row.points)
-	clearActiveTool()
-	const editPayload = row.drawType === 'buffer' ? { points: row.points, meta: row.meta } : row.points
-	startEdit(row.drawType, editPayload)
-	applyPolygonMetrics(pointList)
-	showTypePanelAtCurrent()
-	renderShapeList()
-}
-
-function handleShapeDelete (row) {
-	if (!row) return
-	shapeList.value = shapeList.value.filter(item => item.id !== row.id)
-	renderShapeList()
-	if (activeShapeId.value === row.id) {
-		activeShapeId.value = null
-		clearActiveTool()
-		pointList = []
-		formData.value.areaSize = null
-		formData.value.longitude = null
-		formData.value.latitude = null
-		hideTypePanel()
 	}
 }
 
@@ -801,7 +393,7 @@
 	if (!formData.value?.geom) return
 	pointList = geomAnalysis(formData.value.geom)
 	const result = pointList.map(item => [item.longitude, item.latitude]).flat()
-	viewEntity = viewer.entities?.add({
+	const mian = viewer.entities?.add({
 		customType: 'control_group',
 		position: Cesium.Cartesian3.fromDegrees(result[0], result[1]),
 		polyline: {
@@ -811,7 +403,7 @@
 			material: Cesium.Color.RED,
 		},
 	})
-	viewer.flyTo(viewEntity, { duration: 0 })
+	viewer.flyTo(mian, { duration: 0 })
 }
 
 // 获取派出所列表
@@ -857,32 +449,14 @@
 	dialogMode.value = mode || 'add'
 	formData.value = dialogMode.value === 'add' ? initForm() : row
 	selectedDeviceRows.value = []
-	shapeList.value = []
-	activeShapeId.value = null
 	await nextTick()
 	initMap()
-	clearShapeDisplay()
-	viewEntity && viewer?.entities?.remove(viewEntity)
-	viewEntity = null
-	clearActiveTool()
 	await getDeviceList()
 	if (dialogMode.value === 'add') {
-		// default no draw mode
+		addPolygon()
 	} else if (dialogMode.value === 'edit') {
 		await loadDetail()
-		pointList = geomAnalysis(formData.value.geom) || []
-		if (pointList.length) {
-			activeShapeId.value = `shape_${Date.now()}_${Math.random().toString(16).slice(2, 6)}`
-			shapeList.value = [
-				{
-					id: activeShapeId.value,
-					areaType: formData.value.areaType,
-					drawType: currentShapeType.value,
-					points: _.cloneDeep(pointList),
-				},
-			]
-		}
-		viewPolygon()
+		editPolygon()
 	} else {
 		await loadDetail()
 		viewPolygon()
@@ -896,170 +470,9 @@
 	getDeviceList()
 })
 
-onBeforeUnmount(() => {
-	hideTypePanel()
-})
-
 defineExpose({
 	open,
 })
 </script>
 
-<style scoped lang="scss">
-.left-container {
-	position: relative;
-}
-
-.shape-type-panel {
-	position: absolute;
-	right: 16px;
-	bottom: 16px;
-	z-index: 6;
-	min-width: 260px;
-	background: rgba(22, 33, 44, 0.9);
-	border: 1px solid rgba(255, 255, 255, 0.15);
-	border-radius: 8px;
-	box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35);
-	backdrop-filter: blur(6px);
-	color: #e5e7f0;
-}
-
-.panel-header {
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	padding: 8px 12px;
-	border-bottom: 1px solid rgba(255, 255, 255, 0.12);
-	font-size: 13px;
-	font-weight: 600;
-}
-
-.panel-close {
-	cursor: pointer;
-	color: rgba(255, 255, 255, 0.7);
-}
-
-.panel-body {
-	display: flex;
-	align-items: center;
-	gap: 8px;
-	padding: 10px 12px 12px;
-}
-
-.panel-label {
-	font-size: 12px;
-	color: rgba(255, 255, 255, 0.75);
-	white-space: nowrap;
-}
-
-.map-toolbar {
-	position: absolute;
-	top: 64px;
-	right: 16px;
-	display: flex;
-	flex-direction: column;
-	gap: 10px;
-	padding: 10px 8px;
-	background: rgba(19, 28, 36, 0.75);
-	backdrop-filter: blur(4px);
-	border-radius: 8px;
-	box-shadow: 0 6px 18px rgba(0, 0, 0, 0.2);
-}
-
-.tool-btn {
-	display: flex;
-	flex-direction: column;
-	align-items: center;
-	gap: 6px;
-	width: 64px;
-	padding: 8px 6px;
-	background: rgba(255, 255, 255, 0.08);
-	border: 1px solid rgba(255, 255, 255, 0.18);
-	border-radius: 6px;
-	color: #ffffff;
-	font-size: 12px;
-	line-height: 1;
-	cursor: pointer;
-	transition: all 0.2s ease;
-}
-
-.tool-btn:hover {
-	background: rgba(255, 255, 255, 0.16);
-	border-color: rgba(255, 255, 255, 0.35);
-	transform: translateY(-1px);
-}
-
-.tool-btn:active {
-	transform: translateY(0);
-}
-
-.tool-btn.danger {
-	border-color: rgba(255, 112, 112, 0.6);
-	color: #ffb3b3;
-}
-
-.tool-icon {
-	position: relative;
-	width: 20px;
-	height: 20px;
-	border: 2px solid #ffffff;
-	border-radius: 3px;
-}
-
-.tool-icon.polygon {
-	border-radius: 4px;
-	transform: rotate(15deg);
-}
-
-.tool-icon.rect {
-	border-radius: 2px;
-}
-
-.tool-icon.ellipse {
-	border-radius: 50%;
-}
-
-.tool-icon.buffer {
-	border-radius: 50%;
-	box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.5);
-}
-
-.tool-icon.trash {
-	border: none;
-	box-shadow: none;
-}
-
-.tool-icon.trash::before,
-.tool-icon.trash::after {
-	content: "";
-	position: absolute;
-	left: 4px;
-	right: 4px;
-	background: #ffffff;
-}
-
-.tool-icon.trash::before {
-	top: 4px;
-	height: 10px;
-	border-radius: 2px;
-}
-
-.tool-icon.trash::after {
-	top: 1px;
-	height: 3px;
-	border-radius: 2px;
-}
-
-.shape-table-container {
-	margin-top: 8px;
-	padding: 8px;
-	border-radius: 8px;
-	background: rgba(27, 34, 56, 0.6);
-}
-
-.shape-table-title {
-	margin-bottom: 8px;
-	color: #e5e7f0;
-	font-size: 13px;
-}
-</style>
+<style scoped lang="scss"></style>

--
Gitblit v1.9.3