Quellcode durchsuchen

Merge branch 'master' of http://116.63.33.55/git/read_opc

Zt vor 2 Jahren
Ursprung
Commit
5e86c82c20

+ 16 - 0
chuanyi_client2/src/api/datasource.js

@@ -90,6 +90,22 @@ export function delDataSourceById(id) {
     })
 }
 
+/***
+ * 获取驱动列表
+ * @param data
+ * @returns {AxiosPromise}
+ */
+export function getDriverList(data) {
+    return request({
+        url: '/dataSource/getDaAllDriver',
+        headers: {
+            isToken: true
+        },
+        method: 'post',
+        data
+    })
+}
+
 /**
  * 查询组配置
  * @returns {AxiosPromise}

+ 161 - 15
chuanyi_client2/src/components/HeaderMain/index.vue

@@ -133,16 +133,16 @@
                 <el-select v-model="groupRateForm.readMode" placeholder="请选择读取模式" style="width: 100%;" @change="readModeChange">
                   <el-option
                       v-for="dict in readModeList"
-                      :key="dict.dictValue"
-                      :label="dict.dictKey"
-                      :value="dict.dictValue"
+                      :key="dict.value"
+                      :label="dict.key"
+                      :value="dict.value"
                   ></el-option>
                 </el-select>
               </el-form-item>
               <el-form-item label="模式值" prop="modeValue">
                 <el-input v-model="groupRateForm.modeValue" placeholder="请输入模式值"
                           oninput="value=value.replace(/[^0-9.]/g,'')">
-                  <template slot="append">秒</template>
+                  <template slot="append" v-if="groupRateForm.readMode == '2'">秒</template>
                 </el-input>
               </el-form-item>
             </el-form>
@@ -177,7 +177,7 @@
           </el-select>
         </el-form-item>
       </el-form>
-      <div style="display: flex; height: 60vh; overflow: auto;">
+      <div v-if="itemDataStep == 1" style="display: flex; height: 60vh; overflow: auto;">
         <!-- 数据项 -->
         <div class="cy-transform-data">
           <el-divider content-position="left">数据项</el-divider>
@@ -236,18 +236,67 @@
           </div>
         </div>
       </div>
+      <div v-if="itemDataStep == 2">
+        <el-table
+            :data="chooseItemDataList"
+            :key="bomCheckKey"
+            style="width: 100%">
+          <el-table-column
+              label="数据项名称"
+              prop="itemName"
+              width="300">
+          </el-table-column>
+          <el-table-column
+              label="四则运算表达式"
+              prop="rule.operationRule"
+              width="300">
+          </el-table-column>
+          <el-table-column label="操作">
+            <template slot-scope="scope">
+              <el-button
+                  size="mini"
+                  @click="handleChoose(scope.$index, scope.row)">选择表达式</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
       <span slot='footer'>
-          <el-button type="primary" @click="itemDialogSave">确定</el-button>
+          <el-button type="primary" v-if="itemDataStep == 1" @click="itemDialogSave1">下一步</el-button>
+          <el-button type="primary" v-if="itemDataStep == 2" @click="itemDialogSave2">确定</el-button>
           <el-button @click="itemDialogClose">取消</el-button>
       </span>
     </el-dialog>
+
+    <el-dialog
+        title="选择四则运算表达式"
+        width="500px"
+        top="10vh"
+        center
+        :before-close="dialogDataModelClose"
+        :visible.sync="dialogDataModelVisible"
+        :close-on-click-modal="false"
+        :append-to-body="true">
+      <el-select v-model="chooseDataModel" filterable placeholder="请选择表达式" style="width: 100%;">
+        <el-option
+            v-for="item in this.dataModelList"
+            :key="item.id"
+            :label="item.operationRule"
+            :value="item.id">
+        </el-option>
+      </el-select>
+      <div style="width: 100%; text-align: center; margin-top: 20px;">
+        <el-button type="primary" @click="saveDataModelEvent">确定</el-button>
+        <el-button @click="dialogDataModelClose">取消</el-button>
+      </div>
+    </el-dialog>
+
   </el-tabs>
 </template>
 
 <script>
 import {
   delDataSourceById,
-  delItemGroupById, delTableTemplateById,
+  delItemGroupById, delTableTemplateById, getAllDataModel,
   getAllDataSource,
   getAllItemGroup, getAllTableTemplate,
   getDataSourceItemTree, getItemGroupById,
@@ -265,11 +314,16 @@ export default {
       groupDialogVisible: false,
       dataItemDialogTitle: '选择数据项',
       dataItemDialogVisible: false,
+      dialogDataModelVisible: false,
+      chooseDataModel: null,
+      dataModelList: [],
       labelPosition: 'top',
       // 组配置右键布局显示状态
       visibleGroupMenu: false,
       visibleReportMenu: false,
       visibleGroupChildMenu: false,
+      itemDataStep: 1,
+      bomCheckKey: 0,
       // 右键布局显示位置
       menuLeft: 0,
       // 右键布局显示位置
@@ -290,7 +344,16 @@ export default {
         isLeaf: 'leaf'
       },
       // 读取模式
-      readModeList: [],
+      readModeList: [{
+        'key': '超过设置最大值读取数据',
+        'value': '0'
+      }, {
+        'key': '数据值改变',
+        'value': '1'
+      }, {
+        'key': '频率',
+        'value': '2'
+      }],
       // 数据源
       dataSourceList: [],
       // 数据项
@@ -357,7 +420,7 @@ export default {
   computed: {
   },
   created() {
-    this.getReadMode()
+    // this.getReadMode()
   },
   methods: {
     /** 数据项搜索过滤 */
@@ -560,6 +623,7 @@ export default {
         })
         return
       }
+      this.chooseItemDataList = []
       getItemGroupById(id).then(res => {
         this.createGroupEvent()
         let item = res.data
@@ -582,6 +646,7 @@ export default {
       for (let i in item.itemList) {
         let temp = item.itemList[i]
         arr.push({
+          'dataModelId': temp.dataModelId,
           'label': temp.itemName,
           'nodeIdentifier': temp.nodeIdentifier,
           'nodeIndex': temp.nodeIndex,
@@ -678,7 +743,12 @@ export default {
         })
         return
       }
+      this.itemDataStep = 1
       this.tempItemList = JSON.parse(JSON.stringify(this.groupBasicForm.itemList))
+
+      if (this.tempItemList && this.tempItemList.length > 0) {
+        this.chooseItemDataListByTree = this.tempItemList
+      }
       const loading = showLoading(this, '加载中,请稍候···')
       getDataSourceItemTree(id).then(res => {
         loading.close()
@@ -831,8 +901,8 @@ export default {
       this.$refs.itemTree.setCheckedKeys([])
       this.$refs.chooseItemTree.setCheckedKeys([])
     },
-    /** 选择数据项弹出层保存事件 */
-    itemDialogSave() {
+    /** 选择数据项弹出层保存事件:第一步 */
+    itemDialogSave1() {
       if (this.chooseItemDataListByTree.length == 0) {
         this.$message({
           message: '请选择数据项!',
@@ -845,17 +915,85 @@ export default {
       for (let i in this.chooseItemDataListByTree) {
         let temp = this.chooseItemDataListByTree[i]
         itemList.push({
-          'itemName': temp.label,
+          'dataModelId': temp.dataModelId,
+          'itemName': temp.label ? temp.label : temp.itemName,
           'nodeIdentifier': temp.nodeIdentifier,
           'nodeIndex': temp.nodeIndex,
           'dataType': temp.dataType,
         })
       }
-      this.groupBasicForm.itemList = itemList
-      this.chooseItemDataList = this.chooseItemDataListByTree
+      // this.chooseItemDataList = this.chooseItemDataListByTree
+      this.itemDataStep = 2
+      this.getAllDataModel(itemList)
+    },
+    /** 选择数据项弹出层保存事件:第二步 */
+    itemDialogSave2() {
+      this.groupBasicForm.itemList = this.chooseItemDataList
+      this.itemDataStep = 1
       this.dataItemDialogVisible = false
       this.chooseItemDataView = true
     },
+    /** 查询所有数据模型 */
+    getAllDataModel(itemList) {
+      let loading = showLoading(this, '数据加载中,请稍候···')
+      let params = {
+        'page': 1,
+        'limit': 1000
+      }
+      getAllDataModel(params).then(res => {
+        loading.close()
+        this.itemDataStep = 2
+        if (!res.data) {
+          this.chooseItemDataList = itemList
+          return
+        }
+        let dataModelList = res.data.dataModelList
+        for (let i in itemList) {
+          for (let j in dataModelList) {
+            if (itemList[i].dataModelId == dataModelList[j].id) {
+              itemList[i].rule = dataModelList[j]
+            }
+          }
+        }
+        this.dataModelList = dataModelList
+        this.$nextTick(() => {
+          this.chooseItemDataList = JSON.parse(JSON.stringify(itemList))
+          for (let i in this.chooseItemDataList) {
+            let temp = this.chooseItemDataList[i]
+            if (!temp.rule) {
+              temp.rule = {
+                'operationRule': '默认值'
+              }
+              temp.dataModelId = null
+            }
+          }
+          this.bomCheckKey ++
+        })
+      }).catch((e) => {
+        loading.close()
+      })
+    },
+    /** 保存数据模型事件 */
+    saveDataModelEvent() {
+      let item = {}
+      for (let i in this.dataModelList) {
+        if (this.chooseDataModel == this.dataModelList[i].id) {
+          item = this.dataModelList[i]
+        }
+      }
+      this.$nextTick(() => {
+        this.chooseItemDataList[this.chooseDataItemIndex].rule = item
+        this.chooseItemDataList[this.chooseDataItemIndex].dataModelId = item.id
+        this.bomCheckKey ++
+      })
+      this.dialogDataModelVisible = false
+    },
+    /** 选择数据模型 */
+    handleChoose(index, row) {
+      this.chooseDataItemIndex = index
+      this.chooseDataModel = null
+      this.dialogDataModelVisible = true
+    },
     /** 报表模板移除 */
     removeReportItem(node, data) {
       this.$confirm('您确定要删除该报表模板吗?', '温馨提示', {
@@ -915,7 +1053,15 @@ export default {
       } else {
         this.dataItemDialogVisible = false
       }
-    }
+    },
+    /** 弹出层关闭事件 */
+    dialogDataModelClose() {
+      if (typeof(done) === 'function') {
+        done()
+      } else {
+        this.dialogDataModelVisible = false
+      }
+    },
   }
 }
 </script>

+ 67 - 6
chuanyi_client2/src/components/LeftMenu/index.vue

@@ -92,7 +92,7 @@
     <!-- 数据源连接基础配置弹出层 -->
     <el-dialog
         :title="connDialogTitle"
-        width="450px"
+        width="500px"
         center
         :before-close="handleClose"
         :visible.sync="connDialogVisible"
@@ -105,14 +105,14 @@
                     auto-complete="off"
                     placeholder="主机"></el-input>
         </el-form-item>
-        <el-form-item label='端口:' prop="ipPort">
+        <el-form-item label='端口:' prop="ipPort" v-if="connForm.connType.type != 'opc_da_real'">
           <el-input v-model.number='connForm.ipPort'
                     type="text"
                     auto-complete="off"
                     placeholder="端口"
                     oninput="value=value.replace(/[^0-9.]/g,'')"></el-input>
         </el-form-item>
-        <el-form-item label="是否匿名:" prop="isAnonymous">
+        <el-form-item label="是否匿名:" prop="isAnonymous" v-if="connForm.connType.type != 'opc_da_real'">
           <el-radio-group v-model="connForm.isAnonymous">
             <el-radio
                 v-for="dict in isAnonymous"
@@ -133,6 +133,18 @@
                     auto-complete="new-password"
                     placeholder="密码"></el-input>
         </el-form-item>
+        <el-form-item label='驱动:' prop="clsId" v-if="connForm.connType.type == 'opc_da_real'">
+          <el-select v-model="connForm.clsId" placeholder="请选择驱动"
+                     style="width: calc(100% - 90px);">
+            <el-option
+                v-for="dict in driverList"
+                :key="dict.clsId"
+                :label="dict.description"
+                :value="dict.clsId"
+            ></el-option>
+          </el-select>
+          <el-button size="mini" @click="getDriverEvent" style="float: right;width: 80px;margin-top: 4px;">获取驱动</el-button>
+        </el-form-item>
       </el-form>
       <span slot='footer'>
           <el-button type="warning" @click='handleConnect(1)'>连接测试</el-button>
@@ -147,7 +159,7 @@
 import {
   delDataSourceById,
   getAllDataSource,
-  getDataSourceTree,
+  getDataSourceTree, getDriverList,
   saveOrUpdateDataSource,
   testConnect
 } from "@/api/datasource";
@@ -177,6 +189,7 @@ export default {
       serverTypeList: [],
       // 已配置的数据源
       connServerList: [],
+      driverList: [],
       datasourceForm: {
         datasourceName: '',
         desc: ''
@@ -186,7 +199,12 @@ export default {
         ipPort: '',
         ipUserName: '',
         ipPassword: '',
-        isAnonymous: 0
+        isAnonymous: 0,
+        connType: {
+          type: '',
+          id: ''
+        },
+        clsId: ''
       },
       // ***************** 表单校验开始 *****************
       datasourceRules: {
@@ -201,7 +219,6 @@ export default {
           { validator: this.testKeyByIp }
         ],
         ipPort: [
-          { required: true, message: '端口不能为空', trigger: 'blur' },
           { validator: this.testKeyByPort }
         ],
         ipUserName: [
@@ -234,6 +251,10 @@ export default {
     },
     /** 表单验证判断:端口 */
     testKeyByPort(rule, value, callback) {
+      if (this.connForm.connType.type === "opc_da_real") {
+        callback()
+        return
+      }
       const key = /^([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-4]\d{4}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/
       if (!key.test(value)) {
         callback(new Error('端口号不合法'))
@@ -353,7 +374,14 @@ export default {
           if (this.chooseConnServer) {
             this.$nextTick(() => {
               this.connForm = JSON.parse(JSON.stringify(this.chooseConnServer))
+              this.connForm.connType = {
+                'type' : this.chooseConnServer.dataSourceTypeKey,
+                'id': this.chooseConnServer.typeId
+              }
             })
+          } else {
+            this.connForm.connType.type = this.chooseServerType.labelKey
+            this.connForm.connType.id = this.chooseServerType.id
           }
         }
       })
@@ -462,6 +490,39 @@ export default {
         console.error(e)
       })
     },
+    /** 获取驱动 */
+    getDriverEvent() {
+      this.$refs['connForm'].validate(valid => {
+        if (valid) {
+          const loading = showLoading(this, '驱动获取中,请稍候···')
+          let data = {
+            'typeId': this.connForm.connType.id,
+            'ipAddress': this.connForm.ipAddress,
+            'ipUserName': this.connForm.ipUserName,
+            'ipPassword': this.connForm.ipPassword
+          }
+          if (!this.chooseConnServer || (this.chooseConnServer
+              && this.connForm.ipPassword != this.chooseConnServer.ipPassword)) {
+            data.ipPassword = encrypt(data.ipPassword, getPubKey())
+          }
+          getDriverList(data).then(res => {
+            loading.close()
+            this.driverList = res.data
+            this.$message({
+              message: '驱动获取成功!',
+              type: 'success'
+            })
+          }).catch((e) => {
+            loading.close()
+            console.error(e)
+            this.$message({
+              message: '驱动获取失败!',
+              type: 'warning'
+            })
+          })
+        }
+      })
+    },
     /** 清理数据源选择项背景 */
     clearDatasourceBg() {
       let dom = document.getElementsByClassName('el-tree-node is-expanded is-current is-focusable')[0]

+ 1 - 1
chuanyi_server/src/main/java/com/judong/chuanyiserver/controller/DataSourceController.java

@@ -56,7 +56,7 @@ public class DataSourceController {
      */
     @PostMapping("/getDaAllDriver")
     public Result getDaAllDriver(@RequestBody DataSource dataSource) {
-        if (Blank.isEmpty(dataSource, dataSource.getTypeId(), dataSource.getIpAddress(), dataSource.getIpUserName(), dataSource.getIpPassword(), dataSource.getClsId())) {
+        if (Blank.isEmpty(dataSource, dataSource.getTypeId(), dataSource.getIpAddress(), dataSource.getIpUserName(), dataSource.getIpPassword())) {
             return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "数据源类型,ip用户名密码都不能为空");
         }
         return dataSourceService.getDaAllDriver(dataSource);

+ 1 - 0
chuanyi_server/src/main/java/com/judong/chuanyiserver/service/impl/DataSourceServiceImpl.java

@@ -174,6 +174,7 @@ public class DataSourceServiceImpl implements DataSourceService {
 
     @Override
     public Result getDaAllDriver(DataSource dataSource) {
+        dataSource = DataSource.convertPassword(dataSource);
         DataSourceType dataSourceType = dataSourceDao.getDataSourceTypeById(dataSource.getTypeId());
         if (dataSourceType.getDataSourceTypeKey().equals(DataSourceTypeEnum.OPC_DA_REAL.getValue())) {
             return Result.ok(OpcDaUtil.getDaAllDriver(dataSource));

+ 8 - 8
chuanyi_server/src/main/java/com/judong/chuanyiserver/service/impl/ItemGroupServiceImpl.java

@@ -58,18 +58,18 @@ public class ItemGroupServiceImpl implements ItemGroupService {
             if (Blank.isNotEmpty(itemGroup.getItemList())) {
                 if (dataSourceType.getDataSourceTypeKey().equals(DataSourceTypeEnum.OPC_DA_REAL.getValue())) {
                     List<Item> itemList = itemGroup.getItemList();
-                    if (dataSource.getClsId().equals(OpcDaDriverEnum.KEPSERVER.getValue())) {
+                    if (dataSource.getClsId().toUpperCase().equals(OpcDaDriverEnum.KEPSERVER.getValue())) {
                         for (int i = 0; i < itemList.size(); i++) {
                             itemList.get(i).setItemReadName(itemList.get(i).getItemName());
                         }
-                    } else if (dataSource.getClsId().equals(OpcDaDriverEnum.OPCIFIX.getValue())) {
+                    } else if (dataSource.getClsId().toUpperCase().equals(OpcDaDriverEnum.OPCIFIX.getValue())) {
                         for (int i = 0; i < itemList.size(); i++) {
                             String itemName = itemList.get(i).getItemName();
                             int j = itemName.indexOf(".");
                             String s = itemName.substring(j + 1);
                             itemList.get(i).setItemReadName(itemName.substring(0, j) + s.substring(s.indexOf(".")));
                         }
-                    } else if (dataSource.getClsId().equals(OpcDaDriverEnum.WINCC.getValue())) {
+                    } else if (dataSource.getClsId().toUpperCase().equals(OpcDaDriverEnum.WINCC.getValue())) {
                         for (int i = 0; i < itemList.size(); i++) {
                             String itemName = itemList.get(i).getItemName();
                             itemList.get(i).setItemReadName(itemName.substring(itemName.lastIndexOf(".") + 1));
@@ -97,18 +97,18 @@ public class ItemGroupServiceImpl implements ItemGroupService {
             }
             if (dataSourceType.getDataSourceTypeKey().equals(DataSourceTypeEnum.OPC_DA_REAL.getValue())) {
                 List<Item> itemList = itemGroup.getItemList();
-                if (dataSource.getClsId().equals(OpcDaDriverEnum.KEPSERVER.getValue())) {
+                if (dataSource.getClsId().toUpperCase().equals(OpcDaDriverEnum.KEPSERVER.getValue())) {
                     for (int i = 0; i < itemList.size(); i++) {
                         itemList.get(i).setItemReadName(itemList.get(i).getItemName());
                     }
-                } else if (dataSource.getClsId().equals(OpcDaDriverEnum.OPCIFIX.getValue())) {
+                } else if (dataSource.getClsId().toUpperCase().equals(OpcDaDriverEnum.OPCIFIX.getValue())) {
                     for (int i = 0; i < itemList.size(); i++) {
                         String itemName = itemList.get(i).getItemName();
                         int j = itemName.indexOf(".");
                         String s = itemName.substring(j + 1);
                         itemList.get(i).setItemReadName(itemName.substring(0, j) + s.substring(s.indexOf(".")));
                     }
-                } else if (dataSource.getClsId().equals(OpcDaDriverEnum.WINCC.getValue())) {
+                } else if (dataSource.getClsId().toUpperCase().equals(OpcDaDriverEnum.WINCC.getValue())) {
                     for (int i = 0; i < itemList.size(); i++) {
                         String itemName = itemList.get(i).getItemName();
                         itemList.get(i).setItemReadName(itemName.substring(itemName.lastIndexOf(".") + 1));
@@ -251,7 +251,7 @@ public class ItemGroupServiceImpl implements ItemGroupService {
                 //获取读取使用的itemName
                 List<String> itemList = itemGroupDao.getItemByIdChange(id);
                 //如果驱动是kepserver,则不进行变化
-                if (dataSource.getClsId().equals(OpcDaDriverEnum.OPCIFIX.getValue())) {
+                if (dataSource.getClsId().toUpperCase().equals(OpcDaDriverEnum.OPCIFIX.getValue())) {
                     if (Blank.isNotEmpty(itemList)) {
                         for (int i = 0; i < itemList.size(); i++) {
                             String itemName = itemList.get(i);
@@ -263,7 +263,7 @@ public class ItemGroupServiceImpl implements ItemGroupService {
                     String[] items = itemList.toArray(new String[]{});
                     timer.schedule(new OpcTimerTask(redisUtil, opcAsyncTask, itemGroupDao, timer, itemGroup, dataSource, map, items),
                             DateUtil.strChangeDate(DateUtil.getCurrentYmd() + " " + itemGroup.getStartReadTime()), ConstantStr.PERIOD_DAY);
-                } else if (dataSource.getClsId().equals(OpcDaDriverEnum.WINCC.getValue())) {
+                } else if (dataSource.getClsId().toUpperCase().equals(OpcDaDriverEnum.WINCC.getValue())) {
 
                 } else {
                     throw new CustomException(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "目前未适配此种驱动类型");

+ 10 - 4
chuanyi_server/src/main/java/com/judong/chuanyiserver/util/OpcDaUtil.java

@@ -81,11 +81,11 @@ public class OpcDaUtil {
                 throw new CustomException(ResultEnum.NOT_FOUND.getRespCode(), "连接失败");
             }
             if (OPCSERVERSTATE.OPC_STATUS_RUNNING == server.getServerState().getServerState()) {
-                if (dataSource.getClsId().equals(OpcDaDriverEnum.KEPSERVER.getValue()) ||
+                if (dataSource.getClsId().toUpperCase().equals(OpcDaDriverEnum.KEPSERVER.getValue()) ||
                         dataSource.getClsId().equals(OpcDaDriverEnum.OPCIFIX.getValue())) {
                     List<JSONObject> jsonObjectList = generServerTree(server);
                     return Result.ok(jsonObjectList);
-                } else if (dataSource.getClsId().equals(OpcDaDriverEnum.WINCC.getValue())) {
+                } else if (dataSource.getClsId().toUpperCase().equals(OpcDaDriverEnum.WINCC.getValue())) {
                     List<JSONObject> jsonObjectList = generWinccTree(server);
                     return Result.ok(jsonObjectList);
                 } else {
@@ -217,9 +217,15 @@ public class OpcDaUtil {
             }
             return jsonObjectList;
         } catch (Exception e) {
-            e.printStackTrace();
+            String message = e.getMessage();
+            if (message.contains("0x00000005")) {
+                throw new CustomException(ResultEnum.REQUEST_TIME_OUT.getRespCode(), "用户名或密码错误");
+            }
+            if (message.contains("0x8001FFFF")) {
+                throw new CustomException(ResultEnum.REQUEST_TIME_OUT.getRespCode(), "ip地址不存在");
+            }
+            throw new CustomException(ResultEnum.REQUEST_TIME_OUT.getRespCode(), e.getMessage());
         }
-        return null;
     }
 
     /**