diff --git a/yanzhu-modules/yanzhu-manage/pom.xml b/yanzhu-modules/yanzhu-manage/pom.xml
index d65b984c..0b90c692 100644
--- a/yanzhu-modules/yanzhu-manage/pom.xml
+++ b/yanzhu-modules/yanzhu-manage/pom.xml
@@ -179,6 +179,17 @@
sqlite-jdbc
3.41.2.2
+
+
+ net.hasor
+ hasor-spring
+ 4.2.5
+
+
+ net.hasor
+ hasor-dataway
+ 4.2.5
+
diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/YanZhuManageApplication.java b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/YanZhuManageApplication.java
index 75b7ea92..d5419ec1 100644
--- a/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/YanZhuManageApplication.java
+++ b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/YanZhuManageApplication.java
@@ -3,6 +3,8 @@ package com.yanzhu.manage;
import com.yanzhu.common.security.annotation.EnableCustomConfig;
import com.yanzhu.common.security.annotation.EnableRyFeignClients;
import com.yanzhu.common.swagger.annotation.EnableCustomSwagger2;
+import net.hasor.spring.boot.EnableHasor;
+import net.hasor.spring.boot.EnableHasorWeb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -15,6 +17,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication
+@EnableHasor()
+@EnableHasorWeb()
public class YanZhuManageApplication
{
public static void main(String[] args)
diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/hasor/HasorModule.java b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/hasor/HasorModule.java
new file mode 100644
index 00000000..48b35011
--- /dev/null
+++ b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/hasor/HasorModule.java
@@ -0,0 +1,64 @@
+package com.yanzhu.manage.hasor;
+
+import net.hasor.core.ApiBinder;
+import net.hasor.core.DimModule;
+import net.hasor.dataql.DataQL;
+import net.hasor.dataql.compiler.qil.QIL;
+import net.hasor.dataway.DatawayApi;
+import net.hasor.dataway.authorization.PermissionType;
+import net.hasor.dataway.dal.FieldDef;
+import net.hasor.dataway.service.InterfaceApiFilter;
+import net.hasor.dataway.spi.ApiInfo;
+import net.hasor.dataway.spi.AuthorizationChainSpi;
+import net.hasor.dataway.spi.CompilerSpiListener;
+import net.hasor.dataway.spi.PreExecuteChainSpi;
+import net.hasor.db.JdbcModule;
+import net.hasor.db.Level;
+import net.hasor.spring.SpringModule;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.sql.DataSource;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.Set;
+
+@DimModule
+@Component
+public class HasorModule implements SpringModule {
+ @Autowired
+ private DataSource dataSource = null;
+
+ public void loadModule(ApiBinder apiBinder) throws Throwable {
+ // .DataSource form Spring boot into Hasor
+ apiBinder.installModule(new JdbcModule(Level.Full, this.dataSource));
+
+ InterfaceApiFilter f;
+ apiBinder.bindSpiListener(PreExecuteChainSpi.class, (apiInfo, future) -> {
+ try{
+ Method method = apiInfo.getClass().getMethod("getObj");
+ Map obj=(Map)method.invoke(apiInfo);
+ Object a=obj;
+ }catch (Exception ex){
+
+ }
+ //String apiPath = apiInfo.getApiPath();
+// String apiMethod = apiInfo.getMethod()
+// if (...) {
+// // (方式1)通过 future 设置异常信息
+// future.failed(new StatusMessageException(401, "not power"));
+// // (方式2)或者直接 throw 一个异常
+// throw new StatusMessageException(401, "not power");
+// }
+ });
+ apiBinder.bindSpiListener(CompilerSpiListener.class, new CompilerSpiListener() {
+ @Override
+ public QIL compiler(ApiInfo apiInfo, String query, DataQL dataQL) throws IOException {
+ query = "hint FRAGMENT_SQL_COLUMN_CASE=\"hump\"\n hint FRAGMENT_SQL_QUERY_BY_PAGE_NUMBER_OFFSET = 1 \n" + query;
+ return CompilerSpiListener.super.compiler(apiInfo, query, dataQL);
+ }
+ });
+
+ }
+}
diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/net/hasor/dataql/domain/DomainHelper.java b/yanzhu-modules/yanzhu-manage/src/main/java/net/hasor/dataql/domain/DomainHelper.java
new file mode 100644
index 00000000..820e6b26
--- /dev/null
+++ b/yanzhu-modules/yanzhu-manage/src/main/java/net/hasor/dataql/domain/DomainHelper.java
@@ -0,0 +1,118 @@
+package net.hasor.dataql.domain;
+import net.hasor.dataql.Udf;
+import net.hasor.dataql.runtime.operator.OperatorUtils;
+import net.hasor.utils.ArrayUtils;
+import net.hasor.utils.ref.BeanMap;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.*;
+
+public class DomainHelper {
+ public static ValueModel nullDomain() {
+ return ValueModel.NULL;
+ }
+
+ public static ListModel newList() {
+ return new ListModel();
+ }
+
+ public static ObjectModel newObject() {
+ return new ObjectModel();
+ }
+
+ public static DataModel convertTo(Object object) {
+ if (object instanceof DataModel) {
+ // 已经是 DataModel
+ return (DataModel) object;
+ } else if (object == null) {
+ // 基础类型:空
+ return ValueModel.NULL;
+ } else if (OperatorUtils.isBoolean(object)) {
+ // 基础类型:boolean
+ if ((boolean) object) {
+ return ValueModel.TRUE;
+ } else {
+ return ValueModel.FALSE;
+ }
+ } else if (object instanceof CharSequence) {
+ // 基础类型:字符串
+ return new ValueModel(String.valueOf(object));
+ } else if (OperatorUtils.isNumber(object)) {
+ // 基础类型:数字
+ return new ValueModel(object);
+ } else if (object instanceof Date) {
+ // 外部类型:时间 -> Long
+ return new ValueModel(((Date) object).getTime());
+ } else if (object instanceof UUID) {
+ // 外部类型:UUID -> String
+ return new ValueModel(((UUID) object).toString());
+ } else if (object.getClass().isEnum()) {
+ // 外部类型:枚举 -> ValueModel(字符串)
+ return new ValueModel(((Enum>) object).name());
+ } else if (object instanceof Map) {
+ // 外部类型:Map -> ObjectModel
+ Map mapData = (Map) object;
+ Set entrySet = mapData.entrySet();
+ ObjectModel objectModel = new ObjectModel();
+ for (Object entry : entrySet) {
+ if (entry instanceof Map.Entry) {
+ Object key = ((Map.Entry) entry).getKey();
+ Object val = ((Map.Entry) entry).getValue();
+ objectModel.put(key.toString(), convertTo(val));
+ }
+ }
+ return objectModel;
+ } else if (object.getClass().isArray()) {
+ // 外部类型:数组 -> ListModel
+ Class> componentType = object.getClass().getComponentType();
+ Object[] objectArrays = null;
+ if (componentType.isPrimitive()) {
+ /** */if (Boolean.TYPE == componentType) {
+ objectArrays = ArrayUtils.toObject((boolean[]) object);
+ } else if (Byte.TYPE == componentType) {
+ objectArrays = ArrayUtils.toObject((byte[]) object);
+ } else if (Short.TYPE == componentType) {
+ objectArrays = ArrayUtils.toObject((short[]) object);
+ } else if (Integer.TYPE == componentType) {
+ objectArrays = ArrayUtils.toObject((int[]) object);
+ } else if (Long.TYPE == componentType) {
+ objectArrays = ArrayUtils.toObject((long[]) object);
+ } else if (Character.TYPE == componentType) {
+ objectArrays = ArrayUtils.toObject((char[]) object);
+ } else if (Float.TYPE == componentType) {
+ objectArrays = ArrayUtils.toObject((float[]) object);
+ } else if (Double.TYPE == componentType) {
+ objectArrays = ArrayUtils.toObject((double[]) object);
+ } else {
+ objectArrays = (Object[]) object;
+ }
+ } else {
+ objectArrays = (Object[]) object;
+ }
+ return new ListModel(Arrays.asList(objectArrays));
+ } else if (object instanceof Collection) {
+ // 外部类型:集合 -> ListModel
+ return new ListModel((Collection>) object);
+ } else if (object instanceof Udf) {
+ // 外部类型:UDF -> CallModel
+ return new UdfModel((Udf) object);
+ } else if (object instanceof LocalDateTime) {
+ LocalDateTime localDateTime=(LocalDateTime)object;
+ Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+ return new ValueModel((date).getTime());
+ } else {
+ // 外部类型:Bean -> ObjectModel
+ BeanMap beanMap = new BeanMap(object);
+ ObjectModel objectModel = new ObjectModel();
+ for (String entryKey : beanMap.keySet()) {
+ if ("class".equals(entryKey)) {
+ //objectModel.put(entryKey, convertTo(beanMap.getBean().getClass().getName()));
+ } else {
+ objectModel.put(entryKey, convertTo(beanMap.get(entryKey)));
+ }
+ }
+ return objectModel;
+ }
+ }
+}
\ No newline at end of file
diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/net/hasor/dataway/service/InterfaceApiFilter.java b/yanzhu-modules/yanzhu-manage/src/main/java/net/hasor/dataway/service/InterfaceApiFilter.java
new file mode 100644
index 00000000..e4afa5b5
--- /dev/null
+++ b/yanzhu-modules/yanzhu-manage/src/main/java/net/hasor/dataway/service/InterfaceApiFilter.java
@@ -0,0 +1,149 @@
+package net.hasor.dataway.service;
+import com.alibaba.fastjson.JSON;
+import net.hasor.core.Inject;
+import net.hasor.core.spi.SpiTrigger;
+import net.hasor.dataway.DatawayApi;
+import net.hasor.dataway.config.DatawayUtils;
+import net.hasor.dataway.config.LoggerUtils;
+import net.hasor.dataway.dal.ApiDataAccessLayer;
+import net.hasor.dataway.dal.ApiStatusEnum;
+import net.hasor.dataway.dal.EntityDef;
+import net.hasor.dataway.dal.FieldDef;
+import net.hasor.dataway.spi.ApiInfo;
+import net.hasor.dataway.spi.CallSource;
+import net.hasor.utils.StringUtils;
+import net.hasor.web.Invoker;
+import net.hasor.web.InvokerChain;
+import net.hasor.web.InvokerConfig;
+import net.hasor.web.InvokerFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 负责处理 API 的执行
+ * @author 赵永春 (zyc@hasor.net)
+ * @version : 2020-03-20
+ */
+public class InterfaceApiFilter implements InvokerFilter {
+ protected static Logger logger = LoggerFactory.getLogger(InterfaceApiFilter.class);
+ @Inject
+ private ApiCallService callService;
+ @Inject
+ private SpiTrigger spiTrigger;
+ @Inject
+ private ApiDataAccessLayer dataAccessLayer;
+ @Inject
+ private CrossDomainService crossDomainService;
+ private final String apiBaseUri;
+ private final String adminBaseUri;
+
+ public InterfaceApiFilter(String apiBaseUri, String adminBaseUri) {
+ this.apiBaseUri = apiBaseUri;
+ this.adminBaseUri = adminBaseUri;
+ }
+
+ @Override
+ public void init(InvokerConfig config) {
+ config.getAppContext().justInject(this);
+ }
+
+ @Override
+ public Object doInvoke(Invoker invoker, InvokerChain chain) throws Throwable {
+ HttpServletRequest httpRequest = invoker.getHttpRequest();
+ String requestURI = invoker.getRequestPath();
+ String httpMethod = httpRequest.getMethod().toUpperCase().trim();
+ if (!requestURI.startsWith(this.apiBaseUri)) {
+ return chain.doNext(invoker);
+ }
+ //
+ // .Skip ui url
+ if (StringUtils.isNotBlank(this.adminBaseUri)) {
+ if (requestURI.startsWith(this.adminBaseUri)) {
+ return chain.doNext(invoker);
+ }
+ }
+ //
+ DatawayUtils.resetLocalTime();
+ String mimeType = invoker.getMimeType("json");
+ //
+ // .查询接口数据
+ ApiInfo apiInfo = new ApiInfo();
+ apiInfo.setCallSource(CallSource.External);
+ String script = null;
+ try {
+ Map object = this.dataAccessLayer.getObjectBy(EntityDef.RELEASE, FieldDef.PATH, requestURI);
+ if (object == null) {
+ throw new IllegalStateException("API is not published.");
+ }
+ ApiStatusEnum anEnum = ApiStatusEnum.typeOf(object.get(FieldDef.STATUS));
+ if (anEnum != ApiStatusEnum.Published) {
+ throw new IllegalStateException("API is not published.");
+ }
+ String apiMethod = object.get(FieldDef.METHOD);
+ if (!StringUtils.equalsIgnoreCase(httpMethod, apiMethod)) {
+ throw new IllegalStateException("request method are not allowed.");
+ }
+ //
+ apiInfo.setReleaseID(object.get(FieldDef.ID));
+ apiInfo.setApiID(object.get(FieldDef.API_ID));
+ apiInfo.setMethod(object.get(FieldDef.METHOD));
+ apiInfo.setApiPath(object.get(FieldDef.PATH));
+ apiInfo.setOptionMap(JSON.parseObject(object.get(FieldDef.OPTION)));
+ setApiInfoObj(apiInfo,object);
+ script = object.get(FieldDef.SCRIPT);
+ } catch (Exception e) {
+ Object result = DatawayUtils.exceptionToResult(e).getResult();
+ LoggerUtils loggerUtils = LoggerUtils.create() //
+ .addLog("httpMethod", httpMethod) //
+ .addLog("apiPath", requestURI) //
+ .addLog("result", result) //
+ .logException(e);
+ logger.error("requestFailed - " + loggerUtils.toJson(), e);
+ return DatawayUtils.responseData(this.spiTrigger, apiInfo, mimeType, invoker, result);
+ }
+ //
+ // .准备参数
+ Map jsonParam;
+ if ("GET".equalsIgnoreCase(httpMethod)) {
+ jsonParam = new HashMap<>();
+ Enumeration parameterNames = httpRequest.getParameterNames();
+ while (parameterNames.hasMoreElements()) {
+ String paramName = parameterNames.nextElement();
+ jsonParam.put(paramName + "Arrays", httpRequest.getParameterValues(paramName));
+ jsonParam.put(paramName, httpRequest.getParameter(paramName));
+ }
+ } else {
+ String jsonBody = invoker.getJsonBodyString();
+ if (StringUtils.isNotBlank(jsonBody)) {
+ jsonParam = JSON.parseObject(jsonBody);
+ } else {
+ jsonParam = new HashMap<>();
+ }
+ }
+ apiInfo.setParameterMap(jsonParam);
+ //
+ // .配置跨域
+ this.crossDomainService.configureCross( apiInfo, invoker);
+ //
+ // .执行调用
+ String finalScript = script;
+ Object objectMap = this.callService.doCallWithoutError(apiInfo, param -> finalScript);
+ return DatawayUtils.responseData(this.spiTrigger, apiInfo, mimeType, invoker, objectMap);
+ }
+
+ private void setApiInfoObj(ApiInfo apiInfo, Map object) {
+ try{
+ Method method=apiInfo.getClass().getMethod("setObj",Map.class);
+ method.invoke(apiInfo,object);
+ }catch (Exception ex){
+ ex.printStackTrace();;
+ }
+ }
+}
\ No newline at end of file
diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/net/hasor/dataway/spi/ApiInfo.java b/yanzhu-modules/yanzhu-manage/src/main/java/net/hasor/dataway/spi/ApiInfo.java
new file mode 100644
index 00000000..47b340f1
--- /dev/null
+++ b/yanzhu-modules/yanzhu-manage/src/main/java/net/hasor/dataway/spi/ApiInfo.java
@@ -0,0 +1,102 @@
+package net.hasor.dataway.spi;
+
+import net.hasor.dataql.Hints;
+import net.hasor.dataway.DatawayApi;
+import net.hasor.dataway.dal.FieldDef;
+
+import java.util.Map;
+
+public class ApiInfo implements DatawayApi{
+
+ private CallSource callSource;
+ private String apiID;
+ private String releaseID;
+ private String method;
+ private String apiPath;
+ private Map parameterMap;
+ private Map optionMap;
+ private Hints prepareHint;
+
+ public Map getObj() {
+ return obj;
+ }
+
+ public void setObj(Map obj) {
+ this.obj = obj;
+ }
+
+ private Map obj;
+
+ public ApiInfo() {
+ }
+
+ /** @deprecated */
+ @Deprecated
+ public boolean isPerform() {
+ return CallSource.InterfaceUI == this.callSource;
+ }
+
+ public CallSource getCallSource() {
+ return this.callSource;
+ }
+
+ public void setCallSource(CallSource callSource) {
+ this.callSource = callSource;
+ }
+
+ public String getApiID() {
+ return this.apiID;
+ }
+
+ public void setApiID(String apiID) {
+ this.apiID = apiID;
+ }
+
+ public String getReleaseID() {
+ return this.releaseID;
+ }
+
+ public void setReleaseID(String releaseID) {
+ this.releaseID = releaseID;
+ }
+
+ public String getMethod() {
+ return this.method;
+ }
+
+ public void setMethod(String method) {
+ this.method = method;
+ }
+
+ public String getApiPath() {
+ return this.apiPath;
+ }
+
+ public void setApiPath(String apiPath) {
+ this.apiPath = apiPath;
+ }
+
+ public Map getParameterMap() {
+ return this.parameterMap;
+ }
+
+ public void setParameterMap(Map parameterMap) {
+ this.parameterMap = parameterMap;
+ }
+
+ public Map getOptionMap() {
+ return this.optionMap;
+ }
+
+ public void setOptionMap(Map optionMap) {
+ this.optionMap = optionMap;
+ }
+
+ public Hints getPrepareHint() {
+ return this.prepareHint;
+ }
+
+ public void setPrepareHint(Hints prepareHint) {
+ this.prepareHint = prepareHint;
+ }
+ }
diff --git a/yanzhu-modules/yanzhu-manage/src/main/resources/bootstrap.yml b/yanzhu-modules/yanzhu-manage/src/main/resources/bootstrap.yml
index b02b3f0d..4393a936 100644
--- a/yanzhu-modules/yanzhu-manage/src/main/resources/bootstrap.yml
+++ b/yanzhu-modules/yanzhu-manage/src/main/resources/bootstrap.yml
@@ -1,6 +1,11 @@
# Tomcat
server:
port: 9208
+ servlet:
+ encoding:
+ enabled: true
+ charset: UTF-8
+ force: true
# Spring
spring:
@@ -15,8 +20,10 @@ spring:
discovery:
# 服务注册地址
server-addr: @discovery.server-addr@
+ # 工作空间配置
+ namespace: a113aa27-4d61-46e0-81d6-9cede0457f0d
# 服务分组
- group: JiangYuQi
+ #group: lijun
config:
# 配置中心地址
server-addr: @discovery.server-addr@
@@ -31,4 +38,15 @@ logging:
com.ycx.manage.mapper: DEBUG
bim:
- dataPath: '/Users/mac/code/bimdata/'
\ No newline at end of file
+ dataPath: '/Users/mac/code/bimdata/'
+
+#http://localhost:9208/interface-ui/
+# 启用 Dataway 功能(默认不启用)
+HASOR_DATAQL_DATAWAY: true
+# 开启 ui 管理功能(注意生产环境必须要设置为 false,否则会造成严重的生产安全事故)
+HASOR_DATAQL_DATAWAY_ADMIN: true
+
+# (可选)API工作路径
+HASOR_DATAQL_DATAWAY_API_URL: /api/
+# (可选)ui 的工作路径,只有开启 ui 管理功能后才有效
+HASOR_DATAQL_DATAWAY_UI_URL: /interface-ui/
\ No newline at end of file
diff --git a/yanzhu-ui-vue3/src/views/manage/attendance_cfg/index.vue b/yanzhu-ui-vue3/src/views/manage/attendance_cfg/index.vue
index 2b7caffe..224d6fd6 100644
--- a/yanzhu-ui-vue3/src/views/manage/attendance_cfg/index.vue
+++ b/yanzhu-ui-vue3/src/views/manage/attendance_cfg/index.vue
@@ -1,40 +1,36 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 搜索
- 重置
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
-
-
- 新增
-
-
-
-
+ -->
+
+
-
-
-
-
-
-
- {{scope.row.vendorsName }}
-
-
-
-
-
-
-
-
-
-
-
-
- {{ parseTime(scope.row.createTime) }}
+
+
+
+
+
+
+ {{scope.row.vendorsName }}
+
+
+
+ {{ scope.row.info.projectGuid||scope.row.info.appProjectId}}
+
+
+ {{ scope.row.info.AppKey||scope.row.info.appId}}
+
+
+ {{ scope.row.info.AppSecret||scope.row.info.secret}}
+
+
+
+
+
+
+
+
+ {{ parseTime(scope.row.createTime) }}
+
+
+
+
+
+ 设备列表
+ 修改
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
- 设备列表
- 修改
- 删除
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+