增加沙盘设置
parent
4b3bceb065
commit
d21d683289
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -195,4 +195,10 @@ aside {
|
|||
overflow: hidden !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.is-sapi {
|
||||
.app-main {
|
||||
height: calc(100vh - 84px);
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue