增加沙盘设置

dev_xd
haha 2025-06-10 16:17:24 +08:00
parent 4b3bceb065
commit d21d683289
13 changed files with 1481 additions and 672 deletions

View File

@ -0,0 +1,344 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package net.hasor.dataway.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.function.Supplier;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.hasor.core.spi.SpiTrigger;
import net.hasor.dataql.DataQueryException;
import net.hasor.dataql.QueryResult;
import net.hasor.dataql.domain.DataModel;
import net.hasor.dataql.runtime.ThrowRuntimeException;
import net.hasor.dataway.dal.ApiStatusEnum;
import net.hasor.dataway.dal.FieldDef;
import net.hasor.dataway.dal.QueryCondition;
import net.hasor.dataway.spi.ApiInfo;
import net.hasor.dataway.spi.SerializationChainSpi;
import net.hasor.utils.StringUtils;
import net.hasor.utils.io.IOUtils;
import net.hasor.web.Invoker;
public class DatawayUtils {
private static final ThreadLocal<Long> localRequestTime = ThreadLocal.withInitial(System::currentTimeMillis);
public static final Supplier<Map<FieldDef, String>> STATUS_UPDATE_TO_EDITOR = () -> new HashMap<FieldDef, String>() {
{
this.put(FieldDef.STATUS, String.valueOf(ApiStatusEnum.Editor.typeNum()));
this.put(FieldDef.GMT_TIME, String.valueOf(System.currentTimeMillis()));
}
};
public static final Supplier<Map<FieldDef, String>> STATUS_UPDATE_TO_PUBLISHED = () -> new HashMap<FieldDef, String>() {
{
this.put(FieldDef.STATUS, String.valueOf(ApiStatusEnum.Published.typeNum()));
this.put(FieldDef.GMT_TIME, String.valueOf(System.currentTimeMillis()));
}
};
public static final Supplier<Map<FieldDef, String>> STATUS_UPDATE_TO_CHANGES = () -> new HashMap<FieldDef, String>() {
{
this.put(FieldDef.STATUS, String.valueOf(ApiStatusEnum.Changes.typeNum()));
this.put(FieldDef.GMT_TIME, String.valueOf(System.currentTimeMillis()));
}
};
public static final Supplier<Map<FieldDef, String>> STATUS_UPDATE_TO_DISABLE = () -> new HashMap<FieldDef, String>() {
{
this.put(FieldDef.STATUS, String.valueOf(ApiStatusEnum.Disable.typeNum()));
this.put(FieldDef.GMT_TIME, String.valueOf(System.currentTimeMillis()));
}
};
public static final Supplier<Map<FieldDef, String>> STATUS_UPDATE_TO_DELETE = () -> new HashMap<FieldDef, String>() {
{
this.put(FieldDef.STATUS, String.valueOf(ApiStatusEnum.Delete.typeNum()));
this.put(FieldDef.GMT_TIME, String.valueOf(System.currentTimeMillis()));
}
};
public DatawayUtils() {
}
public static String getDwContextPath(Invoker invoker, String defaultPath) {
String contextPath = invoker.getHttpRequest().getContextPath();
String contextPathProxy2 = invoker.getHttpRequest().getHeader("DW_CONTEXT_PATH_PROXY");
String contextPathProxy = StringUtils.isNotBlank(defaultPath) ? defaultPath : contextPathProxy2;
if (StringUtils.isBlank(contextPathProxy)) {
if (StringUtils.isBlank(contextPath)) {
contextPath = "/";
}
if (contextPath.endsWith("/")) {
contextPath = contextPath.substring(0, contextPath.length() - 1);
}
} else {
contextPath = contextPathProxy;
}
return contextPath;
}
public static String evalCodeValueForSQL(String strCodeValue, Map<String, Object> strRequestBody) {
StringBuilder paramKeyBuilder = new StringBuilder("");
StringBuilder callKeyBuilder = new StringBuilder("");
for(String key : strRequestBody.keySet()) {
paramKeyBuilder.append("`" + key + "`,");
callKeyBuilder.append("${" + key + "},");
}
if (paramKeyBuilder.length() > 0) {
paramKeyBuilder.deleteCharAt(paramKeyBuilder.length() - 1);
callKeyBuilder.deleteCharAt(callKeyBuilder.length() - 1);
}
strCodeValue = "var tempCall = @@sql(" + paramKeyBuilder.toString() + ")<%" + strCodeValue + "%>;\n";
strCodeValue = strCodeValue + "return tempCall(" + callKeyBuilder.toString() + ");";
return strCodeValue;
}
public static long resetLocalTime() {
long currentTimeMillis = System.currentTimeMillis();
localRequestTime.remove();
localRequestTime.set(currentTimeMillis);
return currentTimeMillis;
}
public static long currentLostTime() {
return System.currentTimeMillis() - (Long)localRequestTime.get();
}
public static boolean isResultStructure(Map<String, Object> optionMap) {
return optionMap == null ? true : (Boolean)optionMap.getOrDefault("resultStructure", true);
}
public static String wrapParameterName(Map<String, Object> optionMap) {
if (optionMap == null) {
return null;
} else {
boolean wrapAllParameters = (Boolean)optionMap.getOrDefault("wrapAllParameters", false);
if (wrapAllParameters) {
String wrapParameterName = (String)optionMap.getOrDefault("wrapParameterName", "root");
return StringUtils.isBlank(wrapParameterName) ? null : wrapParameterName.trim();
} else {
return null;
}
}
}
public static Result<Object> queryResultToResultWithSpecialValue(Map<String, Object> optionMap, final QueryResult queryResult, Object specialValue) {
final Object resultValue;
if (specialValue instanceof DataModel) {
resultValue = ((DataModel)specialValue).unwrap();
} else {
resultValue = specialValue;
}
if (!isResultStructure(optionMap)) {
return Result.of(resultValue);
} else {
Map<String, Object> resultData = new LinkedHashMap<String, Object>() {
{
this.put("success", true);
this.put("message", "OK");
this.put("code", queryResult.getCode());
this.put("location", (Object)null);
this.put("lifeCycleTime", DatawayUtils.currentLostTime());
this.put("executionTime", queryResult.executionTime());
this.put("value", resultValue);
}
};
return Result.of(doResponseFormat(optionMap, resultData));
}
}
public static Result<Object> exceptionToResult(Throwable e) {
return e instanceof ThrowRuntimeException ? exceptionToResultWithSpecialValue((Map)null, e, ((ThrowRuntimeException)e).getResult().unwrap()) : exceptionToResultWithSpecialValue((Map)null, e, e.getMessage());
}
public static Result<Object> exceptionToResultWithSpecialValue(Map<String, Object> optionMap, Throwable e, Object specialValue) {
if (!isResultStructure(optionMap) && specialValue != null) {
return Result.of(specialValue);
} else {
Map<String, Object> resultData = new LinkedHashMap();
resultData.put("success", false);
resultData.put("message", e.getLocalizedMessage());
resultData.put("value", specialValue);
resultData.put("lifeCycleTime", currentLostTime());
if (e instanceof ThrowRuntimeException) {
resultData.put("location", ((ThrowRuntimeException)e).getLocation().toString());
resultData.put("code", ((ThrowRuntimeException)e).getThrowCode());
resultData.put("executionTime", ((ThrowRuntimeException)e).getExecutionTime());
} else if (e instanceof DataQueryException) {
resultData.put("location", ((DataQueryException)e).getLocation().toString());
resultData.put("code", 500);
resultData.put("executionTime", -1);
} else {
resultData.put("location", "Unknown");
resultData.put("code", 500);
resultData.put("executionTime", -1);
}
return Result.of(doResponseFormat(optionMap, resultData));
}
}
private static Object doResponseFormat(Map<String, Object> optionMap, Map<String, Object> resultData) {
if (optionMap != null && optionMap.containsKey("responseFormat")) {
Object responseFormat = optionMap.get("responseFormat");
Map<String, Object> finalResult = new LinkedHashMap();
LinkedHashMap<?, ?> jsonObject = (LinkedHashMap)JSONObject.parseObject(responseFormat.toString(), LinkedHashMap.class);
for(Object key : jsonObject.keySet()) {
Object value = jsonObject.get(key);
if (value == null) {
finalResult.put(key.toString(), (Object)null);
} else {
switch (value.toString()) {
case "@resultStatus":
finalResult.put(key.toString(), resultData.get("success"));
break;
case "@resultMessage":
finalResult.put(key.toString(), resultData.get("message"));
break;
case "@codeLocation":
finalResult.put(key.toString(), resultData.get("location"));
break;
case "@resultCode":
finalResult.put(key.toString(), resultData.get("code"));
break;
case "@timeLifeCycle":
finalResult.put(key.toString(), resultData.get("lifeCycleTime"));
break;
case "@timeExecution":
finalResult.put(key.toString(), resultData.get("executionTime"));
break;
case "@resultData":
finalResult.put(key.toString(), resultData.get("value"));
break;
default:
finalResult.put(key.toString(), value);
}
}
}
return finalResult;
} else {
return resultData;
}
}
public static Object responseData(SpiTrigger spiTrigger, ApiInfo apiInfo, String contentType, Invoker invoker, Object objectMap) throws IOException {
HttpServletRequest httpRequest = invoker.getHttpRequest();
HttpServletResponse httpResponse = invoker.getHttpResponse();
if (!httpResponse.isCommitted()) {
Object resultData = spiTrigger.chainSpi(SerializationChainSpi.class, (listener, lastResult) -> listener.doSerialization(apiInfo, invoker, lastResult), objectMap);
String contentDisposition = null;
long contentLength = -1L;
if (resultData instanceof SerializationChainSpi.SerializationInfo) {
contentType = ((SerializationChainSpi.SerializationInfo)resultData).getContentType();
contentDisposition = ((SerializationChainSpi.SerializationInfo)resultData).getContentDisposition();
contentLength = ((SerializationChainSpi.SerializationInfo)resultData).getContentLength();
resultData = ((SerializationChainSpi.SerializationInfo)resultData).getData();
}
if (resultData instanceof String) {
setUIContextType(httpRequest, httpResponse, "text");
String characterEncoding = httpResponse.getCharacterEncoding();
characterEncoding="UTF-8";
responseString(httpResponse, contentType, characterEncoding, (String)resultData);
} else if (resultData instanceof byte[]) {
setUIContextType(httpRequest, httpResponse, "bytes");
byte[] bodyByte = (byte[])resultData;
responseBytes(httpResponse, contentType, contentDisposition, (long)bodyByte.length, new ByteArrayInputStream(bodyByte));
} else if (resultData instanceof InputStream) {
setUIContextType(httpRequest, httpResponse, "bytes");
responseBytes(httpResponse, contentType, contentDisposition, contentLength, (InputStream)resultData);
} else {
setUIContextType(httpRequest, httpResponse, "json");
String characterEncoding = httpResponse.getCharacterEncoding();
characterEncoding="UTF-8";
String body = JSON.toJSONString(resultData, new SerializerFeature[]{SerializerFeature.WriteMapNullValue});
responseString(httpResponse, contentType, characterEncoding, body);
}
}
return objectMap;
}
private static void setUIContextType(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String responseContextType) {
if ("true".equalsIgnoreCase(httpRequest.getHeader("X-InterfaceUI-Info"))) {
httpResponse.setHeader("X-InterfaceUI-ContextType", responseContextType);
}
}
private static void responseBytes(HttpServletResponse httpResponse, String contentType, String contentDisposition, long contentLength, InputStream bodyInputStream) throws IOException {
httpResponse.setContentType(contentType);
if (StringUtils.isNotBlank(contentDisposition)) {
httpResponse.setHeader("Content-Disposition", contentDisposition);
}
if (contentLength > 0L) {
if (contentLength > 2147483647L) {
httpResponse.setContentLengthLong(contentLength);
} else {
httpResponse.setContentLength((int)contentLength);
}
}
try (ServletOutputStream output = httpResponse.getOutputStream()) {
IOUtils.copy(bodyInputStream, output);
output.flush();
}
}
private static void responseString(HttpServletResponse httpResponse, String contentType, String characterEncoding, String contentBody) throws IOException {
if (StringUtils.isNotBlank(characterEncoding)) {
contentType = contentType + ";charset=" + characterEncoding;
}
if (StringUtils.isNotBlank(contentType)) {
httpResponse.setContentType(contentType);
}
try (PrintWriter writer = httpResponse.getWriter()) {
writer.write(contentBody);
writer.flush();
}
}
public static String generateID() {
long timeMillis = System.currentTimeMillis();
int nextInt = (new Random(timeMillis)).nextInt();
String s = Integer.toString(nextInt, 24);
if (s.length() > 4) {
s = s.substring(0, 4);
} else {
s = StringUtils.rightPad(s, 4, "0");
}
return Long.toString(timeMillis, 24) + s;
}
public static Map<QueryCondition, Object> conditionByApiId(final String apiId) {
return new HashMap<QueryCondition, Object>() {
{
this.put(QueryCondition.ApiId, apiId);
}
};
}
}

View File

@ -10,7 +10,7 @@
"dev:prod": "vite --mode production",
"build:prod": "vite build && npm run pkg",
"build:stage": "vite build --mode staging",
"pkg":"node make.cjs",
"pkg": "node make.cjs",
"preview": "vite preview"
},
"repository": {
@ -48,6 +48,7 @@
"@vitejs/plugin-vue": "5.0.5",
"@vitejs/plugin-vue-jsx": "^4.1.2",
"less": "^4.3.0",
"mitt": "^3.0.1",
"sass": "1.77.5",
"unplugin-auto-import": "0.17.6",
"unplugin-vue-components": "^28.5.0",

View File

@ -61,3 +61,11 @@ export function viewpointDeleteById(data) {
params: data,
});
}
export function devicePositionGet(data) {
return request({
url: "/manage/api/bim/devicePosition/get",
method: "get",
params: data,
});
}

View File

@ -0,0 +1 @@
<svg class="icon" style="width: 1.0400390625em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1065 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7908"><path d="M0 1024V250.6656h101.978163a623.725473 623.725473 0 0 0-5.774667 85.596129c0 285.33408 194.290925 517.180818 433.468623 517.180818s433.448146-231.273367 433.448147-517.180818a641.807143 641.807143 0 0 0-5.75419-85.596129h101.281926v773.3344z m379.592209-250.542735a219.212095 219.212095 0 0 1-105.295525-24.962124 200.41371 200.41371 0 0 1-16.054393-80.968204 198.181658 198.181658 0 0 0 16.054393 80.968204c-51.193857-83.609807-27.910891-215.710435 69.726033-303.743391l106.954206-101.240971a29.323841 29.323841 0 0 1 37.187217 0l69.746511 52.873015v4.402672c-32.538815 35.200896-67.412071 83.630284-92.988522 114.448986s-18.614086 44.026717-4.668879 57.214254a36.675279 36.675279 0 0 0 46.504499 4.402672l13.945207-8.805344a1190.707675 1190.707675 0 0 0 120.817502-88.053433h4.648402l55.821781 66.040075a25.658361 25.658361 0 0 1 0 35.221373l-106.954205 101.220494a311.258649 311.258649 0 0 1-215.50566 90.981722z m78.920449-221.157461c-2.313962-12.675599-1.33104-15.41959 10.50498-30.122465a191.731232 191.731232 0 0 1 23.876815-24.573052s23.221533-26.41603 37.187217-39.624045a984.335 984.335 0 0 1 93.008999-101.240971l186.017998-145.390553 4.627925-4.382194 4.259328-4.095509a90.387873 90.387873 0 0 1 0.389074-31.16682s7.146662-46.893573 18.614086-107.650441v-6.798545l2.293485-6.593768 0.901012-2.559693 1.433428-6.470904c0.143343-0.675759 0.307163-1.310563 0.430028-2.047754H841.627005c0-3.194497 0-4.095509 1.822501-6.040875 0.880534-3.74739 1.802024-7.597168 2.805423-11.528857 0-4.423149 4.689357-8.825821 4.689358-13.208015a9.74731 9.74731 0 0 1 9.276327-8.825821 16.648242 16.648242 0 0 1 9.317281 4.402672 15.66532 15.66532 0 0 1 4.648403 13.228493l-4.648403 17.590209a443.707395 443.707395 0 0 0-27.91089 105.66412 88.811103 88.811103 0 0 1-4.8327 26.41603 13.719954 13.719954 0 0 1-1.781547 5.549414l-2.682558 7.658601a19.924649 19.924649 0 0 0 4.66888 26.436508l9.296804 13.187537a22.791505 22.791505 0 0 0 27.931369 4.402672 77.814662 77.814662 0 0 1 41.815142-13.208015 510.91469 510.91469 0 0 0 111.623085-26.41603l18.593609-8.825821a17.692597 17.692597 0 0 1 13.945206 4.361717c4.648402 4.423149 4.648402 4.423149 4.648403 8.825821a9.767788 9.767788 0 0 1-9.296805 8.82582 467.563732 467.563732 0 0 1-134.865096 35.200896 101.302404 101.302404 0 0 0-51.193857 17.610687l-4.689357 4.402672c0 4.402672-4.648402 4.402672-9.296804 8.784866l-162.75551 154.093508c-55.821781 48.429388-84.387953 68.825021-132.366836 105.664121a302.658081 302.658081 0 0 1-59.630604 41.671799c-8.191017 3.849778-10.648322 6.716634-17.569732 6.716634a28.66856 28.66856 0 0 1-24.777826-20.047514zM892.779906 61.739791v-4.382194c0-4.402672 4.66888-8.825821 4.66888-13.228492L906.745591 17.713074h4.689357a964.16462 964.16462 0 0 1 139.472543 132.080151v4.382194l-27.890413 8.805343c-4.66888 4.402672-9.317282 4.402672-18.614086 4.402672a1235.348718 1235.348718 0 0 0-111.623086-105.643643z m-53.487341-10.99644z" p-id="7909"></path></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,2 @@
<svg class="icon" style="width: 1em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5537" data-spm-anchor-id="a313x.search_index.i1.i2.30073a81HnVMdv">
<path d="M768 42.666667H256C209.066667 42.666667 170.666667 81.066667 170.666667 128v682.666667c0 46.933333 38.4 85.333333 85.333333 85.333333v42.666667c0 23.466667 19.2 42.666667 42.666667 42.666666h85.333333c23.466667 0 42.666667-19.2 42.666667-42.666666v-42.666667h170.666666v42.666667c0 23.466667 19.2 42.666667 42.666667 42.666666h85.333333c23.466667 0 42.666667-19.2 42.666667-42.666666v-42.666667c46.933333 0 85.333333-38.4 85.333333-85.333333V128c0-46.933333-38.4-85.333333-85.333333-85.333333zM309.333333 170.666667h405.333334c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32h-405.333334c-17.066667 0-32-14.933333-32-32S292.266667 170.666667 309.333333 170.666667z m0 554.666666c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32-32-14.933333-32-32 14.933333-32 32-32z m106.666667 64c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32 32 14.933333 32 32-14.933333 32-32 32z m106.666667 0c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32 32 14.933333 32 32-14.933333 32-32 32z m-42.666667-115.2c-8.533333 12.8-25.6 8.533333-23.466667-6.4L469.333333 512h-72.533333c-14.933333 0-23.466667-17.066667-12.8-29.866667l136.533333-172.8c8.533333-12.8 25.6-8.533333 23.466667 6.4l-14.933333 155.733334h72.533333c14.933333 0 23.466667 17.066667 12.8 29.866666l-134.4 172.8z" p-id="5538"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,3 @@
<svg class="icon" style="width: 1em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3533">
<path d="M905.5 363.9L357.2 143l-199 108.5v64.2h-65V212.9l260.4-142 577.2 233.2zM502.7 953.1H249.8V504.3h65v383.8h123V504.3h64.9zM835.7 777c-52.4 0-95.1-42.7-95.1-95.1 0-17.9 14.5-32.5 32.5-32.5s32.5 14.5 32.5 32.5c0 16.7 13.5 30.2 30.2 30.2s30.2-13.5 30.2-30.2-13.5-30.2-30.2-30.2h-32.5l-3.9-32.5V503.7c0-17.9 14.5-32.5 32.5-32.5 17.9 0 32.5 14.5 32.5 32.5v88.1c39.5 12.7 66.6 48.3 66.6 90.1-0.2 52.4-42.9 95.1-95.3 95.1z" p-id="3534"></path>
<path d="M855.9 536.1H168.1c-41.3 0-74.9-33.6-74.9-74.9V304.1h837.6v157.1c0 41.4-33.6 74.9-74.9 74.9z m-697.7-167v92.2c0 5.5 4.5 9.9 10 9.9H856c5.5 0 10-4.4 10-9.9v-92.2H158.2zM177.2 888.1h412.1V953H177.2z" p-id="3535"></path></svg>

After

Width:  |  Height:  |  Size: 873 B

View File

@ -0,0 +1,4 @@
<svg class="icon"
style="width: 1em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1709">
<path d="M902.4 678.4L870.4 768c-2.133333 6.4-8.533333 10.666667-14.933333 6.4L55.466667 484.266667c-12.8 32 4.266667 70.4 38.4 81.066666L298.666667 640l-14.933334 42.666667c-4.266667 12.8-14.933333 21.333333-29.866666 21.333333H106.666667v-53.333333c0-17.066667-14.933333-32-32-32S42.666667 633.6 42.666667 650.666667v170.666666c0 17.066667 14.933333 32 32 32S106.666667 838.4 106.666667 821.333333V768h151.466666c36.266667 0 70.4-23.466667 81.066667-57.6l17.066667-49.066667 488.533333 179.2c32 12.8 68.266667-4.266667 81.066667-38.4l14.933333-40.533333c10.666667-34.133333-6.4-70.4-38.4-83.2zM951.466667 407.466667L253.866667 153.6c-44.8-17.066667-93.866667 6.4-110.933334 51.2L85.333333 364.8c-17.066667 44.8 6.4 93.866667 51.2 108.8L714.666667 682.666667c32 12.8 70.4 2.133333 93.866666-23.466667l164.266667-183.466667c17.066667-21.333333 8.533333-57.6-21.333333-68.266666z" p-id="1710">
</path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -195,4 +195,10 @@ aside {
overflow: hidden !important;
}
}
}
}
body.is-sapi {
.app-main {
height: calc(100vh - 84px);
}
}

View File

@ -1,6 +1,8 @@
import { createWebHashHistory, createRouter } from 'vue-router'
/* Layout */
import Layout from '@/layout'
import mitt from 'mitt';
const emitter = mitt();
/**
* Note: 路由配置项
@ -238,16 +240,14 @@ export const dynamicRoutes = [
}
]
const router = createRouter({
export const router = createRouter({
history: createWebHashHistory(),
routes: constantRoutes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
},
routes: [...constantRoutes, ...dynamicRoutes]
})
router.afterEach((to, from) => {
emitter.emit('routeChanged', { to, from });
});
export { emitter };
export default router;

View File

@ -1,108 +1,147 @@
import axios from 'axios'
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi'
import cache from '@/plugins/cache'
import { saveAs } from 'file-saver'
import useUserStore from '@/store/modules/user'
import axios from "axios";
import {
ElNotification,
ElMessageBox,
ElMessage,
ElLoading,
} from "element-plus";
import { getToken } from "@/utils/auth";
import errorCode from "@/utils/errorCode";
import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from "@/plugins/cache";
import { saveAs } from "file-saver";
import useUserStore from "@/store/modules/user";
let downloadLoadingInstance;
// 是否显示重新登录
export let isRelogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分
baseURL: import.meta.env.VITE_APP_BASE_API,
// 超时
timeout: 60000
})
timeout: 60000,
});
// request拦截器
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
service.interceptors.request.use(
(config) => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false;
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
if (getToken() && !isToken) {
config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
}
const sessionObj = cache.session.getJSON('sessionObj')
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj)
} else {
const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = '数据正在处理,请勿重复提交';
console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message))
config.headers["Content-Type"] = "application/json;charset=UTF-8";
// get请求映射params参数
if (config.method === "get" && config.params) {
let url = config.url + "?" + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
if (
!isRepeatSubmit &&
(config.method === "post" || config.method === "put")
) {
const requestObj = {
url: config.url,
data:
typeof config.data === "object"
? JSON.stringify(config.data)
: config.data,
time: new Date().getTime(),
};
const sessionObj = cache.session.getJSON("sessionObj");
if (
sessionObj === undefined ||
sessionObj === null ||
sessionObj === ""
) {
cache.session.setJSON("sessionObj", requestObj);
} else {
cache.session.setJSON('sessionObj', requestObj)
const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
if (
s_data === requestObj.data &&
requestObj.time - s_time < interval &&
s_url === requestObj.url
) {
const message = "数据正在处理,请勿重复提交";
console.warn(`[${s_url}]: ` + message);
return Promise.reject(new Error(message));
} else {
cache.session.setJSON("sessionObj", requestObj);
}
}
}
return config;
},
(error) => {
console.log(error);
Promise.reject(error);
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
);
// 响应拦截器
service.interceptors.response.use(res => {
service.interceptors.response.use(
(res) => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
const msg = errorCode[code] || res.data.msg || errorCode["default"];
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
if (
res.request.responseType === "blob" ||
res.request.responseType === "arraybuffer"
) {
return res.data;
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false;
useUserStore().logOut().then(() => {
location.href = '#/index';
ElMessageBox.confirm(
"登录状态已过期,您可以继续留在该页面,或者重新登录",
"系统提示",
{
confirmButtonText: "重新登录",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
isRelogin.show = false;
useUserStore()
.logOut()
.then(() => {
location.href = "#/index";
});
})
}).catch(() => {
isRelogin.show = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
.catch(() => {
isRelogin.show = false;
});
}
return Promise.reject("无效的会话,或者会话已过期,请重新登录。");
} else if (code === 500) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
ElMessage({ message: msg, type: "error" });
return Promise.reject(new Error(msg));
} else if (code === 601) {
ElMessage({ message: msg, type: 'warning' })
return Promise.reject(new Error(msg))
ElMessage({ message: msg, type: "warning" });
return Promise.reject(new Error(msg));
} else if (code !== 200) {
ElNotification.error({ title: msg })
return Promise.reject('error')
ElNotification.error({ title: msg });
return Promise.reject("error");
} else {
return Promise.resolve(res.data)
return Promise.resolve(res.data);
}
},
error => {
console.log('err' + error)
(error) => {
console.log("err" + error);
let { message } = error;
if (message == "Network Error") {
message = "后端接口连接异常";
@ -111,36 +150,47 @@ service.interceptors.response.use(res => {
} else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error)
ElMessage({ message: message, type: "error", duration: 5 * 1000 });
return Promise.reject(error);
}
)
);
// 通用下载方法
export function download(url, params, filename, config) {
downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
return service.post(url, params, {
transformRequest: [(params) => { return tansParams(params) }],
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: 'blob',
...config
}).then(async (data) => {
const isBlob = blobValidate(data);
if (isBlob) {
const blob = new Blob([data])
saveAs(blob, filename)
} else {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
ElMessage.error(errMsg);
}
downloadLoadingInstance.close();
}).catch((r) => {
console.error(r)
ElMessage.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close();
})
downloadLoadingInstance = ElLoading.service({
text: "正在下载数据,请稍候",
background: "rgba(0, 0, 0, 0.7)",
});
return service
.post(url, params, {
transformRequest: [
(params) => {
return tansParams(params);
},
],
headers: { "Content-Type": "application/x-www-form-urlencoded" },
responseType: "blob",
...config,
})
.then(async (data) => {
const isBlob = blobValidate(data);
if (isBlob) {
const blob = new Blob([data]);
saveAs(blob, filename);
} else {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg =
errorCode[rspObj.code] || rspObj.msg || errorCode["default"];
ElMessage.error(errMsg);
}
downloadLoadingInstance.close();
})
.catch((r) => {
console.error(r);
ElMessage.error("下载文件出现错误,请联系管理员!");
downloadLoadingInstance.close();
});
}
export default service
export default service;

View File

@ -1,15 +1,15 @@
<template>
<div class="model-floor-tree scroll-box" :class="{ 'hide-tree': !showTree }">
<div class="nav-header">
<span class="title">结构树</span>
<span class="toolbar">
<el-icon color="#fff" @click="showTree=!showTree">
<ArrowUpBold v-if="showTree" />
<ArrowDownBold v-else />
</el-icon>
</span>
</div>
<!-- <a-tree
<div class="model-floor-tree scroll-box" :class="{ 'hide-tree': !showTree }">
<div class="nav-header">
<span class="title">结构树</span>
<span class="toolbar">
<el-icon color="#fff" @click="showTree = !showTree">
<ArrowUpBold v-if="showTree" />
<ArrowDownBold v-else />
</el-icon>
</span>
</div>
<!-- <a-tree
checkable
class="model-tree"
:tree-data="modelTrees"
@ -28,325 +28,349 @@
</span>
</template>
</a-tree>-->
<div class="scroll-box">
<a-tree ref="tree" v-model:expandedKeys="expandedKeys" @check="onCheckTree" v-model:selectedKeys="selectedKeys" :tree-data="modelTrees" checkable default-expand-all :load-data="loadTree"></a-tree>
</div>
<div class="scroll-box">
<a-tree
ref="tree"
v-model:expandedKeys="expandedKeys"
@check="onCheckTree"
v-model:selectedKeys="selectedKeys"
:tree-data="modelTrees"
checkable
default-expand-all
:load-data="loadTree"
></a-tree>
</div>
</div>
</template>
<script>
import { getModelTree, getTreeAllLeafChild } from '@/api/bim/bimModel'
import { getModelTree, getTreeAllLeafChild } from "@/api/bim/bimModel";
export default {
props: {
projectMessage: {
type: Object,
default: undefined,
},
props: {
projectMessage: {
type: Object,
default: undefined,
},
data() {
return {
modelTrees: [],
replaceFields: {
title: 'name',
key: 'glid',
value: 'glid',
},
expandedKeys: [],
visibleList: [], //
checkedKeys: [], //
selectedKeys: [],
selectedFeature: undefined,
requestedData: [], //
firstClick: true,
isMobile: false,
showTree: true,
visibleList: [],
},
data() {
return {
modelTrees: [],
replaceFields: {
title: "name",
key: "glid",
value: "glid",
},
expandedKeys: [],
visibleList: [], //
checkedKeys: [], //
selectedKeys: [],
selectedFeature: undefined,
requestedData: [], //
firstClick: true,
isMobile: false,
showTree: true,
visibleList: [],
};
},
mounted() {
window.mtree = this;
this.modelTrees = [
{
title: "项目模型",
level: 0,
type: "root",
key: "root",
children: [],
hadLoad: true,
},
];
this.projectMessage
.map((d) => {
d.gis = JSON.parse(d.gisJson);
return d;
})
.forEach((d) => {
this.modelTrees[0].children.push({
title: d.modelName,
level: 1,
type: "model",
hasLoad: false,
modelId: d.lightweightName,
key: d.lightweightName,
externalId: "0",
glid: "",
children: [],
data: d,
});
});
this.expandedKeys = ["root"];
this.$nextTick(() => {});
},
methods: {
loadTree(a, b, c) {
return new Promise((resolve, reject) => {
if (a.hasLoad) {
resolve();
return;
}
getModelTree(a.modelId, a.glid).then((d) => {
(d.data || []).forEach((e) => {
let title = e.externalId == 0 ? e.name : e.externalId;
title = title.replace(/[\/\\"]/g, "");
a.children.push({
title: title,
key: e.glid,
glid: e.glid,
externalId: e.externalId,
modelId: a.modelId,
type: "data",
children: [],
hasLoad: false,
isLeaf: e.externalId != 0,
data: e,
});
});
resolve();
});
});
},
mounted() {
window.mtree = this
this.modelTrees = [
{
title: '项目模型',
level: 0,
type: 'root',
key: 'root',
children: [],
hadLoad: true,
},
]
this.projectMessage
.map((d) => {
d.gis = JSON.parse(d.gisJson)
return d
})
.forEach((d) => {
this.modelTrees[0].children.push({
title: d.modelName,
level: 1,
type: 'model',
hasLoad: false,
modelId: d.lightweightName,
key: d.lightweightName,
externalId: '0',
glid: '',
children: [],
data: d,
})
})
this.expandedKeys = ['root']
this.$nextTick(() => {})
addModel(modelId, cb) {
let url = `${window.config.modelUrl}/Tools/output/model/${modelId}/root.glt`;
api.Model.add(
url,
modelId,
() => {},
() => {
console.log("加载模型成功");
cb && cb();
this.$emit("change");
}
);
},
methods: {
loadTree(a, b, c) {
return new Promise((resolve, reject) => {
if (a.hasLoad) {
resolve()
return
}
getModelTree(a.modelId, a.glid).then((d) => {
;(d.data || []).forEach((e) => {
let title = e.externalId == 0 ? e.name : e.externalId
title = title.replace(/[\/\\"]/g, '')
a.children.push({
title: title,
key: e.glid,
glid: e.glid,
externalId: e.externalId,
modelId: a.modelId,
type: 'data',
children: [],
hasLoad: false,
isLeaf: e.externalId != 0,
data: e,
})
})
resolve()
})
})
},
addModel(modelId, cb) {
let url = `${window.config.modelUrl}/Tools/output/model/${modelId}/root.glt`
api.Model.add(
url,
modelId,
() => {},
() => {
console.log('加载模型成功')
cb && cb()
this.$emit('change')
}
)
},
onCheckTree(heckedKeys, e) {
const checkNode = e.node.dataRef
const checked = e.checked
const halfChecked = e.node.halfChecked
if (checkNode.type == 'root') {
if (checked) {
checkNode.children.forEach((m) => {
if (halfChecked) {
if (api.m_model.has(m.modelId)) {
api.Model.remove(m.modelId)
}
this.addModel(m.modelId)
this.$emit('change')
} else {
if (api.m_model.has(m.modelId)) {
api.Model.setVisible(m.modelId, true)
this.$emit('change')
} else {
this.addModel(m.modelId)
}
}
})
} else {
if (api.m_model.size == 0) {
return
}
checkNode.children.forEach((m) => {
if (api.m_model.has(m.modelId)) {
api.Model.remove(m.modelId)
this.$emit('change')
}
})
}
return
}
if (checkNode.type == 'model') {
if (checked) {
if (halfChecked) {
if (api.m_model.has(checkNode.modelId)) {
api.Model.remove(checkNode.modelId)
}
this.addModel(checkNode.modelId)
this.$emit('change')
} else {
if (api.m_model.has(checkNode.modelId)) {
api.Model.setVisible(checkNode.modelId, true)
this.$emit('change')
} else {
this.addModel(checkNode.modelId)
}
}
} else {
if (api.m_model.has(checkNode.modelId)) {
api.Model.remove(checkNode.modelId)
this.$emit('change')
}
}
return
}
if (api.m_model.size == 0) {
let modelId = checkNode.modelId
this.addModel(modelId, () => {
this.showItem(e)
})
onCheckTree(heckedKeys, e) {
const checkNode = e.node.dataRef;
const checked = e.checked;
const halfChecked = e.node.halfChecked;
if (checkNode.type == "root") {
if (checked) {
checkNode.children.forEach((m) => {
if (halfChecked) {
if (api.m_model.has(m.modelId)) {
api.Model.remove(m.modelId);
}
this.addModel(m.modelId);
this.$emit("change");
} else {
this.showItem(e)
if (api.m_model.has(m.modelId)) {
api.Model.setVisible(m.modelId, true);
this.$emit("change");
} else {
this.addModel(m.modelId);
}
}
},
async showItem(e) {
const checkNode = e.node.dataRef
const checked = e.checked
api.Model.setVisible(checkNode.modelId, true)
this.$emit('change')
let externalId = checkNode.externalId
if (externalId != 0) {
if (checked) {
this.visibleList.push(externalId)
api.Feature.setVisible(this.visibleList.join('#'), true, checkNode.modelId, false)
} else {
this.visibleList = this.visibleList.filter((item) => item !== externalId)
api.Feature.setVisible(externalId, false, checkNode.modelId)
}
});
} else {
if (api.m_model.size == 0) {
return;
}
checkNode.children.forEach((m) => {
if (api.m_model.has(m.modelId)) {
api.Model.remove(m.modelId);
this.$emit("change");
}
});
}
return;
}
if (checkNode.type == "model") {
if (checked) {
if (halfChecked) {
if (api.m_model.has(checkNode.modelId)) {
api.Model.remove(checkNode.modelId);
}
this.addModel(checkNode.modelId);
this.$emit("change");
} else {
if (api.m_model.has(checkNode.modelId)) {
api.Model.setVisible(checkNode.modelId, true);
this.$emit("change");
} else {
e.node.disableCheckbox = true
const res = await getTreeAllLeafChild(checkNode.modelId, checkNode.glid)
let nodes = res.data || []
if (nodes.length > 0) {
if (checked) {
this.visibleList = this.MergeArray(nodes, this.visibleList)
api.Model.setVisible(checkNode.modelId, true)
this.$emit('change')
api.Feature.setVisible(this.visibleList.join('#'), true, checkNode.modelId, false)
} else {
this.visibleList = this.DelArray(this.visibleList, nodes)
api.Feature.setVisible(nodes.join('#'), false, checkNode.modelId)
}
}
this.addModel(checkNode.modelId);
}
},
MergeArray(arr1, arr2) {
var _arr = new Array()
for (var i = 0; i < arr1.length; i++) {
_arr.push(arr1[i])
}
for (var i = 0; i < arr2.length; i++) {
var flag = true
for (var j = 0; j < arr1.length; j++) {
if (arr2[i] == arr1[j]) {
flag = false
break
}
}
if (flag) {
_arr.push(arr2[i])
}
}
return _arr
},
DelArray(array1, array2) {
var result = []
for (var i = 0; i < array1.length; i++) {
var k = 0
for (var j = 0; j < array2.length; j++) {
if (array1[i] != array2[j]) {
k++
if (k == array2.length) {
result.push(array1[i])
}
}
}
}
return result
},
}
} else {
if (api.m_model.has(checkNode.modelId)) {
api.Model.remove(checkNode.modelId);
this.$emit("change");
}
}
return;
}
if (api.m_model.size == 0) {
let modelId = checkNode.modelId;
this.addModel(modelId, () => {
this.showItem(e);
});
} else {
this.showItem(e);
}
},
}
async showItem(e) {
const checkNode = e.node.dataRef;
const checked = e.checked;
api.Model.setVisible(checkNode.modelId, true);
this.$emit("change");
let externalId = checkNode.externalId;
if (externalId != 0) {
if (checked) {
this.visibleList.push(externalId);
api.Feature.setVisible(
this.visibleList.join("#"),
true,
checkNode.modelId,
false
);
} else {
this.visibleList = this.visibleList.filter(
(item) => item !== externalId
);
api.Feature.setVisible(externalId, false, checkNode.modelId);
}
} else {
e.node.disableCheckbox = true;
const res = await getTreeAllLeafChild(
checkNode.modelId,
checkNode.glid
);
let nodes = res.data || [];
if (nodes.length > 0) {
if (checked) {
this.visibleList = this.MergeArray(nodes, this.visibleList);
api.Model.setVisible(checkNode.modelId, true);
this.$emit("change");
api.Feature.setVisible(
this.visibleList.join("#"),
true,
checkNode.modelId,
false
);
} else {
this.visibleList = this.DelArray(this.visibleList, nodes);
api.Feature.setVisible(nodes.join("#"), false, checkNode.modelId);
}
}
}
},
MergeArray(arr1, arr2) {
var _arr = new Array();
for (var i = 0; i < arr1.length; i++) {
_arr.push(arr1[i]);
}
for (var i = 0; i < arr2.length; i++) {
var flag = true;
for (var j = 0; j < arr1.length; j++) {
if (arr2[i] == arr1[j]) {
flag = false;
break;
}
}
if (flag) {
_arr.push(arr2[i]);
}
}
return _arr;
},
DelArray(array1, array2) {
var result = [];
for (var i = 0; i < array1.length; i++) {
var k = 0;
for (var j = 0; j < array2.length; j++) {
if (array1[i] != array2[j]) {
k++;
if (k == array2.length) {
result.push(array1[i]);
}
}
}
}
return result;
},
},
};
</script>
<style lang="scss">
.model-floor-tree {
position: absolute;
width: 300px;
top: 20px;
left: 20px;
color: #fff;
background: #274754;
&.hide-tree {
height: 50px;
.ant-tree {
display: none;
}
}
.nav-header {
border-bottom: solid 1px #fff;
line-height: 40px;
padding: 0px 10px;
position: relative;
.title {
color: rgb(0, 255, 212);
font-weight: bold;
}
.toolbar {
position: absolute;
right: 10px;
.el-icon {
cursor: pointer;
}
}
}
position: absolute;
width: 300px;
top: 20px;
left: 20px;
color: #fff;
background: #274754;
&.hide-tree {
height: 50px;
.ant-tree {
background: transparent;
color: #fff;
display: none;
}
.scroll-box {
margin-top: 15px;
height: 64vh;
overflow-y: auto;
&::-webkit-scrollbar {
//
height: 8px;
width: 8px;
}
&::-webkit-scrollbar-thumb {
//
border-radius: 1px;
box-shadow: inset 0 0 1px rgba(255, 255, 255, 0.2);
background: #ffffff;
}
&::-webkit-scrollbar-track {
//
box-shadow: 0;
border-radius: 0;
background: rgba(255, 255, 255, 0.3);
}
.ant-tree-node-content-wrapper {
color: #ffffff;
white-space: nowrap;
&.ant-tree-node-selected {
background: #409eff54 !important;
}
}
.ant-list-empty-text {
padding: 5px;
text-align: left;
}
}
.nav-header {
border-bottom: solid 1px #fff;
line-height: 40px;
padding: 0px 10px;
position: relative;
.title {
color: rgb(0, 255, 212);
font-weight: bold;
}
.toolbar {
position: absolute;
right: 10px;
.el-icon {
cursor: pointer;
}
}
}
.ant-tree {
background: transparent;
color: #fff;
}
.scroll-box {
margin-top: 15px;
height: 64vh;
overflow-y: auto;
&::-webkit-scrollbar {
//
height: 8px;
width: 8px;
}
&::-webkit-scrollbar-thumb {
//
border-radius: 1px;
box-shadow: inset 0 0 1px rgba(255, 255, 255, 0.2);
background: #ffffff;
}
&::-webkit-scrollbar-track {
//
box-shadow: 0;
border-radius: 0;
background: rgba(255, 255, 255, 0.3);
}
.ant-tree-node-content-wrapper {
color: #ffffff;
white-space: nowrap;
&.ant-tree-node-selected {
background: #409eff54 !important;
}
}
.ant-list-empty-text {
padding: 5px;
text-align: left;
}
}
}
</style>
</style>

View File

@ -1,275 +1,315 @@
<template>
<div class="bim-setting-page app-container2">
<div id="bimSettingContainer"></div>
<model-floor-tree ref="modelFloorTree" @change="doChange" :projectMessage="models" v-if="showTree"></model-floor-tree>
<div class="footer-box" v-if="showModels.length>0">
<a-tooltip placement="top" title="主视图">
<div class="footer-btn" @click="doMenu(0)" :class="activeMenu == 0 ? 'is-active' : ''">
<svg-icon icon-class="home" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="第一人称漫游">
<div class="footer-btn" @click="doMenu(1)" :class="activeMenu == 1 ? 'is-active' : ''">
<svg-icon icon-class="roam" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="自定义视点漫游">
<div class="footer-btn" @click="doMenu(2)" :class="activeMenu == 2 ? 'is-active' : ''">
<svg-icon icon-class="view" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="视点管理">
<div class="footer-btn" @click="doMenu(3)" :class="activeMenu == 3 ? 'is-active' : ''">
<svg-icon icon-class="camera" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="构件隐藏">
<div class="footer-btn" @click="doMenu(4)" :class="activeMenu == 4 ? 'is-active' : ''">
<svg-icon icon-class="hide" />
</div>
</a-tooltip>
<div class="bim-setting-page app-container2">
<div id="bimSettingContainer"></div>
<model-floor-tree
ref="modelFloorTree"
@change="doChange"
:projectMessage="models"
v-if="showTree"
></model-floor-tree>
<div class="footer-box" v-if="showModels.length > 0">
<a-tooltip placement="top" title="主视图">
<div
class="footer-btn"
@click="doMenu(0)"
:class="activeMenu == 0 ? 'is-active' : ''"
>
<svg-icon icon-class="home" />
</div>
<div class="bim-setting-tools" v-show="activeMenu>0">
<div class="tools-title">{{param.title }}</div>
<el-icon @click="doToolsClose" style="color:#000; font-size:20px; cursor:pointer;" class="tools-close">
<Close />
</el-icon>
<person-roaming v-if="activeMenu==1" ref="personRoaming" :me="this"></person-roaming>
<custom-viewpoint v-if="activeMenu==2" ref="customViewpoint" :me="this"></custom-viewpoint>
<viewpoint v-if="activeMenu==3" ref="viewpoint" :me="this"></viewpoint>
</a-tooltip>
<a-tooltip placement="top" title="第一人称漫游">
<div
class="footer-btn"
@click="doMenu(1)"
:class="activeMenu == 1 ? 'is-active' : ''"
>
<svg-icon icon-class="roam" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="自定义视点漫游">
<div
class="footer-btn"
@click="doMenu(2)"
:class="activeMenu == 2 ? 'is-active' : ''"
>
<svg-icon icon-class="view" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="视点管理">
<div
class="footer-btn"
@click="doMenu(3)"
:class="activeMenu == 3 ? 'is-active' : ''"
>
<svg-icon icon-class="camera" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="构件隐藏">
<div
class="footer-btn"
@click="doMenu(4)"
:class="activeMenu == 4 ? 'is-active' : ''"
>
<svg-icon icon-class="hide" />
</div>
</a-tooltip>
</div>
<div class="bim-setting-tools" v-show="activeMenu > 0">
<div class="tools-title">
<svg-icon icon-class="roam" v-if="activeMenu == 1" />
<svg-icon icon-class="view" v-if="activeMenu == 2" />
<svg-icon icon-class="camera" v-if="activeMenu == 3" />
<svg-icon icon-class="hide" v-if="activeMenu == 4" />
{{ param.title }}
</div>
<el-icon
@click="doToolsClose"
style="color: #000; font-size: 20px; cursor: pointer"
class="tools-close"
>
<Close />
</el-icon>
<person-roaming
v-if="activeMenu == 1"
ref="personRoaming"
:me="this"
></person-roaming>
<custom-viewpoint
v-if="activeMenu == 2"
ref="customViewpoint"
:me="this"
></custom-viewpoint>
<viewpoint v-if="activeMenu == 3" ref="viewpoint" :me="this"></viewpoint>
</div>
</div>
</template>
<script>
import useUserStore from '@/store/modules/user'
import { listBimModel } from '@/api/bim/bimModel'
import ModelFloorTree from './ModelFloorTree.vue'
import PersonRoaming from './PersonRoaming.vue'
import CustomViewpoint from './CustomViewpoint.vue'
import Viewpoint from './Viewpoint.vue'
import useUserStore from "@/store/modules/user";
import { listBimModel } from "@/api/bim/bimModel";
import ModelFloorTree from "./ModelFloorTree.vue";
import PersonRoaming from "./PersonRoaming.vue";
import CustomViewpoint from "./CustomViewpoint.vue";
import Viewpoint from "./Viewpoint.vue";
export default {
components: {
ModelFloorTree,
PersonRoaming,
CustomViewpoint,
Viewpoint,
components: {
ModelFloorTree,
PersonRoaming,
CustomViewpoint,
Viewpoint,
},
data() {
return {
userStore: {},
isAdmin: false,
projects: [],
currentPrjId: null,
currentComId: null,
subDepts: [],
models: [],
isMobile: false,
showTree: false,
initSuccess: false,
activeMenu: 0,
showModels: [],
param: {},
};
},
beforeUnmount() {
document.body.classList.remove("is-sapi");
},
mounted() {
document.body.classList.add("is-sapi");
this.userStore = useUserStore();
this.isAdmin = this.userStore.isAdmin;
this.currentPrjId = this.userStore.currentPrjId;
this.currentComId = this.userStore.currentComId;
this.initLoadModel();
this.initEngine();
},
methods: {
doChange() {
this.showModels = api.m_model.keys().toArray();
console.log("--change--");
},
data() {
return {
userStore: {},
isAdmin: false,
projects: [],
currentPrjId: null,
currentComId: null,
subDepts: [],
models: [],
isMobile: false,
showTree: false,
initSuccess: false,
activeMenu: 0,
showModels: [],
param: {},
resetScene() {
if (this.$refs.personRoaming) {
this.$refs.personRoaming.isRoaming = false;
}
api.Camera.stopImmersiveRoam();
api.Model.location(api.m_model.keys().toArray()[0]);
api.Plugin.deleteMiniMap();
},
doMenu(n) {
if (n == this.activeMenu) {
if (n == 0) {
this.resetScene();
}
return;
}
this.activeMenu = n;
if (n == 0) {
this.resetScene();
}
if (n == 1) {
this.param.title = "第一人称漫游";
}
if (n == 2) {
this.param.title = "自定义视点漫游";
}
if (n == 3) {
this.param.title = "视点管理";
}
},
beforeUnmount() {
document.body.classList.remove('is-sapi')
NotificationPopup(parameter) {
this.param = parameter;
// const that = this
// that.$notification.open({
// key: 'EngineKey',
// message: parameter.title,
// description: parameter.description,
// class: 'engine-notification ' + (parameter.tips ? parameter.tips : ''),
// duration: null,
// placement: parameter.placement ? parameter.placement : that.isMobile ? 'bottomLeft' : 'topRight',
// style: {
// top: parameter.top ? parameter.top : '50px',
// width: parameter.width ? parameter.width : '360px',
// marginRight: `20px`,
// borderRadius: '0px',
// },
// onClose: this.notifClose,
// })
},
mounted() {
document.body.classList.add('is-sapi')
this.userStore = useUserStore()
this.isAdmin = this.userStore.isAdmin
this.currentPrjId = this.userStore.currentPrjId
this.currentComId = this.userStore.currentComId
this.initLoadModel()
this.initEngine()
doToolsClose() {
this.activeMenu = 0;
this.resetScene();
},
methods: {
doChange() {
this.showModels = api.m_model.keys().toArray()
console.log('--change--')
},
resetScene() {
if (this.$refs.personRoaming) {
this.$refs.personRoaming.isRoaming = false
}
api.Camera.stopImmersiveRoam()
api.Model.location(api.m_model.keys().toArray()[0])
api.Plugin.deleteMiniMap()
},
doMenu(n) {
if (n == this.activeMenu) {
if (n == 0) {
this.resetScene()
}
return
}
this.activeMenu = n
if (n == 0) {
this.resetScene()
}
if (n == 1) {
this.param.title = '第一人称漫游'
}
if (n == 2) {
this.param.title = '自定义视点漫游'
}
if (n == 3) {
this.param.title = '视点管理'
}
},
NotificationPopup(parameter) {
this.param = parameter
// const that = this
// that.$notification.open({
// key: 'EngineKey',
// message: parameter.title,
// description: parameter.description,
// class: 'engine-notification ' + (parameter.tips ? parameter.tips : ''),
// duration: null,
// placement: parameter.placement ? parameter.placement : that.isMobile ? 'bottomLeft' : 'topRight',
// style: {
// top: parameter.top ? parameter.top : '50px',
// width: parameter.width ? parameter.width : '360px',
// marginRight: `20px`,
// borderRadius: '0px',
// },
// onClose: this.notifClose,
// })
},
doToolsClose() {
this.activeMenu = 0
this.resetScene()
},
notifClose() {
this.activeMenu = -1
},
initEngine() {
window.api = new SAPI(
{
serverIP: window.config.serverIP, //ip
port: window.config.port, //HTTP
useHttps: window.config.useHttps, //使Https
container: 'bimSettingContainer', //[]id
secretKey: window.config.secretKey,
openEarth: window.config.openEarth, //[]Gis
bgColor: window.config.bgColor, //[]bim,
tintColor: window.config.tintColor, //[]osgb
sceneTime: window.config.sceneTime, //[]
cadMode: window.config.cadMode, // Cad
},
() => {
this.initSuccess = true
console.log('初始化成功')
let mapOptions = {
imgs: {
//
top: './img/top.png',
bottom: './img/under.png',
east: './img/east.png',
south: './img/south.png',
west: './img/west.png',
north: './img/north.png',
},
offset: {
//
corner: GLENavigationCube.RightTop,
x: 25,
y: 20,
},
cube: {
hoverColor: '#7193dc', //
size: 32, //
hotPointSize: 7, //
cubeTextColor: '#4c4c4ccc', // cube
cubeStrokeColor: '#374769cc', // cube
cubeFillColor: '#374769cc', // cube
},
zoomRatios: 1, //
show: true, //
showAxes: true, // XYZ线
}
api.Plugin.initNavCube(mapOptions)
}
)
},
initLoadModel() {
listBimModel({
pageNum: 1,
pageSize: 10,
comId: this.currentComId,
projectId: this.currentPrjId,
}).then((d) => {
this.models = d.rows || []
if (this.models.length == 0) {
this.$modal.msgError('暂无模型,请先关联模型')
} else {
this.showTree = true
}
})
},
notifClose() {
this.activeMenu = -1;
},
}
initEngine() {
window.api = new SAPI(
{
serverIP: window.config.serverIP, //ip
port: window.config.port, //HTTP
useHttps: window.config.useHttps, //使Https
container: "bimSettingContainer", //[]id
secretKey: window.config.secretKey,
openEarth: window.config.openEarth, //[]Gis
bgColor: window.config.bgColor, //[]bim,
tintColor: window.config.tintColor, //[]osgb
sceneTime: window.config.sceneTime, //[]
cadMode: window.config.cadMode, // Cad
},
() => {
this.initSuccess = true;
console.log("初始化成功");
let mapOptions = {
imgs: {
//
top: "./img/top.png",
bottom: "./img/under.png",
east: "./img/east.png",
south: "./img/south.png",
west: "./img/west.png",
north: "./img/north.png",
},
offset: {
//
corner: GLENavigationCube.RightTop,
x: 25,
y: 20,
},
cube: {
hoverColor: "#7193dc", //
size: 32, //
hotPointSize: 7, //
cubeTextColor: "#4c4c4ccc", // cube
cubeStrokeColor: "#374769cc", // cube
cubeFillColor: "#374769cc", // cube
},
zoomRatios: 1, //
show: true, //
showAxes: true, // XYZ线
};
api.Plugin.initNavCube(mapOptions);
}
);
},
initLoadModel() {
listBimModel({
pageNum: 1,
pageSize: 10,
comId: this.currentComId,
projectId: this.currentPrjId,
}).then((d) => {
this.models = d.rows || [];
if (this.models.length == 0) {
this.$modal.msgError("暂无模型,请先关联模型");
} else {
this.showTree = true;
}
});
},
},
};
</script>
<style lang="scss">
.bim-setting-page {
position: relative;
position: relative;
height: 100%;
#bimSettingContainer {
height: 100%;
#bimSettingContainer {
height: 100%;
}
.footer-box {
position: absolute;
bottom: 10vh;
left: 50%;
margin-left: -75px;
background: #274754;
border-radius: 4px;
.footer-btn {
display: inline-flex;
width: 40px;
height: 40px;
justify-content: center;
align-items: center;
cursor: pointer;
svg {
width: 20px;
height: 20px;
fill: #fff;
}
&:hover {
background: #408edb97;
}
&.is-active {
svg {
fill: rgb(0, 255, 174);
}
}
}
.footer-box {
position: absolute;
bottom: 10vh;
left: 50%;
margin-left: -75px;
background: #274754;
border-radius: 4px;
.footer-btn {
display: inline-flex;
width: 40px;
height: 40px;
justify-content: center;
align-items: center;
cursor: pointer;
svg {
width: 20px;
height: 20px;
fill: #fff;
}
&:hover {
background: #408edb97;
}
&.is-active {
svg {
fill: rgb(0, 255, 174);
}
}
}
.bim-setting-tools {
position: absolute;
top: 80px;
right: 10px;
background: rgba(255, 255, 255, 0.5);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
.tools-title {
padding: 10px;
color: #114c5f;
size: 24px;
}
.tools-close {
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
}
}
.bim-setting-tools {
position: absolute;
top: 80px;
right: 10px;
background: rgba(255, 255, 255, 0.5);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
min-width: 300px;
min-height: 400px;
.tools-title {
padding: 10px;
color: #114c5f;
size: 24px;
}
.tools-close {
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
}
}
}
body.is-sapi {
.app-main {
height: calc(100vh - 84px);
}
}
</style>
</style>

View File

@ -0,0 +1,326 @@
<template>
<div class="bim-sand-table-setting app-container2">
<div id="bimSandTableSetting" :key="elId">
<div
id="bimSandTableSettingContainer"
class="bimSandTableSettingContainer"
></div>
</div>
<div class="footer-box" v-if="models.length > 0">
<a-tooltip placement="top" title="主视图">
<div
class="footer-btn"
@click="doMenu(0)"
:class="activeMenu == 0 ? 'is-active' : ''"
>
<svg-icon icon-class="home" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="视频监控">
<div
class="footer-btn"
@click="doMenu(1)"
:class="activeMenu == 1 ? 'is-active' : ''"
>
<svg-icon icon-class="videoMonitor" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="基坑监控">
<div
class="footer-btn"
@click="doMenu(2)"
:class="activeMenu == 2 ? 'is-active' : ''"
>
<svg-icon icon-class="pitMonitor" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="塔机监控">
<div
class="footer-btn"
@click="doMenu(3)"
:class="activeMenu == 3 ? 'is-active' : ''"
>
<svg-icon icon-class="towerMonitor" />
</div>
</a-tooltip>
<a-tooltip placement="top" title="电箱监控">
<div
class="footer-btn"
@click="doMenu(4)"
:class="activeMenu == 4 ? 'is-active' : ''"
>
<svg-icon icon-class="power" />
</div>
</a-tooltip>
</div>
<div class="bim-setting-tools" v-show="activeMenu > 0">
<div class="tools-title">
<svg-icon icon-class="videoMonitor" v-if="activeMenu == 1" />
<svg-icon icon-class="pitMonitor" v-if="activeMenu == 2" />
<svg-icon icon-class="towerMonitor" v-if="activeMenu == 3" />
<svg-icon icon-class="power" v-if="activeMenu == 4" />
{{ title }}
</div>
<el-icon
@click="doToolsClose"
style="color: #000; font-size: 20px; cursor: pointer"
class="tools-close"
>
<Close />
</el-icon>
<div class="device-list scroll">
<div class="device-item" v-for="(item, index) in devices" :key="index">
<div class="device-name">
<svg-icon icon-class="videoMonitor" v-if="activeMenu == 1" />
<svg-icon icon-class="pitMonitor" v-if="activeMenu == 2" />
<svg-icon icon-class="towerMonitor" v-if="activeMenu == 3" />
<svg-icon icon-class="power" v-if="activeMenu == 4" />
{{ item.name }}
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import useUserStore from "@/store/modules/user";
import { listBimModel } from "@/api/bim/bimModel";
import { emitter } from "@/router/index.js";
import { devicePositionGet } from "@/api/bim/bim.js";
export default {
name: "SandTableSetting",
components: {
// attItem
},
data() {
return {
currentPrjId: null,
currentComId: null,
models: [],
elId: 1,
activeMenu: 0,
title: "",
devices: [],
};
},
created() {
emitter.on("routeChanged", ({ to, from }) => {
if (to.name === "SandTableSetting") {
this.initEngine();
}
//
});
},
beforeUnmount() {
emitter.off("routeChanged");
document.body.classList.remove("is-sapi");
},
mounted() {
this.userStore = useUserStore();
this.currentPrjId = this.userStore.currentPrjId;
this.currentComId = this.userStore.currentComId;
document.body.classList.add("is-sapi");
this.initEngine();
},
methods: {
doToolsClose() {
this.activeMenu = 0;
this.resetScene();
},
resetScene() {
api.Camera.stopImmersiveRoam();
api.Model.location(api.m_model.keys().toArray()[0]);
api.Plugin.deleteMiniMap();
},
doMenu(n) {
if (n == this.activeMenu) {
if (n == 0) {
this.resetScene();
}
return;
}
this.activeMenu = n;
if (n == 1) {
this.title = "视频监控";
} else if (n == 2) {
this.title = "基坑监控";
} else if (n == 3) {
this.title = "塔机监控";
} else if (n == 4) {
this.title = "电箱监控";
}
this.loadPoisionData();
},
loadPoisionData() {
devicePositionGet({ projectId: this.currentPrjId }).then((d) => {
this.devices = (d.data || []).filter(
(item) => item.deviceType == this.activeMenu
);
});
},
initEngine() {
this.elId++;
this.activeMenu = 0;
setTimeout(() => {
this.loadEngine();
}, 10);
},
loadEngine() {
window.sandSettingApi = new SAPI(
{
serverIP: window.config.serverIP, //ip
port: window.config.port, //HTTP
useHttps: window.config.useHttps, //使Https
container: "bimSandTableSettingContainer", //[]id
secretKey: window.config.secretKey,
openEarth: window.config.openEarth, //[]Gis
bgColor: window.config.bgColor, //[]bim,
tintColor: window.config.tintColor, //[]osgb
sceneTime: window.config.sceneTime, //[]
cadMode: window.config.cadMode, // Cad
},
() => {
this.initSuccess = true;
console.log("初始化成功");
setTimeout(() => {
this.initLoadModel();
}, 10);
let mapOptions = {
imgs: {
//
top: "./img/top.png",
bottom: "./img/under.png",
east: "./img/east.png",
south: "./img/south.png",
west: "./img/west.png",
north: "./img/north.png",
},
offset: {
//
corner: GLENavigationCube.RightTop,
x: 25,
y: 20,
},
cube: {
hoverColor: "#7193dc", //
size: 32, //
hotPointSize: 7, //
cubeTextColor: "#4c4c4ccc", // cube
cubeStrokeColor: "#374769cc", // cube
cubeFillColor: "#374769cc", // cube
},
zoomRatios: 1, //
show: true, //
showAxes: true, // XYZ线
};
sandSettingApi.Plugin.initNavCube(mapOptions);
}
);
},
initLoadModel() {
listBimModel({
pageNum: 1,
pageSize: 10,
comId: this.currentComId,
projectId: this.currentPrjId,
}).then((d) => {
this.models = d.rows || [];
if (this.models.length == 0) {
this.$modal.msgError("暂无模型,请先关联模型");
} else {
this.models.forEach((item) => {
this.addModel(item.lightweightName);
});
}
});
},
addModel(modelId, cb) {
let url = `${window.config.modelUrl}/Tools/output/model/${modelId}/root.glt`;
console.log(modelId, url);
sandSettingApi.Model.add(
url,
modelId,
() => {},
() => {
cb && cb();
console.log("加载模型成功");
}
);
},
},
};
</script>
<style lang="scss">
.bim-sand-table-setting {
position: absolute;
height: calc(100% - 0px);
width: 100%;
#bimSandTableSetting {
height: 100%;
#bimSandTableSettingContainer {
height: 100%;
}
}
.footer-box {
position: absolute;
bottom: 6vh;
left: 50%;
margin-left: -75px;
background: #274754;
border-radius: 4px;
.footer-btn {
display: inline-flex;
width: 40px;
height: 40px;
justify-content: center;
align-items: center;
cursor: pointer;
svg {
width: 20px;
height: 20px;
fill: #fff;
}
&:hover {
background: #408edb97;
}
&.is-active {
svg {
fill: rgb(0, 255, 174);
}
}
}
}
.bim-setting-tools {
position: absolute;
top: 80px;
right: 10px;
background: rgba(255, 255, 255, 0.5);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
min-width: 300px;
min-height: 400px;
.tools-title {
padding: 10px;
color: #114c5f;
size: 24px;
}
.tools-close {
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
}
}
}
</style>