dianlixunjian
徐景良 1 year ago
parent cc6034a042
commit f816fe9266

@ -146,7 +146,9 @@
"vxe-table-plugin-export-xlsx": "^3.1.0",
"xe-utils": "^3.5.14",
"xlsx": "^0.18.5",
"xml-js": "^1.6.11"
"xml-js": "^1.6.11",
"jszip":"^3.10.1",
"shpjs":"^6.1.0"
},
"devDependencies": {
"@commitlint/cli": "^18.4.4",

@ -25,7 +25,7 @@
item.name
}}</a-checkbox>
</p>
</a-collapse-panel>
</a-collapse-panel>
</a-collapse>
</div>
@ -56,7 +56,7 @@
<a-upload
name="file"
:before-upload="handleImportCoorinateChange"
:before-upload="handleImportShapeFileChange"
:showUploadList="false"
>
<p class="split-panel-item">导入图层分割</p>
@ -237,6 +237,9 @@
import { polygonCut } from './lib/segmentation';
import { splitPolygonByLine, splitPolygonByFill } from './lib/splitpolygon';
// 线
import {chunkUtil} from './lib/chunkutil.ts';
//
import { userFormFileStore } from '@/store/modules/formFileUrl';
import { storeToRefs } from 'pinia';
@ -260,7 +263,73 @@
import { useCloudQueryStore } from '@/store/modules/cloudquery';
import { AddDroneTask } from '@/api/demo/cloudQuery.ts';
//
import proj4 from 'proj4'
// shp
import JSZip from 'jszip'
import shp from 'shpjs'
// zipzip
const parseZip = async(zip)=>{
// zip
const jsZip = new JSZip()
const zipData = await jsZip.loadAsync(zip)
// zip
const data = await zipData.generateAsync({ type: 'arraybuffer' })
return await shp(data)
}
//
const handleImportShapeFileChange = (e)=>{
parseZip(e).then(res=>{
let geojson = JSON.parse(JSON.stringify(res))
// shapgefile
handlerDetails(
res,
'shapefileSource',
'shapefileLayer',
{
lineStyle: { 'line-color': '#ff0000', 'line-width': 3 },
fillStyle: { 'fill-color': '#ff0000', 'fill-opacity': 0.1 },
}
)
Modal.confirm({
title: '是否确认分割图斑?',
onCancel() {
handlerDetails(
{type:"FeatureCollection",features:[]},
'shapefileSource',
'shapefileLayer',
{
lineStyle: { 'line-color': '#ff0000', 'line-width': 3 },
fillStyle: { 'fill-color': '#ff0000', 'fill-opacity': 0.1 },
}
)
},
async onOk() {
splitFeatureByFill(geojson.features[0].geometry.coordinates[0]);
handlerDetails(
{type:"FeatureCollection",features:[]},
'shapefileSource',
'shapefileLayer',
{
lineStyle: { 'line-color': '#ff0000', 'line-width': 3 },
fillStyle: { 'fill-color': '#ff0000', 'fill-opacity': 0.1 },
}
)
},
});
});
}
// shapefile
//
function GkToCGCS2000(lngLat){
@ -289,9 +358,6 @@
}
}
const useCloudQuery = useCloudQueryStore();
const { VITE_GLOB_API_URL } = getAppEnvConfig();
@ -716,43 +782,63 @@
let splitPolygon = currentGeoJson.value;
try {
// let features = polygonCut(splitPolygon,splitLineString,0.1,"meters");
let features = splitPolygonByLine(splitLineString, splitPolygon);
splitPolygon?.geometry.coordinates[0].forEach((item,index)=>{
splitPolygon.geometry.coordinates[0][index] = [item[0],item[1]];
})
let features = splitPolygonByLine(splitLineString, splitPolygon);
let tempFeatures = JSON.parse(JSON.stringify(features))
let splitAfterFeatures = {
type: 'FeatureCollection',
features: [],
};
splitAfterFeatures.features = features;
emit('handlerSplitPolygon', features);
handlerDetails(splitAfterFeatures);
splitAfterFeatures.features = tempFeatures;
console.log("tempFeatures",tempFeatures)
//
emit('handlerSplitPolygon', tempFeatures);
//
// handlerDetails(splitAfterFeatures);
handlerUnDraw();
} catch (e) {
createMessage.warning('分割线起点、终点需要在图斑外');
console.log("error error",e);
createMessage.warning('分割线起点、终点需要在图斑外,多个图斑时需要点击选择需要分割的图斑!');
handlerUnDraw();
}
};
//
const splitFeatureByFill = (fill) => {
let splitLineString = {
let drawPolygon = {
type: 'Feature',
properties: {},
properties: {
id:null,
},
geometry: {
coordinates: [fill],
type: 'Polygon',
},
};
let splitPolygon = currentGeoJson.value;
// let features = polygonCut(splitPolygon,splitLineString,0.1,"meters");
let features = splitPolygonByFill(splitLineString, splitPolygon);
let features = splitPolygonByFill(drawPolygon, splitPolygon);
let tempFeatures = JSON.parse(JSON.stringify(features))
let splitAfterFeatures = {
type: 'FeatureCollection',
features: [],
};
splitAfterFeatures.features = [features];
handlerDetails(splitAfterFeatures);
splitAfterFeatures.features = tempFeatures;
emit('handlerSplitPolygon', tempFeatures);
handlerUnDraw();
};
//
@ -790,11 +876,21 @@
splitPanelVisible.value = false;
mp.draw('Polygon');
mp.on('Polygon', function (e) {
let coordinates = [];
e?.forEach((item, index) => {
coordinates?.push([item.lng, item.lat]);
Modal.confirm({
title: '是否确认分割图斑?',
onCancel() {
handlerUnDraw();
},
async onOk() {
let coordinates = [];
e?.forEach((item, index) => {
coordinates?.push([item.lng, item.lat]);
});
coordinates.push(coordinates[0]);
splitFeatureByFill(coordinates);
handlerUnDraw();
},
});
splitFeatureByFill(coordinates);
emit('mapDraw', 'Polygon', e);
});
};
@ -1131,7 +1227,6 @@
};
const currentGeoJson = ref({});
const handlerDetails = (
geojson,
source = 'detailsSource',
@ -1141,26 +1236,30 @@
fillStyle: { 'fill-color': '#fcf003', 'fill-opacity': 0.1 },
},
) => {
let fillLayerName = layer + 'Fill';
let lineLayerName = layer + 'Line';
if (source == 'detailsSource') {
console.log('currentGeoJson', geojson);
if (source == 'detailsSource' || source == "splitPolygonSource") {
//
let coordinates = null;
if (geojson.features.length>0 && geojson.features[0].geometry.type == 'MultiPolygon') {
if (geojson.features.length>0 && geojson.features[0].geometry.type == 'MultiPolygon') { //
//
coordinates = geojson.features[0].geometry.coordinates[0];
} else if (geojson.features.length>0 && geojson.features[0].geometry.type == 'Polygon') {
} else if (geojson.features.length>0 && geojson.features[0].geometry.type == 'Polygon') { //
coordinates = geojson.features[0].geometry.coordinates;
}
// 2Mapbox
if (coordinates) {
if(
coordinates[0][coordinates[0].length - 1][0] ==
coordinates[0][coordinates[0].length - 2][0]
) {
if((coordinates[0][coordinates[0].length - 1][0] == coordinates[0][coordinates[0].length - 2][0]) && (coordinates[0][coordinates[0].length - 1][1] == coordinates[0][coordinates[0].length - 2][1])) {
coordinates[0]?.pop();
}
}
let singleFeature = {
type: 'Feature',
properties: {},
@ -1169,10 +1268,13 @@
type: 'Polygon',
},
};
currentGeoJson.value = singleFeature;
console.log('currentGeoJson', currentGeoJson.value);
}
// geojson使
currentGeoJson.value = singleFeature;
}
if (map.getSource(source)) {
map.getSource(source).setData(geojson);
} else {
@ -1195,10 +1297,14 @@
paint: style.lineStyle,
});
map.on('click', fillLayerName, function (e) {
if (e.features.length > 0) {
var feature = e.features[0];
emit('onFeatureClick', feature);
}
if(fillLayerName == 'detailsLayerFill' || fillLayerName == 'detailsLayerLine'){
}
});
}
};
@ -1297,7 +1403,7 @@
};
const handlerLocationRemove = (index: number) => {
locationArrays.value.splice(index, 1);
locationDrawArrays.value.splice(index, 1);
locationDrawArrays.value?.splice(index, 1);
handlerLocationGeoJson();
};
@ -1311,7 +1417,7 @@
console.log(obj);
locationDrawArrays.value?.push(obj)
})
locationDrawArrays.value?.forEach((item,index)=>{
//
if(item.lng > 180){

@ -0,0 +1,142 @@
class chunkUtil {
constructor() {
this.turf = window.turf || "";
if (!this.turf) {
throw new Error("请确定turf已挂载至window");
}
}
clipPolygon(polygon, polyline) {
const types = typeof polygon;
const types1 = typeof polyline;
if (!polygon) {
throw console.error("请传入面");
}
if (!polyline) {
throw console.error("请传入线");
}
if ([types, types1].includes('string')) {
const polygonParse = JSON.parse(polygon);
const polylineParse = JSON.parse(polyline);
const isLon = !polygonParse && !polygonParse.features && !polygonParse.features.length;
const isLine = !polylineParse && !polylineParse.features && !polylineParse.features.length;
if (isLon || isLine) {
throw new Error("请确定为面与线都为json串格式");
}
return this._setFloors(polygonParse, polylineParse)
} else {
throw new Error("暂时只支持json串格式的转换如需支持json格式请与作者沟通。");
}
}
_setFloors(A, B) {
const { turf } = this;
if ([A.type, B.type].includes('FeatureCollection')) {
const geojsonA = A.features[0];
if (geojsonA.geometry.type !== 'Polygon') {
throw new Error("第一个值请传入面");
}
const polyline = turf.polygonToLine(geojsonA);
if (polyline.geometry.type === "LineString") {
const lines = B.features[0]
const singClip = this._singeClips(polyline, lines)
return singClip
}
}
}
_singeClips(A, B) {
const { turf } = this;
const C = turf.lineIntersect(A, B);
if (C.features.length !== 2) {
throw new Error("请确定线与面有两个相交点");
}
const L = B.geometry.coordinates.length;
const SP = turf.point(B.geometry.coordinates[0]);
const EP = turf.point(B.geometry.coordinates[L - 1]);
const P = turf.polygon([A.geometry.coordinates])
if (turf.booleanPointInPolygon(SP, P) || turf.booleanPointInPolygon(EP, P)) {
throw new Error("线起点或终点不能在面内部");
}
const PL = turf.lineSlice(C.features[0], C.features[1], A);
const CL = turf.lineSlice(C.features[0], C.features[1], B);
const RL = this.connectLine(PL, CL);
RL.geometry.coordinates.push(RL.geometry.coordinates[0]); //闭合
const RP1 = turf.lineToPolygon(RL);
const FL = this.isLines(turf.point(A.geometry.coordinates[0]), PL);
const pList = [];
if (FL) {
for (let i = 0; i < A.geometry.coordinates.length; i++) {
const coordinate = A.geometry.coordinates[i];
if (!this.isLines(turf.point(coordinate), PL)) {
pList.push(coordinate)
}
}
} else {
let sNum = 0;
let isStartPush = false;
for (let i = 0; i < A.geometry.coordinates.length; i++) {
const coordinate = A.geometry.coordinates[i];
if (!this.isLines(turf.point(coordinate), PL)) {
if (isStartPush) {
pList.push(coordinate)
} else {
sNum++;
}
} else {
isStartPush = true;
}
}
for (let i = 0; i < sNum; i++) {
pList.push(A.geometry.coordinates[i]);
}
}
const PL2 = turf.lineString(pList);
const RL2 = this.connectLine(PL2, CL);
RL2.geometry.coordinates.push(RL2.geometry.coordinates[0]);
const RP2 = turf.lineToPolygon(RL2);
return turf.featureCollection([RP1, RP2])
}
connectLine(l1, l2) {
const l2l = l2.geometry.coordinates.length;
const l1sp = l1.geometry.coordinates[0];
const l2sp = l2.geometry.coordinates[0];
const l2ep = l2.geometry.coordinates[l2l - 1];
const pList = [];
for (let i = 0; i < l1.geometry.coordinates.length; i++) {
const coordinate = l1.geometry.coordinates[i];
pList.push(coordinate);
}
if (this.turf.distance(l1sp, l2sp) < this.turf.distance(l1sp, l2ep)) {
l2.geometry.coordinates = l2.geometry.coordinates.reverse();
}
for (let i = 0; i < l2.geometry.coordinates.length; i++) {
const coordinate = l2.geometry.coordinates[i];
pList.push(coordinate);
}
return this.turf.lineString(pList)
}
isLines(P, L) {
for (let i = 0; i < L.geometry.coordinates.length; i++) {
const coordinate = L.geometry.coordinates[i];
if (P.geometry.coordinates[0] === coordinate[0] && P.geometry.coordinates[1] === coordinate[1]) {
return true
}
}
return false;
}
}
export { chunkUtil }

@ -7,32 +7,51 @@ import { generateUUID } from '../src/tool';
* return
*/
export function splitPolygonByLine(line, outerPolygon) {
console.log("绘制的分割线数据",line);
// 处理被分割的面数据坐标小数点保留多少位
let truncatedSplitter = turf.truncate(turf.lineString(outerPolygon.geometry.coordinates[0]), {
precision: 7,
});
console.log("分割面转换为线数据",truncatedSplitter);
//求交点
let intersectCollection = turf.lineIntersect(line, truncatedSplitter);
console.log("与分割面的交点",intersectCollection);
// printLngLat(intersectCollection.geometry.coordinates);
// 交点小于2个 返回null
if (intersectCollection.features.length < 2) {
return null;
}
//将点合并成MultiPoint
let intersectCombined = turf.combine(intersectCollection).features[0];
console.log("分割后所有点数据",intersectCombined)
//分别获取切割线
let outerPieceCollection = turf.lineSplit(line, intersectCombined);
let splitterPieceCollection = turf.lineSplit(truncatedSplitter, intersectCombined);
console.log("切割线被分割后所有线段",outerPieceCollection);
console.log("切割面被分割后所有线段",splitterPieceCollection);
//将所有的线段放到一起
let pieceCollection = turf.featureCollection(
outerPieceCollection.features.concat(splitterPieceCollection.features),
);
console.log("所有分割线段",pieceCollection);
//使用turf将闭合线组成多边形
let polygonCollection = turf.polygonize(pieceCollection);
console.log("分割线合并面数据",polygonCollection)
//对多边形进行判断,切割外的多边形丢弃
let innerPolygons = polygonCollection.features.filter((polygon) => {
// 获取多边形质心 多边形不规则时有问题
@ -44,6 +63,7 @@ export function splitPolygonByLine(line, outerPolygon) {
// 判断点是否在被分割图斑内
// 图斑中心点
let centerPoint = turf.point(newcenter.geometry.coordinates);
// 图斑面
let outPolygon = turf.polygon(outerPolygon.geometry.coordinates)
// return turf.booleanPointInPolygon(centerPoint, outPolygon);
@ -56,6 +76,7 @@ export function splitPolygonByLine(line, outerPolygon) {
// return turf.booleanPointInPolygon(randomPoint.features[0], outPolygon);
return turf.booleanWithin(centerPoint, outerPolygon);
});
// let innerPolygons = polygonCollection.features;
@ -75,10 +96,32 @@ export function splitPolygonByLine(line, outerPolygon) {
return diff;
});
}
innerPolygons.forEach((item, index) => {
innerPolygons[index].properties.id = generateUUID();
// console.log("innerPolygons_length",innerPolygons[index].geometry.coordinates[0].length);
// console.log("innerPolygons_array",innerPolygons[index].geometry.coordinates[0])
// console.log("innerPolygons_length",innerPolygons[index].geometry.coordinates[0].length);
// console.log("innerPolygons_string",JSON.stringify(innerPolygons[index].geometry.coordinates[0]));
});
// let arr = JSON.parse(JSON.stringify(innerPolygons))
// arr.forEach((item, index) => {
// arr[index].properties.id = generateUUID();
// if((arr[index].geometry.coordinates[0][0][0] == arr[index].geometry.coordinates[0][arr[index].geometry.coordinates[0].length-1][0]) && arr[index].geometry.coordinates[0][0][1] == arr[index].geometry.coordinates[0][arr[index].geometry.coordinates[0].length-1][1]){
// }else{
// arr[index].geometry.coordinates[0].push(arr[index].geometry.coordinates[0][0])
// console.log("coordinates789",arr);
// }
// });
return innerPolygons;
}
function getRandomPointInPolygon(polygon) {
@ -93,65 +136,31 @@ function getRandomPointInPolygon(polygon) {
}
export function splitPolygonByFill(fill, outerPolygon) {
var polygon1 = turf.polygon(fill.geometry.coordinates);
// var polygon1 = turf.polygon(
// [
// [
// [
// 118.08246593377775,
// 35.22214906870923
// ],
// [
// 118.0824468053414,
// 35.2221025269492
// ],
// [
// 118.08255783344151,
// 35.22206277960647
// ],
// [
// 118.08258527859043,
// 35.22213378126961
// ],
// [
// 118.08246593377775,
// 35.22214906870923
// ]
// ]
// ]
// )
export function splitPolygonByFill(drawPolygon, outerPolygon) {
console.log("drawPolygon",drawPolygon);
console.log("outerPolygon",outerPolygon)
var polygon1 = turf.polygon(drawPolygon.geometry.coordinates)
var polygon2 = turf.polygon(outerPolygon.geometry.coordinates);
// var polygon2 = turf.polygon(
// [
// [
// [
// 118.082358,
// 35.222126
// ],
// [
// 118.082517,
// 35.222061
// ],
// [
// 118.082535,
// 35.222098
// ],
// [
// 118.082372,
// 35.222163
// ],
// [
// 118.082358,
// 35.222126
// ]
// ]
// ]
// )
var difference = turf.difference(polygon1, polygon2);
console.log('difference123', difference);
return difference;
var difference = turf.difference(polygon2,polygon1);
var intersection = turf.intersect(polygon2, polygon1);
intersection.properties.id = generateUUID();
difference.properties.id = generateUUID();
let splitAfterFeatures = [intersection,difference];
// splitAfterFeatures?.forEach((item,index)=>{
// splitAfterFeatures[index].properties?.id = generateUUID();
// })
return splitAfterFeatures;
}
export function printLngLat(arr){
arr.forEach((item,index)=>{
console.log(item[1]+","+item[0]+"\n");
})
}

@ -29,7 +29,7 @@ const LINE_IS_DRAW_STYLE = {
};
const POLYGON_STYLE = {
'fill-color': '#FAFAD2',
'fill-opacity': 0.3,
'fill-opacity': 0.6,
};
function typeOf(obj: any): any {
@ -394,6 +394,13 @@ export class MP extends BaseMP {
_this._currentDrawLayer();
this.drawIsFinish();
}
if (this.drawModel === this.drawModelChoose.Polygon) {
_this.drawLocal.push(e.lngLat);
_this._currentDrawSource();
_this._currentDrawLayer();
this.drawIsFinish();
}
}
};
//右键点击

@ -373,9 +373,9 @@
</div>
<div class="split-operation">
<a-button type="primary" :disabled="isSpliting" @click="mergeSplitResult"></a-button>
&nbsp;
<a-button type="error" :disabled="isSpliting" @click="deleteSplitResult"></a-button>
<!-- <a-button type="primary" :disabled="isSpliting" @click="mergeSplitResult"></a-button> -->
<!-- &nbsp;
<a-button type="error" :disabled="isSpliting" @click="deleteSplitResult"></a-button> -->
&nbsp;
<a-button type="primary" :disabled="isSpliting" @click="reductionSplit"></a-button>
&nbsp;
@ -509,6 +509,7 @@
import { getLoadDroneCaseInfoDetail } from '@/api/tiankongdi/index.ts';
import ShowInfoModal from '@/views/demo/tiankongdi/curbspotcity/MapList/ShowInfoModal/index.vue';
import { dataProcessing ,dataProcessingCount} from '@/views/demo/tiankongdi/util.ts';
import { itemProps } from '@/components/Menu/src/props';
const MapboxComponent = ref();
const mapConfig = ref({});
@ -741,10 +742,15 @@
};
const splitPolygonForm = ref([]);
const splitAfterPolygon = ref({});
const splitAfterPolygon = ref([]);
const handlerSplitPolygon = (e) => {
splitAfterPolygon.value = e;
splitPolygonForm.value = [];
// splitPolygonForm.value = [];
//
if(currentPolygon.value){
splitPolygonForm.value?.splice(currentPolygon.value,1);
splitAfterPolygon.value?.splice(currentPolygon.value,1);
}
e?.forEach((item, index) => {
let form = {
fid: null,
@ -764,8 +770,38 @@
checked:false,
};
splitPolygonForm.value?.push(form);
splitAfterPolygon.value?.push(form.geom)
});
//
let splitAfterFeatures = {
type: 'FeatureCollection',
features: [],
};
splitPolygonForm.value?.forEach((item,idnex)=>{
splitAfterFeatures.features.push(item.geom);
})
// splitAfterFeatures.features = e;
MapboxComponent.value.handlerDetails(splitAfterFeatures);
//
let geoms = {
type: 'FeatureCollection',
features: [],
};
MapboxComponent.value.handlerDetails(geoms, 'splitPolygonSource', 'splitPolygonLayer', {
lineStyle: { 'line-color': '#408eff', 'line-width': 3 },
fillStyle: { 'fill-color': '#408eff', 'fill-opacity': 0.1 },
});
console.log('splitPolygonForm', splitPolygonForm.value);
currentPolygon.value = null;
};
const handlerEditPolygonInfo = (e) => {
@ -798,7 +834,7 @@
};
//
const currentPolygon = ref<Number>();
const currentPolygon = ref(null);
const changeCurrentPolygon = (index, item) => {
let geoms = {
type: 'FeatureCollection',
@ -815,7 +851,6 @@
//
const onFeatureClick = (feature) => {
splitPolygonForm.value?.forEach((item, index) => {
console.log('item---', item);
if (item['geom']['properties']['id'] == feature.properties.id) {
changeCurrentPolygon(index, item);
}
@ -839,6 +874,7 @@
fillStyle: { 'fill-color': '#408eff', 'fill-opacity': 0.1 },
});
splitPolygonForm.value = [];
currentPolygon.value = null;
};
@ -917,8 +953,8 @@
}
})
if(deleteIndexs.length<=1){
createMessage.error("请选择至少两个图斑进行合并!");
if(deleteIndexs.length!=2){
createMessage.error("请选择两个图斑进行合并!");
return;
}

@ -0,0 +1,66 @@
// vite.config.ts
import { defineApplicationConfig } from "file:///E:/projects/%E8%B4%A2%E6%BA%90%E7%B3%BB%E7%BB%9F/CaiYuanYiTiHua/internal/vite-config/dist/index.mjs";
var vite_config_default = defineApplicationConfig({
overrides: {
optimizeDeps: {
include: [
"echarts/core",
"echarts/charts",
"echarts/components",
"echarts/renderers",
"qrcode",
"@iconify/iconify",
"ant-design-vue/es/locale/zh_CN",
"ant-design-vue/es/locale/en_US",
"@/../lib/vform/designer.umd.js"
]
},
build: {
/* 其他build生产打包配置省略 */
//...
target: "esnext",
commonjsOptions: {
include: /node_modules|lib/
//这里记得把lib目录加进来否则生产打包会报错
}
},
server: {
proxy: {
"/basic-api": {
target: "http://localhost:3000",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^/basic-api`), "")
// only https
// secure: false
},
"/upload": {
target: "http://localhost:3300/upload",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^/upload`), "")
}
},
warmup: {
clientFiles: ["./index.html", "./src/{views,components}/*"]
}
},
define: {
"process.env": {
BASE_URL: "/"
}
},
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true
}
}
},
plugins: []
}
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJFOlxcXFxwcm9qZWN0c1xcXFxcdThEMjJcdTZFOTBcdTdDRkJcdTdFREZcXFxcQ2FpWXVhbllpVGlIdWFcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkU6XFxcXHByb2plY3RzXFxcXFx1OEQyMlx1NkU5MFx1N0NGQlx1N0VERlxcXFxDYWlZdWFuWWlUaUh1YVxcXFx2aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRTovcHJvamVjdHMvJUU4JUI0JUEyJUU2JUJBJTkwJUU3JUIzJUJCJUU3JUJCJTlGL0NhaVl1YW5ZaVRpSHVhL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQXBwbGljYXRpb25Db25maWcgfSBmcm9tICdAdmJlbi92aXRlLWNvbmZpZyc7XG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUFwcGxpY2F0aW9uQ29uZmlnKHtcbiAgb3ZlcnJpZGVzOiB7XG4gICAgb3B0aW1pemVEZXBzOiB7XG4gICAgICBpbmNsdWRlOiBbXG4gICAgICAgICdlY2hhcnRzL2NvcmUnLFxuICAgICAgICAnZWNoYXJ0cy9jaGFydHMnLFxuICAgICAgICAnZWNoYXJ0cy9jb21wb25lbnRzJyxcbiAgICAgICAgJ2VjaGFydHMvcmVuZGVyZXJzJyxcbiAgICAgICAgJ3FyY29kZScsXG4gICAgICAgICdAaWNvbmlmeS9pY29uaWZ5JyxcbiAgICAgICAgJ2FudC1kZXNpZ24tdnVlL2VzL2xvY2FsZS96aF9DTicsXG4gICAgICAgICdhbnQtZGVzaWduLXZ1ZS9lcy9sb2NhbGUvZW5fVVMnLFxuICAgICAgICAnQC8uLi9saWIvdmZvcm0vZGVzaWduZXIudW1kLmpzJyxcbiAgICAgIF0sXG4gICAgfSxcbiAgICBidWlsZDoge1xuICAgICAgLyogXHU1MTc2XHU0RUQ2YnVpbGRcdTc1MUZcdTRFQTdcdTYyNTNcdTUzMDVcdTkxNERcdTdGNkVcdTc3MDFcdTc1NjUgKi9cbiAgICAgIC8vLi4uXG4gICAgICB0YXJnZXQ6ICdlc25leHQnLFxuICAgICAgY29tbW9uanNPcHRpb25zOiB7XG4gICAgICAgIGluY2x1ZGU6IC9ub2RlX21vZHVsZXN8bGliLywgLy9cdThGRDlcdTkxQ0NcdThCQjBcdTVGOTdcdTYyOEFsaWJcdTc2RUVcdTVGNTVcdTUyQTBcdThGREJcdTY3NjVcdUZGMENcdTU0MjZcdTUyMTlcdTc1MUZcdTRFQTdcdTYyNTNcdTUzMDVcdTRGMUFcdTYyQTVcdTk1MTlcdUZGMDFcdUZGMDFcbiAgICAgIH0sXG4gICAgfSxcbiAgICBzZXJ2ZXI6IHtcbiAgICAgIHByb3h5OiB7XG4gICAgICAgICcvYmFzaWMtYXBpJzoge1xuICAgICAgICAgIHRhcmdldDogJ2h0dHA6Ly9sb2NhbGhvc3Q6MzAwMCcsXG4gICAgICAgICAgY2hhbmdlT3JpZ2luOiB0cnVlLFxuICAgICAgICAgIHdzOiB0cnVlLFxuICAgICAgICAgIHJld3JpdGU6IChwYXRoKSA9PiBwYXRoLnJlcGxhY2UobmV3IFJlZ0V4cChgXi9iYXNpYy1hcGlgKSwgJycpLFxuICAgICAgICAgIC8vIG9ubHkgaHR0cHNcbiAgICAgICAgICAvLyBzZWN1cmU6IGZhbHNlXG4gICAgICAgIH0sXG4gICAgICAgICcvdXBsb2FkJzoge1xuICAgICAgICAgIHRhcmdldDogJ2h0dHA6Ly9sb2NhbGhvc3Q6MzMwMC91cGxvYWQnLFxuICAgICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcbiAgICAgICAgICB3czogdHJ1ZSxcbiAgICAgICAgICByZXdyaXRlOiAocGF0aCkgPT4gcGF0aC5yZXBsYWNlKG5ldyBSZWdFeHAoYF4vdXBsb2FkYCksICcnKSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICB3YXJtdXA6IHtcbiAgICAgICAgY2xpZW50RmlsZXM6IFsnLi9pbmRleC5odG1sJywgJy4vc3JjL3t2aWV3cyxjb21wb25lbnRzfS8qJ10sXG4gICAgICB9LFxuICAgIH0sXG4gICAgZGVmaW5lOiB7XG4gICAgICAncHJvY2Vzcy5lbnYnOiB7XG4gICAgICAgIEJBU0VfVVJMOiAnLycsXG4gICAgICB9LFxuICAgIH0sXG4gICAgY3NzOiB7XG4gICAgICBwcmVwcm9jZXNzb3JPcHRpb25zOiB7XG4gICAgICAgIGxlc3M6IHtcbiAgICAgICAgICBqYXZhc2NyaXB0RW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBwbHVnaW5zOiBbXSxcbiAgfSxcbn0pO1xuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUF1VCxTQUFTLCtCQUErQjtBQUUvVixJQUFPLHNCQUFRLHdCQUF3QjtBQUFBLEVBQ3JDLFdBQVc7QUFBQSxJQUNULGNBQWM7QUFBQSxNQUNaLFNBQVM7QUFBQSxRQUNQO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLElBQ0EsT0FBTztBQUFBO0FBQUE7QUFBQSxNQUdMLFFBQVE7QUFBQSxNQUNSLGlCQUFpQjtBQUFBLFFBQ2YsU0FBUztBQUFBO0FBQUEsTUFDWDtBQUFBLElBQ0Y7QUFBQSxJQUNBLFFBQVE7QUFBQSxNQUNOLE9BQU87QUFBQSxRQUNMLGNBQWM7QUFBQSxVQUNaLFFBQVE7QUFBQSxVQUNSLGNBQWM7QUFBQSxVQUNkLElBQUk7QUFBQSxVQUNKLFNBQVMsQ0FBQyxTQUFTLEtBQUssUUFBUSxJQUFJLE9BQU8sYUFBYSxHQUFHLEVBQUU7QUFBQTtBQUFBO0FBQUEsUUFHL0Q7QUFBQSxRQUNBLFdBQVc7QUFBQSxVQUNULFFBQVE7QUFBQSxVQUNSLGNBQWM7QUFBQSxVQUNkLElBQUk7QUFBQSxVQUNKLFNBQVMsQ0FBQyxTQUFTLEtBQUssUUFBUSxJQUFJLE9BQU8sVUFBVSxHQUFHLEVBQUU7QUFBQSxRQUM1RDtBQUFBLE1BQ0Y7QUFBQSxNQUNBLFFBQVE7QUFBQSxRQUNOLGFBQWEsQ0FBQyxnQkFBZ0IsNEJBQTRCO0FBQUEsTUFDNUQ7QUFBQSxJQUNGO0FBQUEsSUFDQSxRQUFRO0FBQUEsTUFDTixlQUFlO0FBQUEsUUFDYixVQUFVO0FBQUEsTUFDWjtBQUFBLElBQ0Y7QUFBQSxJQUNBLEtBQUs7QUFBQSxNQUNILHFCQUFxQjtBQUFBLFFBQ25CLE1BQU07QUFBQSxVQUNKLG1CQUFtQjtBQUFBLFFBQ3JCO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxJQUNBLFNBQVMsQ0FBQztBQUFBLEVBQ1o7QUFDRixDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo=
Loading…
Cancel
Save