Эх сурвалжийг харах

1. 修改数据库数据,制作测试接口

kindring 2 жил өмнө
parent
commit
c91e03398b

+ 176 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AiConfig.java

@@ -0,0 +1,176 @@
+package com.genersoft.iot.vmp.gb28181.bean;
+import io.swagger.v3.oas.annotations.media.Schema;
+/**
+ * ai数据
+ */
+@Schema(description = "合方圆/ai")
+public class AiConfig {
+    @Schema(description = "设备国标编号")
+    private String deviceId;
+    @Schema(description = "配置id")
+    private int configId;
+    @Schema(description = "图像库id")
+    private int libraryId;
+    @Schema(description = "对应的算法")
+    private int arithmetic;
+
+    @Schema(description = "触发类型")
+    private int triggerType;
+
+    @Schema(description = "刷新时间")
+    private int refreshTime;
+
+    @Schema(description = "检测阈值")
+    private float score;
+
+    @Schema(description = "资源数据更新获取地址")
+    private String resourcePath;
+
+    @Schema(description = "多媒体资源上传地址")
+    private String uploadUrl;
+
+    @Schema(description = "回调地址")
+    private String pushUrl;
+
+    public String getConfigName() {
+        return configName;
+    }
+
+    public void setConfigName(String configName) {
+        this.configName = configName;
+    }
+
+    @Schema(description = "ai配置名称")
+    private String configName;
+
+    public String getLibraryName() {
+        return libraryName;
+    }
+
+    public void setLibraryName(String libraryName) {
+        this.libraryName = libraryName;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public int getImgId() {
+        return imgId;
+    }
+
+    public void setImgId(int imgId) {
+        this.imgId = imgId;
+    }
+
+    public String getImageUrl() {
+        return imageUrl;
+    }
+
+    public void setImageUrl(String imageUrl) {
+        this.imageUrl = imageUrl;
+    }
+
+    @Schema(description = "图形库名称")
+    private String libraryName;
+
+    @Schema(description = "图像块版本")
+    private String version;
+
+    @Schema(description = "图像id")
+    private int imgId;
+
+    @Schema(description = "图片的链接")
+    private String imageUrl;
+
+    public int getConfigId() {
+        return configId;
+    }
+
+    public void setConfigId(int configId) {
+        this.configId = configId;
+    }
+
+
+    public int getLibraryId() {
+        return libraryId;
+    }
+
+    public void setLibraryId(int libraryId) {
+        this.libraryId = libraryId;
+    }
+
+
+
+    public int getArithmetic() {
+        return arithmetic;
+    }
+
+    public void setArithmetic(int arithmetic) {
+        this.arithmetic = arithmetic;
+    }
+
+
+    public int getTriggerType() {
+        return triggerType;
+    }
+
+    public void setTriggerType(int triggerType) {
+        this.triggerType = triggerType;
+    }
+
+    public int getRefreshTime() {
+        return refreshTime;
+    }
+
+    public void setRefreshTime(int refreshTime) {
+        this.refreshTime = refreshTime;
+    }
+
+    public float getScore() {
+        return score;
+    }
+
+    public void setScore(float score) {
+        this.score = score;
+    }
+
+    public String getResourcePath() {
+        return resourcePath;
+    }
+
+    public void setResourcePath(String resourcePath) {
+        this.resourcePath = resourcePath;
+    }
+
+    public String getUploadUrl() {
+        return uploadUrl;
+    }
+
+    public void setUploadUrl(String uploadUrl) {
+        this.uploadUrl = uploadUrl;
+    }
+
+    public String getPushUrl() {
+        return pushUrl;
+    }
+
+    public void setPushUrl(String pushUrl) {
+        this.pushUrl = pushUrl;
+    }
+
+
+
+    public String getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(String deviceId) {
+        this.deviceId = deviceId;
+    }
+
+}

+ 3 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java

@@ -49,6 +49,9 @@ public class DeferredResultHolder {
 
 	public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM";
 
+	public static final String CALLBACK_CMD_AI_ALARM = "CALLBACK_CMD_AI_ALARM";
+
+	public static final String CALLBACK_CMD_QUERY_AI = "CALLBACK_CMD_QUERY_AI";
 	public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST";
 
 	private Map<String, Map<String, DeferredResult>> map = new ConcurrentHashMap<>();

+ 3 - 3
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java

@@ -52,10 +52,10 @@ public class SipUtils {
 
     public static UserAgentHeader createUserAgentHeader(SipFactory sipFactory, GitUtil gitUtil) throws PeerUnavailableException, ParseException {
         List<String> agentParam = new ArrayList<>();
-        agentParam.add("Hfy-GB v");
+        agentParam.add("Hfy-GB v1.1");
         if (gitUtil != null && gitUtil.getCommitTime() != null) {
-            agentParam.add(gitUtil.getBuildVersion() + ".");
-            agentParam.add(gitUtil.getCommitTime());
+//            agentParam.add(gitUtil.getBuildVersion() + ".");
+//            agentParam.add(gitUtil.getCommitTime());
         }
         return sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
     }

+ 23 - 2
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java

@@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.storager;
 
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
 import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
@@ -49,6 +48,26 @@ public interface IVideoManagerStorage {
 	 */
 	public Device queryVideoDevice(String deviceId);
 
+	/**
+	 * 获取设备绑定的ai列表
+	 * @param deviceId
+	 * @return
+	 */
+	public List<AiConfig> queryDevAiConfigList(String deviceId);
+
+	/**
+	 * 获取数据库中所有的ai库
+	 * @return
+	 */
+	public List<AiConfig> queryLibraryList();
+
+	/**
+	 * 通过ai库的
+	 * @param libraryId
+	 * @return
+	 */
+	public List<AiConfig> queryItemByLibraryId(int libraryId);
+
 	/**
 	 * 获取某个设备的通道列表
 	 *
@@ -58,7 +77,9 @@ public interface IVideoManagerStorage {
 	 * @return
 	 */
 	public PageInfo queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, Boolean catalogUnderDevice, int page, int count);
-	
+
+
+
 	public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit);
 
 

+ 59 - 0
src/main/java/com/genersoft/iot/vmp/storager/dao/HfyDevAiMapper.java

@@ -0,0 +1,59 @@
+package com.genersoft.iot.vmp.storager.dao;
+import com.genersoft.iot.vmp.gb28181.bean.AiConfig;
+import com.genersoft.iot.vmp.gb28181.bean.Device;
+import org.apache.ibatis.annotations.*;
+import org.springframework.stereotype.Repository;
+import java.util.List;
+
+/**
+ * 用于存储ai信息
+ */
+@Mapper
+@Repository
+public interface HfyDevAiMapper {
+    @Select("select c.* from ai_configs as c " +
+            "left Join devAiConfigs as dc on dc.configId = c.configId " +
+            "where dc.deviceId = #{deviceId}")
+    List<AiConfig> getDevAiConfigByDeviceId(String deviceId);
+
+    @Select("select * from ai_library ")
+    List<AiConfig> getAiLibraryList();
+
+
+    @Insert("insert into ai_library(" +
+            "libraryName," +
+            "version," +
+            "arithmetic" +
+            ") values (" +
+            "#{libraryName}," +
+            "#{version}," +
+            "#{arithmetic}" +
+            ")")
+    int createAiLibrary(AiConfig aiConfig);
+
+    @Update(value = {"<script>" +
+            "update img_library" +
+            "set " +
+            "<if test=\"libraryName\">, libraryName='${name}'</if>" +
+            "<if test=\"version\">, version='${version}'</if>" +
+            "<if test=\"arithmetic\">, libraryName='${arithmetic}'</if>" +
+            "where libraryId = '${libraryId}'" +
+            "</script>" })
+    int updateAiLibrary(AiConfig aiConfig);
+
+    @Select("select * from lib_item where libraryId = #{libraryId}")
+    List<AiConfig> getLibItemByLibraryId(int libraryId);
+
+    @Insert("insert into lib_item(" +
+            "libraryId," +
+            "itemType," +
+            "textValue" +
+            "imageUrl" +
+            ") values (" +
+            "#{libraryName}," +
+            "#{version}," +
+            "#{arithmetic}" +
+            ")")
+    int addImg(AiConfig aiConfig);
+
+}

+ 24 - 1
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java

@@ -59,7 +59,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
 
 	@Autowired
     private DeviceMapper deviceMapper;
-
+	@Autowired
+	private HfyDevAiMapper HfyDevAiMapper;
 	@Autowired
 	private DeviceChannelMapper deviceChannelMapper;
 
@@ -228,6 +229,28 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
 		return deviceMapper.getDeviceByDeviceId(deviceId);
 	}
 
+	/**
+	 * 获取设备的ai列表
+	 * @param deviceId
+	 * @return
+	 */
+	public List<AiConfig> queryDevAiConfigList(String deviceId) {
+		List<AiConfig> all = HfyDevAiMapper.getDevAiConfigByDeviceId(deviceId);
+		return all;
+	}
+
+	/**
+	 * 获取数据库列表
+	 * @return
+	 */
+	public List<AiConfig> queryLibraryList(){
+		return HfyDevAiMapper.getAiLibraryList();
+	}
+
+	public List<AiConfig> queryItemByLibraryId(int libraryId){
+		return HfyDevAiMapper.getLibItemByLibraryId(libraryId);
+	}
+
 	@Override
 	public PageInfo queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, Boolean catalogUnderDevice, int page, int count) {
 		// 获取到所有正在播放的流

+ 32 - 8
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java

@@ -3,10 +3,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.device;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.conf.DynamicTask;
 import com.genersoft.iot.vmp.conf.exception.ControllerException;
-import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
-import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
-import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
+import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
 import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
@@ -25,7 +22,6 @@ import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.apache.commons.compress.utils.IOUtils;
-import org.apache.http.HttpResponse;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -33,12 +29,10 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.util.ObjectUtils;
-import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.context.request.async.DeferredResult;
 
 import javax.servlet.http.HttpServletResponse;
-import javax.sip.DialogState;
 import javax.sip.InvalidArgumentException;
 import javax.sip.SipException;
 import java.io.*;
@@ -88,10 +82,38 @@ public class DeviceQuery {
 	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
 	@GetMapping("/devices/{deviceId}")
 	public Device devices(@PathVariable String deviceId){
-		
 		return storager.queryVideoDevice(deviceId);
 	}
 
+	@Operation(summary = "设备ai查询")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@GetMapping("/devAis/{deviceId}")
+	public List<AiConfig> devAiList(@PathVariable String deviceId){
+		if (logger.isDebugEnabled()) {
+			logger.debug("设备ai数据查询");
+		}
+		return storager.queryDevAiConfigList(deviceId);
+	}
+
+
+	@Operation(summary = "ai数据库查询")
+	@GetMapping("/aiLibrary")
+	public List<AiConfig> aiLibrary(){
+		if (logger.isDebugEnabled()) {
+			logger.debug("设备ai数据查询");
+		}
+		return storager.queryLibraryList();
+	}
+	@Operation(summary = "ai库子项数据查询")
+	@Parameter(name = "libraryId", description = "设备国标编号", required = true)
+	@GetMapping("/aiLibItem/{libraryId}")
+	public List<AiConfig> aiLibItem(@PathVariable int libraryId){
+		if (logger.isDebugEnabled()) {
+			logger.debug("ai库子项数据查询");
+		}
+		return storager.queryItemByLibraryId(libraryId);
+	}
+
 	/**
 	 * 分页查询国标设备
 	 * @param page 当前页
@@ -343,6 +365,8 @@ public class DeviceQuery {
 		return result;
 	}
 
+
+
 	/**
 	 * 设备报警查询请求API接口
 	 * @param deviceId 设备id

+ 4 - 4
src/main/resources/application.yml

@@ -123,11 +123,11 @@ media:
     # [必须修改] zlm服务器的内网IP
     ip: 192.168.1.203
     # [可选] 返回流地址时的ip,置空使用 media.ip
-    # stream-ip: 119.136.145.117
-    stream-ip: 192.168.1.203
+    stream-ip: 113.88.193.113
+    #stream-ip: 192.168.1.203
     # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
-    # sdp-ip: 119.136.145.117
-    sdp-ip: 192.168.1.203
+    sdp-ip: 113.88.193.113
+    #sdp-ip: 192.168.1.203
     # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
     hook-ip:
     # [必须修改] zlm服务器的http.port

+ 1 - 1
web_src/.postcssrc.js

@@ -2,8 +2,8 @@
 
 module.exports = {
   "plugins": {
-    tailwindcss: { config: './tailwind.config.js' },
     "postcss-import": {},
+    tailwindcss: { config: './tailwind.config.js' },
     "postcss-url": {},
     // to edit target browsers: use "browserslist" field in package.json
     "autoprefixer": {},

+ 9 - 6
web_src/build/utils.js

@@ -18,15 +18,18 @@ exports.cssLoaders = function (options) {
   const cssLoader = {
     loader: 'css-loader',
     options: {
-      sourceMap: options.sourceMap
+      sourceMap: options.sourceMap,
+      plugins: [
+        require('tailwindcss')
+      ]
     }
   }
 
   const postcssLoader = {
     loader: 'postcss-loader',
     options: {
-      sourceMap: options.sourceMap
-    }
+      sourceMap: options.sourceMap,
+    },
   }
 
   // generate loader string to be used with extract text plugin
@@ -37,8 +40,8 @@ exports.cssLoaders = function (options) {
       loaders.push({
         loader: loader + '-loader',
         options: Object.assign({}, loaderOptions, {
-          sourceMap: options.sourceMap
-        })
+          sourceMap: options.sourceMap,
+        }),
       })
     }
 
@@ -47,7 +50,7 @@ exports.cssLoaders = function (options) {
     if (options.extract) {
       return ExtractTextPlugin.extract({
         use: loaders,
-        fallback: 'vue-style-loader'
+        fallback: 'vue-style-loader',
       })
     } else {
       return ['vue-style-loader'].concat(loaders)

+ 6 - 2
web_src/build/vue-loader.conf.js

@@ -9,7 +9,7 @@ const sourceMapEnabled = isProduction
 module.exports = {
   loaders: utils.cssLoaders({
     sourceMap: sourceMapEnabled,
-    extract: isProduction
+    extract: isProduction,
   }),
   cssSourceMap: sourceMapEnabled,
   cacheBusting: config.dev.cacheBusting,
@@ -18,5 +18,9 @@ module.exports = {
     source: 'src',
     img: 'src',
     image: 'xlink:href'
-  }
+  },
+
+
+
+
 }

+ 17 - 3
web_src/src/assets/index.css

@@ -1,3 +1,17 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
+.flex{
+  display: flex;
+}
+
+.align-center{
+  align-items: center;
+}
+.justify-center{
+  justify-content: center;
+}
+.xy-center{
+  align-items: center;
+  justify-content: center;
+}
+.space-between{
+  justify-content: space-between;
+}

+ 129 - 3
web_src/src/components/aiConfig.vue

@@ -12,24 +12,130 @@
       </el-tooltip>
     </div>
   </div>
-  <el-container v-loading="isLoading" style="min-height: 82vh" >
+  <el-container v-loading="isLoading" style="min-height: 82vh;flex-direction: column;" >
+    <el-card class="box-card" v-for="item in useAiList" :key="item.arithmetic">
+      <div slot="header" class="card-header flex space-between align-center" >
+        <span>{{ toArithmetic(item.arithmetic).text }}</span>
 
+        <el-button-group>
+          <el-button icon="el-icon-edit" @click="showEditAi(item.id)">调整算法</el-button>
+          <el-button icon="el-icon-delete" type="danger">关闭该算法</el-button>
+        </el-button-group>
+      </div>
+
+      <div class="ai-info">
+
+        <div class="info-item">
+          <div class="label">检验类型:</div>
+          <div class="text">{{toTriggerType(item.triggerType).text}}</div>
+        </div>
+
+        <div class="info-item">
+          <div class="label">触发相似度:</div>
+          <div class="text">{{item.score}}%</div>
+        </div>
+
+        <div class="info-item">
+          <div class="label">使用数据库:</div>
+          <div class="text">{{ toAiData(item.libraryId).libraryName }}</div>
+        </div>
+        <div class="info-item">
+          <div class="label">数据库版本:</div>
+          <div class="text">{{ toAiData(item.libraryId).version }}</div>
+        </div>
+        <div class="info-item">
+          <div class="label">名单数量:</div>
+          <div class="text">{{ toAiData(item.libraryId).total }}</div>
+        </div>
+        <div class="info-item">
+          <div class="label">资源路径:</div>
+          <div class="text">{{ item.resourcePath }}</div>
+        </div>
+        <div class="info-item">
+          <div class="label">多媒体资源上传地址:</div>
+          <div class="text">{{ item.uploadUrl }}</div>
+        </div>
+        <div class="info-item">
+          <div class="label">报警推送回调地址:</div>
+          <div class="text">{{ item.pushUrl }}</div>
+        </div>
+      </div>
+    </el-card>
   </el-container>
 </div>
 </template>
 
 <script>
+import aiMap from "../map/ai"
+import {toNumber} from "../until/typeTool";
+
 export default {
   name: "aiConfig",
   data(){
     return {
-      isLoading: true
+      deviceId: this.$route.params.deviceId,
+      isLoading: false,
+      arithmeticEnum:aiMap.arithmeticEnum,
+      // ai数据库标记列表
+      aiList:[
+        {
+          id: 1,
+          libraryName: "人脸库1",
+          version: "20121",
+          total: 120
+        }
+      ],
+      useAiList: [
+      ],
     }
   },
+  mounted(){
+    this.loadDeviceAi();
+  },
   methods:{
-    showDevice: function () {
+    toArithmetic: aiMap.toArithmetic,
+    toTriggerType: aiMap.toTriggerType,
+    toAiData(num){
+      num=toNumber(num);
+      let key = Object.keys(this.aiList).find(key=>this.aiList[key].id===num);
+      return key?this.aiList[key]:false;
+    },
+    showDevice() {
       this.$router.back();
+      if (this.deviceId === "" ) {
+        this.beforeUrl = "/deviceList"
+      }
+    },
+    loadDeviceAi(){
+      this.isLoading = true;
+      let that = this;
+      this.$axios({
+        method: 'get',
+        url: '/api/device/query/devAis/' + that.deviceId
+      }).then((res) => {
+        // console.log("获取ai数据结果:" + JSON.stringify(res));
+        this.isLoading = false;
+        // console.log(res);
+        let data = res.data;
+        if(data.code === 0 ){
+          that.useAiList = data.data;
+        }else{
+          console.log(res);
+          console.error("未知的返回结果!")
+        }
+      }).catch((e) => {
+        console.error(e)
+        that.$message({
+          showClose: true,
+          message: e,
+          type: 'error'
+        });
+      });
+    },
+    showEditAi(id){
+      this.$router.push(`/devEditAi/${id}`);
     },
+
   }
 
 }
@@ -44,4 +150,24 @@ export default {
   justify-content: space-between;
   align-items: center;
 }
+.box-card{
+  margin-top: 5px;
+}
+.ai-info{
+  width: 100%;
+  min-height: 60px;
+  height: auto;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-around;
+}
+.ai-info .info-item{
+  height: 35px;
+  display: flex;
+  padding: 0 10px;
+  align-items: center;
+}
+.ai-info .info-item .text{
+  margin-left: 5px;
+}
 </style>

+ 63 - 0
web_src/src/components/devAiEdit.vue

@@ -0,0 +1,63 @@
+<template>
+  <div id="devAiEdit w-full" style="width:100%">
+    <div class="page-header">
+      <div class="page-title">
+        <el-button icon="el-icon-back" size="mini" style="font-size: 20px; color: #000;" type="text" @click="back" ></el-button>
+        <el-divider direction="vertical"></el-divider>
+        设备ai参数设置
+      </div>
+
+      <div class="page-header-btn">
+
+      </div>
+    </div>
+
+    <el-container v-loading="isLoading" style="min-height: 82vh;flex-direction: column;" >
+
+    </el-container>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "devAiEdit",
+  data(){
+    return {
+      //
+      aiId: this.$route.params.aiId,
+      isLoading: false,
+    }
+  },
+  mounted() {
+    this.loadAiData();
+  },
+  methods:{
+    back(){
+      this.$router.back();
+      if (this.deviceId === "" ) {
+        this.beforeUrl = "/deviceList"
+      }
+    },
+    loadAiData(){
+      let that = this;
+      this.$axios({
+        method: 'post',
+        url: '/api/device/ai/edit/' + that.aiId
+      }).then((res) => {
+        console.log("获取ai数据结果:" + JSON.stringify(res));
+      }).catch((e) => {
+        console.error(e)
+        that.$message({
+          showClose: true,
+          message: e,
+          type: 'error'
+        });
+      });
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 1 - 0
web_src/src/main.js

@@ -3,6 +3,7 @@ import App from './App.vue';
 Vue.config.productionTip = false;
 import ElementUI from 'element-ui';
 import 'element-ui/lib/theme-chalk/index.css';
+
 import "./assets/index.css";
 import router from './router/index.js';
 import axios from 'axios';

+ 78 - 0
web_src/src/map/ai.js

@@ -0,0 +1,78 @@
+import {toNumber} from "../until/typeTool";
+import {getMapVal} from "../until/mapTools"
+const arithmeticEnum = {
+  face:{
+    val: 1,
+    text: '人脸识别',
+
+  },
+  fire:{
+    val: 2,
+    text: '火情识别'
+  },
+  carPlate:{
+    val: 3,
+    text: '车牌识别'
+  },
+}
+
+const triggerTypeEnum = {
+  unlimited:{
+    val: 1,
+    text: '无限制',
+  },
+  whiteList:{
+    val: 2,
+    text: '白名单'
+  },
+  blackList:{
+    val: 3,
+    text: 'b黑名单'
+  },
+}
+
+/**
+ * 触发类型
+ * @type {{unlimited: number, blackList: number, whiteList: number}}
+ */
+const triggerTypes = {
+  unlimited:triggerTypeEnum.unlimited.val,
+  whiteList:triggerTypeEnum.whiteList.val,
+  blackList:triggerTypeEnum.blackList.val,
+}
+const aiTypes = {
+  face:arithmeticEnum.face.val,
+  fire:arithmeticEnum.fire.val,
+  carPlate:arithmeticEnum.carPlate.val,
+}
+  /**
+ * 通过数字查找对应的值
+ * @param num
+ * @returns {*|boolean}
+ */
+function toArithmetic(num){
+  num=toNumber(num);
+  let arithmetic = Object.keys(arithmeticEnum).find(key=>arithmeticEnum[key].val===num);
+  return arithmetic?arithmeticEnum[arithmetic]:false;
+}
+
+/**
+ * 通过数字查找对应的值
+ * @param num
+ * @returns {*|boolean}
+ */
+function toTriggerType(num){
+  num=toNumber(num);
+  let key = Object.keys(triggerTypeEnum).find(key=>triggerTypeEnum[key].val===num);
+  return key?triggerTypeEnum[key]:false;
+}
+
+
+export default {
+  arithmeticEnum,
+  toArithmetic,
+  aiTypes,
+  triggerTypeEnum,
+  toTriggerType,
+  triggerTypes
+}

+ 6 - 1
web_src/src/router/index.js

@@ -19,7 +19,7 @@ import live from '../components/live.vue'
 import deviceTree from '../components/common/DeviceTree.vue'
 import userManager from '../components/UserManager.vue'
 import aiConfig from "../components/aiConfig";
-
+import devAiEdit from "../components/devAiEdit";
 
 import wasmPlayer from '../components/common/jessibuca.vue'
 import rtcPlayer from '../components/dialog/rtcPlayer.vue'
@@ -71,6 +71,11 @@ export default new VueRouter({
           name: 'aiConfig',
           component: aiConfig,
         },
+        {
+          path: '/devEditAi/:aiId',
+          name: 'devAiEdit',
+          component: devAiEdit,
+        },
         {
           path: '/parentPlatformList/:count/:page',
           name: 'parentPlatformList',

+ 10 - 0
web_src/src/until/mapTools.js

@@ -0,0 +1,10 @@
+export function getMapVal(rawObj){
+  return Object.keys(rawObj).reduce((ac,key)=>{
+    ac[key] = rawObj[key].val
+    return ac;
+  },{})
+}
+
+export default {
+  getMapVal
+}

+ 59 - 0
web_src/src/until/typeTool.js

@@ -0,0 +1,59 @@
+let matchNumberStr = ['0',]
+// 部分关键字转换为boolean值
+let falseField = ['false','False','FALSE','null','Null','NULL','undefined','Undefined'];
+let trueField = ['true','True','TRUE'];
+// 类型转换
+function toString(v){
+    // 情况1 非对象,直接调用内部值
+    if(isNumber(v)) {
+        return v + ''
+    }
+    return v + '';
+
+}
+
+// 转换为number类型,先用toBoolean转换为布尔类型
+function toNumber(v){
+    if(isString(v)){
+        if(falseField.includes(v)){
+            v = toBoolean(v)
+        }else if (trueField.includes(v)){
+            v = toBoolean(v)
+        }
+    }
+    return Number(v)
+}
+
+// 考虑字段类型
+function toBoolean(v){
+    // 字符串类型
+    if (isString(v)){
+        if(falseField.includes(v)){
+            return false
+        }else if (trueField.includes(v)){
+            return true
+        }else{
+            Boolean(v)
+        }
+    }
+}
+
+function isArray(v){
+    return v instanceof Array
+}
+function isString(v){
+    return v instanceof String || typeof v === 'string'
+}
+function isNumber(v){
+    return v instanceof Number
+}
+function isObject(v){
+    return v instanceof Object
+}
+
+
+module.exports = {
+    toNumber,
+    toString,
+    toBoolean
+}

+ 6 - 1
web_src/tailwind.config.js

@@ -2,7 +2,12 @@
 module.exports = {
   content: [],
   presets: [],
-  purge: ['src/*.html','src/*.vue'],
+  purge: [
+    ...process.env.NODE_ENV === 'production'
+      // 只在production环境使用,节省dev环境时间
+      ? ['./view/**/*.html', './view/**/*.vue', './view/**/*.jsx']
+      : [],
+  ],
   darkMode: 'media', // or 'class'
   theme: {
     screens: {

+ 37 - 1
参考文档/数据库扩展.md

@@ -1,3 +1,39 @@
 # ai配置数据库扩展
 > 需要知道设备当前的订阅信息
-> 以及使用的图像库
+> 以及使用的图像库
+> 
+## 图像库 ai_library
+| 字段    | 类型 | 可选值 | 备注  |
+|-------| -- | --- |-----|
+| libraryId | int | pk | 图像库id  |
+| libraryName | string | "" | 图像库名称  |
+| version | string | "" | 图像库 版本uuid |
+| arithmetic | int | 1-3 | 适用的算法 |
+| total | int | n | 图像数量 |
+
+### 图像 lib_item
+| 字段    | 类型 | 可选值 | 备注  |
+|-------| -- | --- |-----|
+| libId | int | pk | 项目id |
+| libraryId | int | tk | 图像库id  |
+| itemType | int | 1,2 | 数据类型,图片,文本 |
+| imageUrl | string | url | 图片的链接 |
+| textValue | string | '' | 用于匹配的值 |
+## ai配置 aiConfigs
+| 字段    | 类型 | 可选值 | 备注  |
+|-------| -- | --- |-----|
+| configId | int | pk | 配置id |
+| libraryId | int | tk | 图形库id |
+| arithmetic | int | 1-3 | 启用的算法.人脸,火情,车牌, |
+| triggerType | int | 1-3 | 触发类型 无限制,白名单,黑名单 |
+| refreshTime | int | 0-n | 刷新时间 单位秒 |
+| score | float | 0.0-100.0 | 检测阈值 |
+| resourcePath | string | url | 资源数据更新获取地址 |
+| uploadUrl | string | url | 多媒体资源上传地址 |
+| pushUrl | string | url | 回调地址 | 
+
+### 国标设备配置 devAiConfigs
+| 字段    | 类型 | 可选值 | 备注  |
+|-------| -- | --- |-----|
+| deviceId | int | tk | 设备id |
+| configId | int | tk | 配置id |