| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604 |
- <template>
- <div id="controlPanelBox">
- <div>
- <div class="sceneNameBox">
- <div class="">
- 场景名称:
- <el-cascader
- :disabled="$route.query.sceneId"
- v-model="SceneValue"
- placeholder="试试搜索:距离"
- :options="SceneList"
- :props="{ expandTrigger: 'hover' }"
- @change="handleChange"
- filterable
- ></el-cascader>
- <el-tooltip
- v-if="SceneValue && SceneRule[SceneValue].functionalDefinition"
- :content="SceneRule[SceneValue].functionalDefinition"
- placement="bottom"
- :popper-style="{ maxWidth: '300px' }"
- >
- <el-icon
- style="margin-left: 1rem; width: 1rem; height: 1rem"
- v-show="SceneValue && SceneRule[SceneValue].functionalDefinition"
- ><QuestionFilled
- /></el-icon>
- </el-tooltip>
- </div>
- <div>
- <el-button type="primary" @click="sendGeometriesToBackend"
- >发送<i class="el-icon-s-promotion el-icon--right"></i
- ></el-button>
- </div>
- </div>
- <el-divider></el-divider>
- <div
- v-if="
- SceneValue &&
- SceneRule[SceneValue] &&
- (SceneRule[SceneValue].elementTypes.includes('point') ||
- SceneRule[SceneValue].elementTypes.includes('polyline') ||
- SceneRule[SceneValue].elementTypes.includes('polygon'))
- "
- >
- 元素个数:{{
- SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].numberOf : ""
- }}
- </div>
- <div>
- 参数类型:{{
- SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].elementTypes : ""
- }}
- </div>
- <div>
- 接口地址:{{
- SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].apiUrl : ""
- }}
- </div>
- </div>
- <el-divider></el-divider>
- <div>
- <!-- 元素文本渲染和操作区域 -->
- <el-tabs tab-position="left" style="height: calc(100vh - 370px)" class="demo-tabs">
- <el-tab-pane label="入参">
- <div
- v-if="
- SceneValue &&
- SceneRule[SceneValue] &&
- SceneRule[SceneValue].elementTypes.includes('file')
- "
- >
- <el-upload
- v-model:file-list="fileList"
- class="upload-demo"
- action=""
- :limit="1"
- :on-change="handleFileChange"
- :on-exceed="handleExceed"
- :on-remove="uploadRemove"
- :auto-upload="false"
- >
- <el-button type="primary">上传文件</el-button>
- </el-upload>
- </div>
- <div v-if="SceneValue && SceneRule[SceneValue]">
- <div
- v-for="item in SceneRule[SceneValue].elementTypes"
- :key="item"
- style="margin-top: 0.5rem"
- >
- <div
- v-if="SceneValue && SceneRule[SceneValue] && SceneRule[SceneValue][item]"
- >
- {{ item }}:<el-select
- v-if="SceneRule[SceneValue][item]"
- v-model="params[item]"
- :placeholder="'请选择' + item"
- style="width: 240px"
- >
- <el-option
- v-for="item in SceneRule[SceneValue][item]"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </div>
- <div v-if="['lon', 'lat', 'filePath', 'EPSILON'].includes(item)">
- {{ item }}:
- <el-input
- v-model="params[item]"
- style="width: 240px"
- :placeholder="'请输入' + item"
- />
- </div>
- </div>
- </div>
- <json-viewer
- v-if="
- SceneValue &&
- SceneRule[SceneValue] &&
- (SceneRule[SceneValue].elementTypes.includes('point') ||
- SceneRule[SceneValue].elementTypes.includes('polyline') ||
- SceneRule[SceneValue].elementTypes.includes('polygon'))
- "
- :value="jsonData"
- :editable="true"
- :preview-mode="false"
- style="
- pointer-events: auto;
- max-height: calc(100vh - 370px) !important;
- overflow-y: scroll !important;
- "
- copyable
- @input="handleJsonInput"
- />
- </el-tab-pane>
- <el-tab-pane label="返回">
- <div
- v-if="backData.message || backData.error"
- :style="{
- backgroundColor: backData.code === 200 ? '#67C23A' : '#F56C6C',
- color: '#fff',
- padding: '5px 10px',
- fontSize: '14px',
- }"
- >
- {{ backData.message || backData.error }}
- </div>
- <json-viewer
- :value="backData.content"
- :editable="true"
- :preview-mode="false"
- style="
- pointer-events: auto;
- max-height: calc(100vh - 370px) !important;
- overflow-y: scroll !important;
- "
- copyable
- /></el-tab-pane>
- </el-tabs>
- </div>
- <!-- 绘制工具栏 -->
- <div
- class="toolbar"
- v-if="
- SceneValue &&
- SceneRule[SceneValue] &&
- (SceneRule[SceneValue].elementTypes.includes('point') ||
- SceneRule[SceneValue].elementTypes.includes('polyline') ||
- SceneRule[SceneValue].elementTypes.includes('polygon'))
- "
- >
- <div
- class="tool-item"
- @click="activateDraw('point')"
- :class="{ active: currentTool === 'point' }"
- >
- 绘制点
- <el-tooltip
- content="绘制开关,蓝色状态代表开启,再次点击结束绘制,地图左键点击选点,"
- placement="right"
- >
- <el-icon style="width: 1rem; height: 1rem"><QuestionFilled /></el-icon>
- </el-tooltip>
- </div>
- <div
- class="tool-item"
- @click="activateDraw('polyline')"
- :class="{ active: currentTool === 'polyline' }"
- >
- 绘制线<el-tooltip
- content="绘制线最少需要两个点,鼠标左键点击选点,点之间自动连线,鼠标右键结束绘制"
- placement="right"
- >
- <el-icon style="width: 1rem; height: 1rem"><QuestionFilled /></el-icon>
- </el-tooltip>
- </div>
- <div
- class="tool-item"
- @click="activateDraw('polygon')"
- :class="{ active: currentTool === 'polygon' }"
- >
- 绘制面<el-tooltip
- content="绘制面最少需要三个点,鼠标左键点击选点,面自动必合,鼠标右键结束绘制"
- placement="right"
- >
- <el-icon style="width: 1rem; height: 1rem"><QuestionFilled /></el-icon>
- </el-tooltip>
- </div>
- <!-- <div class="tool-item" @click="startHoleDrawing" :class="{ active: isDrawingHole }">
- 绘制镂空
- </div> -->
- <div class="tool-item" @click="clearAll">清除所有</div>
- </div>
- </div>
- </template>
- <script>
- import sksjgl from "../../api/sksjgl";
- // 控制面板
- export default {
- name: "ControlPanel",
- // 2. 接收父组件传递的 props(单向数据流,子组件不能直接修改)
- props: {
- btnText: {
- type: String, // 类型限制
- default: "默认按钮", // 默认值
- required: false, // 是否必传
- },
- showCount: {
- type: Boolean,
- default: false,
- },
- },
- data() {
- return {
- currentFile: null, // 当前选中的文件
- fileList: [],
- // 其他参数
- params: {
- unit: "",
- outFileType: "",
- outPrj: "",
- inPrj: "",
- lon: "",
- lat: "",
- },
- // 请求参数
- jsonData: {},
- // 返回参数
- backData: {},
- // 当前场景值
- SceneValue: "",
- // 场景列表
- SceneList: [
- {
- value: "1.5.1",
- label: "1.5.1拓扑计算",
- children: [
- {
- value: "1.5.1.1",
- label: "点线面拓扑关系",
- },
- ],
- },
- {
- value: "1.5.2",
- label: "1.5.2空间量算",
- children: [
- {
- value: "1.5.2.1",
- label: "两点欧氏距离",
- },
- {
- value: "1.5.2.2",
- label: "点到线的最短距离",
- },
- {
- value: "1.5.2.3",
- label: "点到面的最短距离",
- },
- {
- value: "1.5.2.4",
- label: "面到面的最短距离",
- },
- {
- value: "1.5.2.5",
- label: "折线距离(累加线段长度)",
- },
- {
- value: "1.5.2.6",
- label: "平面面积、不规则面面积",
- },
- {
- value: "1.5.2.7",
- label: "曲面面积,考虑地形起伏",
- },
- {
- value: "1.5.2.8",
- label: "单点高程查询",
- },
- {
- value: "1.5.2.9",
- label: "两点高程差",
- },
- {
- value: "1.5.2.10",
- label: "区域高程统计",
- },
- {
- value: "1.5.4.5",
- label: "缓冲区计算",
- },
- ],
- },
- {
- value: "1.5.3",
- label: "1.5.3几何运算",
- children: [
- {
- value: "1.5.3.1",
- label: "并集运算",
- },
- {
- value: "1.5.3.2",
- label: "交集运算",
- },
- {
- value: "1.5.3.3",
- label: "差集运算",
- },
- {
- value: "1.5.3.4",
- label: "几何参数计算",
- },
- ],
- },
- {
- value: "1.5.4",
- label: "1.5.4关系分析",
- children: [
- {
- value: "1.5.4.1",
- label: "邻接关系分析",
- },
- {
- value: "1.5.4.2",
- label: "包含关系分析",
- },
- {
- value: "1.5.4.3",
- label: "相交关系分析",
- },
- {
- value: "1.5.4.4",
- label: "相离关系分析",
- },
- ],
- },
- {
- value: "1.5.5",
- label: "1.5.5非空间数据转换",
- children: [
- {
- value: "1.5.5.1",
- label: "非空间数据转空间数据",
- },
- ],
- },
- {
- value: "1.5.6",
- label: "1.5.6坐标转换",
- children: [
- {
- value: "1.5.6.1",
- label: "单点的坐标转换接口",
- },
- ],
- },
- {
- value: "1.5.7",
- label: "1.5.7时空数据格式转换",
- children: [
- {
- value: "1.5.7.1",
- label: "文件格式转换",
- },
- {
- value: "1.5.7.2",
- label: "转换文件下载",
- },
- ],
- },
- ],
- // 场景规则
- SceneRule: {
- "1.5.1.1": {
- // 功能描述
- functionalDefinition:
- "拓扑计算功能聚焦于深度解析大批量数据的点、线、面之间的拓扑关系,能够精准判断点与线、面的位置关系,以及线、面之间的相交、平行、邻接、包含等复杂状态。借助四叉树、R 树等精心设计的数据结构,结合 Douglas - Peucker 等高效算法,确保在处理海量空间数据时,也能快速且准确地输出分析结果。",
- // 元素类型
- elementTypes: ["point", "polyline", "polygon"],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/topology/geoJsonToGeoJson",
- },
- "1.5.2.1": {
- // 功能描述
- functionalDefinition:
- "计算两个点要素之间的最短空间距离,单位支持米、千米。操作逻辑为:用户通过接口输入两点经纬度坐标,或在系统内部地图上点击选择两点,系统基于坐标系参数计算欧氏距离。例如:计算青浦区某学校与社区卫生服务中心的直线距离,用于公共服务覆盖半径评估;计算两个监测点位的直线距离,用于监测设备信号覆盖范围判断。",
- // 元素类型
- elementTypes: ["point", "point", "unit"],
- // 单位
- unit: [
- {
- value: "METER",
- label: "米",
- },
- {
- value: "KILOMETER",
- label: "千米",
- },
- ],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/spatialMeasure/pointToPoint",
- },
- "1.5.2.2": {
- // 功能描述
- functionalDefinition: "计算点和线要素之间的最短空间距离,单位支持米、千米",
- // 元素类型
- elementTypes: ["point", "polyline", "unit"],
- // 单位
- unit: [
- {
- value: "METER",
- label: "米",
- },
- {
- value: "KILOMETER",
- label: "千米",
- },
- ],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/spatialMeasure/pointToLine",
- },
- "1.5.2.3": {
- // 功能描述
- functionalDefinition: "计算点和面要素之间的最短空间距离,单位支持米、千米",
- // 元素类型
- elementTypes: ["point", "polygon", "unit"],
- // 单位
- unit: [
- {
- value: "METER",
- label: "米",
- },
- {
- value: "KILOMETER",
- label: "千米",
- },
- ],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/spatialMeasure/pointToPolygon",
- },
- "1.5.2.4": {
- // 功能描述
- functionalDefinition: "计算两个面要素之间的最短空间距离,单位支持米、千米",
- // 元素类型
- elementTypes: ["polygon", "polygon", "unit"],
- // 单位
- unit: [
- {
- value: "METER",
- label: "米",
- },
- {
- value: "KILOMETER",
- label: "千米",
- },
- ],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/spatialMeasure/PolygonToPolygon",
- },
- "1.5.2.5": {
- // 功能描述
- functionalDefinition: "计算多条线段组成的折线总长度,单位支持米、千米",
- // 元素类型
- elementTypes: ["polyline", "unit"],
- // 单位
- unit: [
- {
- value: "METER",
- label: "米",
- },
- {
- value: "KILOMETER",
- label: "千米",
- },
- ],
- // 元素个数
- numberOf: 1,
- // 后台接口路径
- apiUrl: "/spatialMeasure/calculatePolylineDistance",
- },
- "1.5.2.6": {
- // 功能描述
- functionalDefinition:
- "计算面要素在二维平面上的投影面积,单位支持平方米、公顷、平方千米切换",
- // 元素类型
- elementTypes: ["polygon", "unit"],
- // 单位
- unit: [
- {
- value: "SQUARE_METER",
- label: "平方米",
- },
- {
- value: "HECTARE",
- label: "公顷",
- },
- {
- value: "SQUARE_KILOMETER",
- label: "平方千米",
- },
- ],
- // 元素个数
- numberOf: 1,
- // 后台接口路径
- apiUrl: "/spatialMeasure/calculatePlaneAreaInGeometry",
- },
- "1.5.2.7": {
- // 功能描述
- functionalDefinition:
- "结合 DEM 高程数据,计算面要素在三维地形上的实际曲面面积(考虑地形起伏),精度依赖 DEM 数据分辨率。,单位支持平方米、公顷、平方千米切换",
- // 元素类型
- elementTypes: ["polygon", "unit"],
- // 单位
- unit: [
- {
- value: "SQUARE_METER",
- label: "平方米",
- },
- {
- value: "HECTARE",
- label: "公顷",
- },
- {
- value: "SQUARE_KILOMETER",
- label: "平方千米",
- },
- ],
- // 元素个数
- numberOf: 1,
- // 后台接口路径
- apiUrl: "/spatialMeasure/calculateSurfaceAreaInGeometry",
- },
- "1.5.2.8": {
- // 功能描述
- functionalDefinition:
- "查询单个点要素的海拔高度(基于 CGCS2000 大地高程基准),单位为米",
- // 元素类型
- elementTypes: ["point"],
- // 元素个数
- numberOf: 1,
- // 后台接口路径
- apiUrl: "/spatialMeasure/getPointElevationInGeometry",
- },
- "1.5.2.9": {
- // 功能描述
- functionalDefinition:
- "计算两个点要素之间的高程差值,支持正负值显示(正值表示前者高于后者,负值相反)",
- // 元素类型
- elementTypes: ["point", "point"],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/spatialMeasure/calculateElevationDiffInGeometry",
- },
- "1.5.2.10": {
- // 功能描述
- functionalDefinition:
- "查询单个面要素的海拔高度(基于 CGCS2000 大地高程基准),单位为米",
- // 元素类型
- elementTypes: ["polygon"],
- // 元素个数
- numberOf: 1,
- // 后台接口路径
- apiUrl: "/spatialMeasure/calculateAreaElevationStatsInGeometry",
- },
- "1.5.3.1": {
- // 功能描述
- functionalDefinition:
- "将两个或多个不重叠 / 部分重叠的面要素,合并为一个连续的新面要素(消除重叠部分,保留所有要素的覆盖范围)",
- // 元素类型
- elementTypes: ["polygon"],
- // 元素个数
- minNumberOf: 2,
- // 后台接口路径
- apiUrl: "/geometry/union",
- },
- "1.5.3.2": {
- // 功能描述
- functionalDefinition:
- "提取两个或多个面要素之间的重叠区域,生成新的面要素(仅保留所有要素共同覆盖的范围)",
- // 元素类型
- elementTypes: ["polygon"],
- // 元素个数
- minNumberOf: 2,
- // 后台接口路径
- apiUrl: "/geometry/intersection",
- },
- "1.5.3.3": {
- // 功能描述
- functionalDefinition:
- "以一个面要素(称为 “源面”)为基础,减去与另一个面要素(称为 “裁剪面”)的重叠区域,生成新的面要素(保留源面中未被裁剪面覆盖的部分)",
- // 元素类型
- elementTypes: ["polygon"],
- // 元素个数
- minNumberOf: 2,
- // 后台接口路径
- apiUrl: "/geometry/difference",
- },
- "1.5.3.4": {
- // 功能描述
- functionalDefinition:
- "计算面要素的参数(面积、周长、中心坐标、最小外接矩形等)",
- // 元素类型
- elementTypes: ["point", "polyline", "polygon"],
- // 元素个数
- numberOf: 1,
- // 后台接口路径
- apiUrl: "/geometry/parameters",
- },
- "1.5.4.1": {
- // 功能描述
- functionalDefinition:
- "判断两个面要素是否 “边界接触但不重叠”,且距离小于等于自定义阈值(默认 1 米,可通过接口参数调整),核心用于 “相邻区域联动” 场景",
- // 元素类型
- elementTypes: ["polygon", "polygon", "EPSILON"],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/relationAnalys/adjacent",
- },
- "1.5.4.2": {
- // 功能描述
- functionalDefinition:
- "判断一个要素(含点、线、面)是否完全位于另一个面要素内部,且无任何部分超出,核心用于 “归属界定” 场景",
- // 元素类型
- elementTypes: ["point", "polyline", "polygon", "EPSILON"],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/relationAnalys/include",
- },
- "1.5.4.3": {
- // 功能描述
- functionalDefinition:
- "判断两个要素(点与线、点与面、线与线、线与面、面与面)是否存在空间重叠(含部分重叠),核心用于 “交叉影响” 场景",
- // 元素类型
- elementTypes: ["point", "polyline", "polygon", "EPSILON"],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/relationAnalys/intersect",
- },
- "1.5.4.4": {
- // 功能描述
- functionalDefinition:
- "判断两个要素(点、线、面)之间无任何空间接触(含边界接触),且最小距离大于自定义阈值(默认 10 米,可通过接口参数调整),核心用于 “无关联排除” 场景",
- // 元素类型
- elementTypes: ["point", "polyline", "polygon", "EPSILON"],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/relationAnalys/parting",
- },
- "1.5.4.5": {
- // 功能描述
- functionalDefinition:
- "以一个核心要素(点、线、面)为中心,按自定义半径(如 500 米、1 千米)划定范围,查询范围内所有目标要素(如设施、地块、道路),核心用于 “资源覆盖范围” 场景。由于不是我负责,暂时为缓冲区计算功能。",
- // 元素类型
- elementTypes: ["point", "polyline", "polygon", "EPSILON"],
- // 元素个数
- numberOf: 2,
- // 后台接口路径
- apiUrl: "/relationAnalys/neighbor",
- },
- "1.5.5.1": {
- // 功能描述
- functionalDefinition:
- "非空间数据转空间数据功能支持常见格式的非空间数据转换,如 CSV、Excel 表格数据等。通过与地理编码服务紧密结合,关联空间参考信息(如地址、行政区域、关联 ID),转换为带坐标的空间要素(点、线、面),将表格中的地址、坐标等信息转换为具有空间位置的矢量数据的功能,并依据用户设定规则赋予属性信息。核心解决 “业务数据与地图引擎关联” 的问题,实现 “数据可视化” 与 “空间分析” 的联动。在智慧城市建设中,整合人口、环境、交通等多源非空间数据,实现数据融合分析,为城市精细化管理提供数据支持;在地理大数据分析中,拓展非空间数据的应用维度,挖掘数据潜在价值。",
- // 元素类型
- elementTypes: ["file"],
- // 元素个数
- numberOf: 0,
- // 后台接口路径
- apiUrl: "/nonStandardToStandard/importFile",
- },
- "1.5.6.1": {
- // 功能描述
- functionalDefinition:
- "坐标转换是基于青浦区三维数字底板的坐标系统(SH2000投影坐标系),将空间要素的坐标在不同坐标系之间进行转换的功能,包括地理坐标系(如 WGS84、上海 2000 等)和投影坐标系(如高斯 - 克吕格投影、UTM 投影等)",
- // 元素类型
- elementTypes: ["lon", "lat", "inPrj", "outPrj"],
- inPrj: [
- {
- value: "WGS84",
- label: "WGS84",
- },
- {
- value: "SH2000",
- label: "SH2000",
- },
- {
- value: "UTM",
- label: "UTM",
- },
- ],
- outPrj: [
- {
- value: "WGS84",
- label: "WGS84",
- },
- {
- value: "SH2000",
- label: "SH2000",
- },
- {
- value: "UTM",
- label: "UTM",
- },
- ],
- // 元素个数
- numberOf: 0,
- // 后台接口路径
- apiUrl: "/coordinateSystemTransformation/pointTransformation",
- },
- "1.5.7.1": {
- // 功能描述
- functionalDefinition:
- "时空数据格式转换是将青浦区三维数字底板中的时空数据(含空间坐标与时间属性的数据,如轨迹数据、时序监测数据),在不同标准数据格式之间进行转换的功能,如 Shapefile、GeoJSON、KML、NetCDF 等。核心支持 “矢量数据格式转换”“栅格数据格式转换”“时空轨迹数据格式转换” 三类转换,确保数据能在不同 GIS 软件、不同应用系统之间兼容流转,不同部门、不同系统之间顺利读取和处理时空数据;在大数据存储和管理时,根据不同应用场景和存储需求,选择合适的数据格式。提高数据存储和访问效率,满足数据共享、分析、展示的多场景需求。",
- // 元素类型
- elementTypes: ["file", "outFileType", "lonKey", "latKey"],
- outFileType: [
- {
- value: "geoJson",
- label: "geoJson",
- },
- {
- value: "shp",
- label: "shp",
- },
- {
- value: "csv",
- label: "csv",
- },
- {
- value: "xlsx",
- label: "xlsx",
- },
- ],
- // 元素个数
- numberOf: 0,
- // 后台接口路径
- apiUrl: "/spatiotemporal_data_format_conversion/fileFormatConversion",
- },
- "1.5.7.2": {
- // 功能描述
- functionalDefinition: "转换文件下载",
- // 元素类型
- elementTypes: ["filePath"],
- // 元素个数
- numberOf: 0,
- // 后台接口路径
- apiUrl: "/spatiotemporal_data_format_conversion/downloadFile",
- },
- },
- currentTool: null,
- drawingMode: null,
- handler: null,
- drawnEntities: [],
- geometries: [], // 存储绘制的几何对象
- // 绘制状态相关
- currentEntity: null, // 当前正在绘制的实体
- currentPositions: [], // 当前正在绘制的位置数组
- isDrawingHole: false, // 是否正在绘制镂空
- currentPolygonEntity: null, // 当前要添加镂空的多边形实体
- currentPolygonGeometry: null, // 当前要添加镂空的多边形几何对象
- tempEntity: null, // 临时预览实体
- };
- },
- mounted() {
- this.SceneValue = this.$route.query.sceneId ? this.$route.query.sceneId : "";
- },
- beforeUnmount() {
- // 组件卸载前清理资源
- this.deactivateDraw();
- if (this.handler) {
- this.handler.destroy();
- }
- },
- methods: {
- handleExceed(file) {
- this.$message({
- message: "最多只能上传一个文件",
- type: "warning",
- });
- },
- handleFileChange(file, fileList) {
- this.currentFile = file; // 注意:Element UI Plus 无需 .raw
- },
- uploadRemove() {
- this.currentFile = null;
- },
- handleJsonInput(value) {
- this.jsonData = JSON.parse(value);
- },
- handleChange(emit) {
- this.params.unit = "";
- this.currentFile = null;
- // 清除所有地图中的元素
- this.clearAll();
- this.jsonData = {};
- this.backData = {};
- this.SceneValue = emit[emit.length - 1];
- },
- // 初始化绘制处理器
- initDrawHandler() {
- // 创建绘制处理器
- this.handler = new SkyScenery.ScreenSpaceEventHandler(viewer.canvas);
- },
- // 激活绘制工具
- activateDraw(type) {
- // 取消镂空绘制模式
- this.isDrawingHole = false;
- // 如果已经是当前激活的工具,则取消激活
- if (this.currentTool === type) {
- this.deactivateDraw();
- return;
- }
- // 先取消之前的绘制模式
- this.deactivateDraw();
- // 设置当前工具
- this.currentTool = type;
- this.drawingMode = type;
- // 重置当前绘制状态
- this.resetDrawingState();
- switch (type) {
- case "point":
- this.drawPoint();
- break;
- case "polyline":
- this.drawPolyline();
- break;
- case "polygon":
- this.drawPolygon();
- break;
- }
- },
- // 重置绘制状态
- resetDrawingState() {
- this.currentPositions = [];
- this.currentEntity = null;
- // 移除临时预览实体
- if (this.tempEntity) {
- viewer.entities.remove(this.tempEntity);
- viewer.scene.requestRender();
- this.tempEntity = null;
- }
- },
- // 取消绘制模式
- deactivateDraw() {
- if (this.handler) {
- // 移除所有事件监听器
- this.handler.removeInputAction(SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
- this.handler.removeInputAction(SkyScenery.ScreenSpaceEventType.MOUSE_MOVE);
- this.handler.removeInputAction(SkyScenery.ScreenSpaceEventType.RIGHT_CLICK);
- }
- // 重置状态
- this.resetDrawingState();
- this.currentTool = null;
- this.drawingMode = null;
- this.isDrawingHole = false;
- },
- // 绘制点
- drawPoint() {
- const that = this;
- this.handler.setInputAction(function (event) {
- const ray = viewer.camera.getPickRay(event.position);
- const position = viewer.scene.globe.pick(ray, viewer.scene);
- if (position) {
- const cartographic = SkyScenery.Cartographic.fromCartesian(position);
- const longitude = SkyScenery.Math.toDegrees(cartographic.longitude);
- const latitude = SkyScenery.Math.toDegrees(cartographic.latitude);
- // 创建点实体(实时渲染)
- const entity = viewer.entities.add({
- position: position,
- point: {
- show: true,
- color: SkyScenery.Color.RED,
- pixelSize: 10,
- outlineColor: SkyScenery.Color.WHITE,
- outlineWidth: 2,
- },
- });
- viewer.scene.requestRender();
- that.drawnEntities.push(entity);
- // 转换为geometry格式并保存
- const geometry = {
- type: "Point",
- coordinates: [longitude, latitude],
- };
- that.geometries.push(geometry);
- that.changeGeometries();
- console.log("绘制了点:", geometry);
- }
- }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
- },
- // 绘制线
- drawPolyline() {
- const that = this;
- // 鼠标移动时更新临时线(实时渲染预览)
- this.handler.setInputAction(function (event) {
- if (that.currentPositions.length > 0) {
- const ray = viewer.camera.getPickRay(event.endPosition);
- const endPosition = viewer.scene.globe.pick(ray, viewer.scene);
- if (endPosition) {
- const tempPositions = [...that.currentPositions, endPosition];
- // 更新临时预览实体
- if (!that.tempEntity) {
- that.tempEntity = viewer.entities.add({
- polyline: {
- show: true,
- positions: tempPositions,
- material: SkyScenery.Color.BLUE.withAlpha(0.5),
- width: 3,
- },
- });
- viewer.scene.requestRender();
- } else {
- that.tempEntity.polyline.positions = tempPositions;
- }
- }
- }
- }, SkyScenery.ScreenSpaceEventType.MOUSE_MOVE);
- // 左键点击添加点
- this.handler.setInputAction(function (event) {
- const ray = viewer.camera.getPickRay(event.position);
- const position = viewer.scene.globe.pick(ray, viewer.scene);
- if (position) {
- that.currentPositions.push(position.clone());
- // 如果是第一个点,不需要更新实体
- if (that.currentPositions.length > 1) {
- // 如果已有实体,更新它
- if (that.currentEntity) {
- viewer.entities.remove(that.currentEntity);
- }
- // 创建当前实体(实时渲染)
- that.currentEntity = viewer.entities.add({
- polyline: {
- show: true,
- positions: [...that.currentPositions],
- material: SkyScenery.Color.BLUE,
- width: 3,
- },
- });
- viewer.scene.requestRender();
- }
- }
- }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
- // 右键点击完成绘制
- this.handler.setInputAction(function () {
- if (that.currentPositions.length > 1) {
- // 移除临时预览实体
- if (that.tempEntity) {
- viewer.entities.remove(that.tempEntity);
- that.tempEntity = null;
- }
- // 否则创建线
- // 确保当前实体存在
- if (!that.currentEntity) {
- that.currentEntity = viewer.entities.add({
- polyline: {
- show: true,
- positions: [...that.currentPositions],
- material: SkyScenery.Color.BLUE,
- width: 3,
- },
- });
- }
- that.drawnEntities.push(that.currentEntity);
- viewer.scene.requestRender();
- // 转换为geometry格式并保存
- const coordinates = [];
- that.currentPositions.forEach((pos) => {
- const cartographic = SkyScenery.Cartographic.fromCartesian(pos);
- coordinates.push([
- SkyScenery.Math.toDegrees(cartographic.longitude),
- SkyScenery.Math.toDegrees(cartographic.latitude),
- ]);
- });
- const geometry = {
- type: "LineString",
- coordinates: coordinates,
- };
- that.geometries.push(geometry);
- that.changeGeometries();
- console.log("绘制了线:", geometry);
- // 取消当前绘制模式
- that.deactivateDraw();
- }
- }, SkyScenery.ScreenSpaceEventType.RIGHT_CLICK);
- },
- // 绘制面
- drawPolygon() {
- const that = this;
- // 鼠标移动时更新临时面(实时渲染预览)
- this.handler.setInputAction(function (event) {
- if (that.currentPositions.length > 0) {
- const ray = viewer.camera.getPickRay(event.endPosition);
- const endPosition = viewer.scene.globe.pick(ray, viewer.scene);
- if (endPosition) {
- // 为了预览效果,临时闭合多边形
- const tempPositions = [
- ...that.currentPositions,
- endPosition,
- that.currentPositions[0],
- ];
- // 更新临时预览实体
- if (!that.tempEntity) {
- that.tempEntity = viewer.entities.add({
- polygon: {
- show: true,
- hierarchy: new SkyScenery.PolygonHierarchy(tempPositions),
- material: new SkyScenery.ColorMaterialProperty(
- new SkyScenery.Color(0, 0, 1, 0.2)
- ),
- outline: true,
- outlineColor: SkyScenery.Color.BLUE.withAlpha(0.5),
- outlineWidth: 2,
- },
- });
- viewer.scene.requestRender();
- } else {
- that.tempEntity.polygon.hierarchy = new SkyScenery.PolygonHierarchy(
- tempPositions
- );
- }
- }
- }
- }, SkyScenery.ScreenSpaceEventType.MOUSE_MOVE);
- // 左键点击添加点
- this.handler.setInputAction(function (event) {
- const ray = viewer.camera.getPickRay(event.position);
- const position = viewer.scene.globe.pick(ray, viewer.scene);
- if (position) {
- // 检查是否点击了第一个点附近(自动闭合)
- if (
- that.currentPositions.length > 2 &&
- that.isPositionNearFirst(position, that.currentPositions[0])
- ) {
- // 完成多边形绘制
- that.finalizePolygonDrawing();
- that.deactivateDraw();
- return;
- }
- that.currentPositions.push(position.clone());
- // 如果有足够的点,更新多边形实体(实时渲染)
- if (that.currentPositions.length > 2) {
- // 闭合多边形
- const closedPositions = [...that.currentPositions, that.currentPositions[0]];
- // 如果已有实体,更新它
- if (that.currentEntity) {
- viewer.entities.remove(that.currentEntity);
- }
- // 创建当前实体
- that.currentEntity = viewer.entities.add({
- polygon: {
- show: true,
- hierarchy: new SkyScenery.PolygonHierarchy(closedPositions),
- material: new SkyScenery.ColorMaterialProperty(
- new SkyScenery.Color(0, 0, 1, 0.3)
- ),
- outline: true,
- outlineColor: SkyScenery.Color.BLUE,
- outlineWidth: 2,
- },
- });
- viewer.scene.requestRender();
- }
- }
- }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
- // 右键点击完成绘制
- this.handler.setInputAction(function () {
- if (that.currentPositions.length > 2) {
- that.finalizePolygonDrawing();
- // 取消当前绘制模式
- that.deactivateDraw();
- }
- }, SkyScenery.ScreenSpaceEventType.RIGHT_CLICK);
- },
- // 完成多边形绘制
- finalizePolygonDrawing() {
- // 移除临时预览实体
- if (this.tempEntity) {
- viewer.entities.remove(this.tempEntity);
- this.tempEntity = null;
- }
- // 确保多边形是闭合的
- let closedPositions = [...this.currentPositions];
- // 创建最终的多边形实体
- if (this.currentEntity) {
- viewer.entities.remove(this.currentEntity);
- }
- this.currentEntity = viewer.entities.add({
- polygon: {
- show: true,
- hierarchy: new SkyScenery.PolygonHierarchy(closedPositions),
- material: new SkyScenery.ColorMaterialProperty(
- new SkyScenery.Color(0, 0, 1, 0.3)
- ),
- outline: true,
- outlineColor: SkyScenery.Color.BLUE,
- outlineWidth: 2,
- },
- });
- viewer.scene.requestRender();
- this.drawnEntities.push(this.currentEntity);
- // 转换为geometry格式并保存(不包含重复的最后一个点)
- const coordinates = [];
- const mainRing = [];
- for (let i = 0; i < closedPositions.length; i++) {
- const cartographic = SkyScenery.Cartographic.fromCartesian(closedPositions[i]);
- mainRing.push([
- SkyScenery.Math.toDegrees(cartographic.longitude),
- SkyScenery.Math.toDegrees(cartographic.latitude),
- ]);
- }
- const cartographic = SkyScenery.Cartographic.fromCartesian(closedPositions[0]);
- mainRing.push([
- SkyScenery.Math.toDegrees(cartographic.longitude),
- SkyScenery.Math.toDegrees(cartographic.latitude),
- ]);
- coordinates.push(mainRing);
- const geometry = {
- type: "Polygon",
- coordinates: coordinates, // GeoJSON格式
- holes: [], // 用于存储镂空区域
- };
- // 保存实体和几何对象的关联
- this.currentEntity.geometryRef = geometry;
- this.geometries.push(geometry);
- this.changeGeometries();
- console.log("绘制了面:", geometry);
- },
- // 开始绘制镂空
- startHoleDrawing() {
- // 如果已经在绘制镂空,则取消
- if (this.isDrawingHole) {
- this.isDrawingHole = false;
- this.deactivateDraw();
- return;
- }
- // 取消其他绘制模式
- this.deactivateDraw();
- // 设置为镂空绘制模式
- this.isDrawingHole = true;
- console.log("请点击一个多边形以添加镂空");
- // 设置点击事件选择多边形
- const that = this;
- this.handler.setInputAction(function (event) {
- // 拾取实体
- const pickedObject = viewer.scene.pick(event.position);
- if (pickedObject && pickedObject.id && pickedObject.id.polygon) {
- const polygonEntity = pickedObject.id;
- // 检查是否有对应的几何对象
- if (polygonEntity.geometryRef && polygonEntity.geometryRef.type === "Polygon") {
- that.currentPolygonEntity = polygonEntity;
- that.currentPolygonGeometry = polygonEntity.geometryRef;
- console.log("已选择多边形,现在绘制镂空区域");
- // 开始绘制镂空区域(使用多边形绘制逻辑,但最后添加为镂空)
- that.resetDrawingState();
- that.drawHole();
- } else {
- console.log("选择的不是有效的多边形");
- }
- } else {
- console.log("未选中任何多边形");
- }
- }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
- },
- // 绘制镂空区域
- drawHole() {
- const that = this;
- // 清除之前的事件
- this.handler.removeInputAction(SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
- // 鼠标移动时更新临时镂空区域
- this.handler.setInputAction(function (event) {
- if (that.currentPositions.length > 0) {
- const ray = viewer.camera.getPickRay(event.endPosition);
- const endPosition = viewer.scene.globe.pick(ray, viewer.scene);
- if (endPosition) {
- // 为了预览效果,临时闭合多边形
- const tempPositions = [
- ...that.currentPositions,
- endPosition,
- that.currentPositions[0],
- ];
- // 更新临时预览实体
- if (!that.tempEntity) {
- that.tempEntity = viewer.entities.add({
- polygon: {
- show: true,
- hierarchy: new SkyScenery.PolygonHierarchy(tempPositions),
- material: new SkyScenery.ColorMaterialProperty(
- new SkyScenery.Color(1, 0, 0, 0.3)
- ),
- outline: true,
- outlineColor: SkyScenery.Color.RED,
- outlineWidth: 2,
- },
- });
- viewer.scene.requestRender();
- } else {
- that.tempEntity.polygon.hierarchy = new SkyScenery.PolygonHierarchy(
- tempPositions
- );
- }
- }
- }
- }, SkyScenery.ScreenSpaceEventType.MOUSE_MOVE);
- // 左键点击添加点
- this.handler.setInputAction(function (event) {
- const ray = viewer.camera.getPickRay(event.position);
- const position = viewer.scene.globe.pick(ray, viewer.scene);
- if (position) {
- // 检查是否点击了第一个点附近(自动闭合)
- if (
- that.currentPositions.length > 2 &&
- that.isPositionNearFirst(position, that.currentPositions[0])
- ) {
- // 完成镂空绘制
- that.finalizeHoleDrawing();
- return;
- }
- that.currentPositions.push(position.clone());
- }
- }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
- // 右键点击完成绘制
- this.handler.setInputAction(function () {
- if (that.currentPositions.length > 2) {
- that.finalizeHoleDrawing();
- }
- }, SkyScenery.ScreenSpaceEventType.RIGHT_CLICK);
- },
- // 完成镂空绘制
- finalizeHoleDrawing() {
- // 移除临时预览实体
- if (this.tempEntity) {
- viewer.entities.remove(this.tempEntity);
- viewer.scene.requestRender();
- this.tempEntity = null;
- }
- // 确保镂空区域是闭合的
- let closedPositions = [...this.currentPositions];
- // 转换为几何坐标
- const holeCoordinates = [];
- for (let i = 0; i < closedPositions.length; i++) {
- const cartographic = SkyScenery.Cartographic.fromCartesian(closedPositions[i]);
- holeCoordinates.push([
- SkyScenery.Math.toDegrees(cartographic.longitude),
- SkyScenery.Math.toDegrees(cartographic.latitude),
- ]);
- }
- const cartographic = SkyScenery.Cartographic.fromCartesian(closedPositions[0]);
- holeCoordinates.push([
- SkyScenery.Math.toDegrees(cartographic.longitude),
- SkyScenery.Math.toDegrees(cartographic.latitude),
- ]);
- // 添加到几何对象的镂空数组
- if (!this.currentPolygonGeometry.holes) {
- this.currentPolygonGeometry.holes = [];
- }
- this.currentPolygonGeometry.holes.push(holeCoordinates);
- // 更新多边形的层级结构以包含镂空
- const polygonHierarchy = this.buildPolygonHierarchyWithHoles(
- this.currentPolygonGeometry.coordinates[0],
- this.currentPolygonGeometry.holes
- );
- // 更新实体显示
- this.currentPolygonEntity.polygon.hierarchy = polygonHierarchy;
- console.log("添加了镂空区域:", holeCoordinates);
- console.log("更新后的多边形几何:", this.currentPolygonGeometry);
- // 重置状态
- this.resetDrawingState();
- this.isDrawingHole = false;
- this.currentPolygonEntity = null;
- this.currentPolygonGeometry = null;
- // 取消绘制模式
- this.deactivateDraw();
- },
- // 构建包含镂空的多边形层级结构
- buildPolygonHierarchyWithHoles(outerRing, holes) {
- // 将外部环转换为Cartesian3数组
- const outerRingPositions = [];
- outerRing.forEach((coord) => {
- const cartesian = SkyScenery.Cartesian3.fromDegrees(coord[0], coord[1]);
- outerRingPositions.push(cartesian);
- });
- // 闭合外部环
- outerRingPositions.push(outerRingPositions[0]);
- // 创建层级结构
- const hierarchy = new SkyScenery.PolygonHierarchy(outerRingPositions);
- // 添加镂空
- if (holes && holes.length > 0) {
- hierarchy.holes = holes.map((hole) => {
- const holePositions = [];
- hole.forEach((coord) => {
- const cartesian = SkyScenery.Cartesian3.fromDegrees(coord[0], coord[1]);
- holePositions.push(cartesian);
- });
- // 闭合镂空环
- holePositions.push(holePositions[0]);
- return new SkyScenery.PolygonHierarchy(holePositions);
- });
- }
- return hierarchy;
- },
- // 检查点是否靠近第一个点
- isPositionNearFirst(position, firstPosition, tolerance = 10) {
- // 单位:米
- const distance = SkyScenery.Cartesian3.distance(position, firstPosition);
- return distance < tolerance;
- },
- changeGeometries() {
- let requestData = {};
- const geometriesToSend = this.geometries;
- let FeatureCollectionFeatures = [];
- geometriesToSend.forEach((item) => {
- FeatureCollectionFeatures.push({
- type: "Feature",
- properties: {},
- geometry: {
- type: item.type,
- coordinates: item.coordinates,
- },
- });
- });
- // 构造请求数据
- requestData = {
- type: "FeatureCollection",
- features: FeatureCollectionFeatures,
- timestamp: new Date().getTime(),
- };
- if (
- this.SceneValue &&
- this.SceneRule[this.SceneValue] &&
- this.SceneRule[this.SceneValue].elementTypes &&
- this.SceneRule[this.SceneValue].elementTypes.includes("unit") &&
- this.params.unit
- ) {
- requestData.unit = this.params.unit;
- }
- if (
- this.SceneValue &&
- this.SceneRule[this.SceneValue] &&
- this.SceneRule[this.SceneValue].elementTypes &&
- this.SceneRule[this.SceneValue].elementTypes.includes("EPSILON") &&
- this.params.EPSILON
- ) {
- requestData.EPSILON = this.params.EPSILON;
- }
- this.jsonData = requestData;
- return requestData;
- },
- // 发送几何数据到后台接口
- sendGeometriesToBackend() {
- // 这里使用axios发送请求,需要确保项目中已安装并导入axios
- let requestData;
- let requestUrl = this.SceneRule[this.SceneValue].apiUrl;
- if (
- this.SceneRule[this.SceneValue].elementTypes.includes("point") ||
- this.SceneRule[this.SceneValue].elementTypes.includes("polyline") ||
- this.SceneRule[this.SceneValue].elementTypes.includes("polygon")
- ) {
- requestData = this.changeGeometries();
- } else {
- requestData = new FormData();
- this.SceneRule[this.SceneValue].elementTypes.forEach((key) => {
- if (key == "file") {
- if (!this.currentFile) {
- return this.$message({
- message: "请选择文件",
- type: "error",
- });
- }
- requestData.append("file", this.currentFile.raw);
- } else {
- requestData.append(key, this.params[key]);
- }
- });
- }
- let that = this;
- // 实际项目中使用以下代码发送请求
- sksjgl
- .topology(requestUrl, requestData)
- .then((res) => {
- if (requestUrl.indexOf("downloadFile") == -1) {
- that.backData = res;
- if (res.code && res.code == 200) {
- that.$message({
- message: res.message,
- type: "success",
- });
- } else {
- that.$message({
- message: res.content,
- type: "error",
- });
- }
- } else {
- const blob = res; // 响应体是 Blob 类型
- if (!blob) {
- that.$message.error("下载失败:文件流为空");
- reject("文件流为空");
- return;
- }
- let _downloadFile = that.params.filePath + "";
- let fileName = _downloadFile.substring(
- _downloadFile.indexOf("down_files") + 11
- );
- // D:\work\backCode\one_map_portal_server\down_files\0378b1c2e92a4c36ab447f552c0c7888.xlsx
- // 替换原代码中创建 url 的逻辑,先加校验
- console.log("blob 类型:", Object.prototype.toString.call(blob)); // 正常应输出 [object Blob]
- console.log("blob 大小:", blob.size); // 正常应大于 0
- if (!(blob instanceof Blob) || blob.size === 0) {
- this.$message.error("文件流解析失败,无法生成下载链接");
- return;
- }
- const url = window.URL.createObjectURL(blob); // 将 Blob 转为临时 URL
- const link = document.createElement("a");
- link.href = url;
- link.download = fileName; // 设置下载文件名
- link.style.display = "none";
- document.body.appendChild(link);
- link.click(); // 触发点击下载
- document.body.removeChild(link);
- window.URL.revokeObjectURL(url); // 销毁临时 URL,避免内存泄漏
- }
- })
- .catch((error) => {
- console.error("后台接口调用失败:", error);
- });
- },
- // 清除所有绘制的元素
- clearAll() {
- // 移除所有实体
- this.drawnEntities.forEach((entity) => {
- viewer.entities.remove(entity);
- });
- viewer.scene.requestRender();
- // 清空数组
- this.drawnEntities = [];
- this.geometries = [];
- this.changeGeometries();
- // 取消当前绘制模式
- this.deactivateDraw();
- console.log("已清除所有绘制的元素");
- },
- },
- };
- </script>
- <style lang="less" scoped>
- // 操作栏样式
- #controlPanelBox {
- width: calc(30vw - 2rem);
- min-width: 500px;
- height: calc(100vh - 120px - 2rem);
- display: flex;
- flex-direction: column;
- padding: 1rem;
- position: fixed;
- top: 70px;
- right: 0;
- background: #fff;
- }
- // 绘制按钮区域
- .toolbar {
- position: absolute;
- top: 10px;
- left: -120px;
- z-index: 1000;
- background: rgba(255, 255, 255, 0.9);
- border-radius: 8px;
- padding: 3px 5px;
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
- display: flex;
- flex-direction: column;
- gap: 8px;
- }
- .tool-item {
- padding: 10px 20px;
- cursor: pointer;
- border-radius: 4px;
- transition: all 0.3s ease;
- user-select: none;
- font-size: 14px;
- }
- .tool-item:hover {
- background: #f0f0f0;
- }
- .tool-item.active {
- background: #409eff;
- color: white;
- }
- .sceneNameBox {
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
- </style>
|