浏览代码

室内温湿度自定义组件

cyy 9 月之前
父节点
当前提交
379182c162

+ 47 - 88
package-lock.json

@@ -2278,6 +2278,17 @@
             "unique-filename": "^1.1.1"
             "unique-filename": "^1.1.1"
           }
           }
         },
         },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
         "cliui": {
         "cliui": {
           "version": "6.0.0",
           "version": "6.0.0",
           "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
           "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
@@ -2350,6 +2361,25 @@
             "supports-color": "^7.0.0"
             "supports-color": "^7.0.0"
           }
           }
         },
         },
+        "json5": {
+          "version": "2.2.3",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+          "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+          "dev": true,
+          "optional": true
+        },
+        "loader-utils": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
         "locate-path": {
         "locate-path": {
           "version": "5.0.0",
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
           "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -2451,6 +2481,18 @@
             "webpack-sources": "^1.4.3"
             "webpack-sources": "^1.4.3"
           }
           }
         },
         },
+        "vue-loader-v16": {
+          "version": "npm:vue-loader@16.8.3",
+          "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
+          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "chalk": "^4.1.0",
+            "hash-sum": "^2.0.0",
+            "loader-utils": "^2.0.0"
+          }
+        },
         "wrap-ansi": {
         "wrap-ansi": {
           "version": "6.2.0",
           "version": "6.2.0",
           "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
           "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
@@ -5590,6 +5632,11 @@
         }
         }
       }
       }
     },
     },
+    "dayjs": {
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
+      "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
+    },
     "de-indent": {
     "de-indent": {
       "version": "1.0.2",
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
       "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
@@ -15594,94 +15641,6 @@
         }
         }
       }
       }
     },
     },
-    "vue-loader-v16": {
-      "version": "npm:vue-loader@16.8.3",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
-      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "chalk": "^4.1.0",
-        "hash-sum": "^2.0.0",
-        "loader-utils": "^2.0.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-convert": "^2.0.1"
-          }
-        },
-        "chalk": {
-          "version": "4.1.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^4.1.0",
-            "supports-color": "^7.1.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "color-name": {
-          "version": "1.1.4",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-          "dev": true,
-          "optional": true
-        },
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true,
-          "optional": true
-        },
-        "json5": {
-          "version": "2.2.3",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
-          "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
-          "dev": true,
-          "optional": true
-        },
-        "loader-utils": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
-          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^2.1.2"
-          }
-        },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        }
-      }
-    },
     "vue-qr": {
     "vue-qr": {
       "version": "2.3.0",
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/vue-qr/-/vue-qr-2.3.0.tgz",
       "resolved": "https://registry.npmjs.org/vue-qr/-/vue-qr-2.3.0.tgz",

+ 1 - 0
package.json

@@ -27,6 +27,7 @@
     "bpmn-js": "^7.3.0",
     "bpmn-js": "^7.3.0",
     "core-js": "^3.6.5",
     "core-js": "^3.6.5",
     "crypto-js": "^4.2.0",
     "crypto-js": "^4.2.0",
+    "dayjs": "^1.11.13",
     "fastclick": "^1.0.6",
     "fastclick": "^1.0.6",
     "hls.js": "^0.14.10",
     "hls.js": "^0.14.10",
     "js-cookie": "^2.2.1",
     "js-cookie": "^2.2.1",

+ 68 - 68
src/business/platform/data/data-template/field-formatter.vue

@@ -99,8 +99,8 @@ export default {
         this.label = value
         this.label = value
         return
         return
       }
       }
-      const fieldType = this.descField.same === 'N' ? this.descField.field_type : this.fieldType
-      const fieldOptions = this.descField.same === 'N' ? this.descField.field_options : this.fieldOptions
+      const fieldType = this.descField && this.descField.same === 'N' ? this.descField.field_type : this.fieldType
+      const fieldOptions = this.descField && this.descField.same === 'N' ? this.descField.field_options : this.fieldOptions
       if (
       if (
         this.$utils.isEmpty(value) ||
         this.$utils.isEmpty(value) ||
         this.$utils.isEmpty(fieldType) ||
         this.$utils.isEmpty(fieldType) ||
@@ -222,15 +222,15 @@ export default {
           'name'
           'name'
         )
         )
       } else {
       } else {
-        remoteRequest('formTemplate', {key}, () => {
-            return getDictionaryData({
-              typeKey: key
-            })
-          }).then(response => {
-            const data = response.data
-            DICTIONARY_CACHE[key] = data
-            this.label = this.formatterOptions(value, data, 'key', 'name')
+        remoteRequest('formTemplate', { key }, () => {
+          return getDictionaryData({
+            typeKey: key
           })
           })
+        }).then(response => {
+          const data = response.data
+          DICTIONARY_CACHE[key] = data
+          this.label = this.formatterOptions(value, data, 'key', 'name')
+        })
           .catch(e => {
           .catch(e => {
             DICTIONARY_CACHE[key] = []
             DICTIONARY_CACHE[key] = []
             // 异常
             // 异常
@@ -270,29 +270,29 @@ export default {
               SELECTOR_CACHE[key] = item.userName + ','
               SELECTOR_CACHE[key] = item.userName + ','
             }
             }
           })
           })
-          remoteRequest('formTemplate', {key}, () => {
+          remoteRequest('formTemplate', { key }, () => {
             return getUserById({ employeeId: id })
             return getUserById({ employeeId: id })
           }).then(response => {
           }).then(response => {
-              const data = response.data
-              data[nameKey] = data['name']
-              if (data) {
-                SELECTOR_CACHE[key] = data[nameKey]
-                this.label = data[nameKey]
-              }
-            })
+            const data = response.data
+            data[nameKey] = data['name']
+            if (data) {
+              SELECTOR_CACHE[key] = data[nameKey]
+              this.label = data[nameKey]
+            }
+          })
             .catch(e => {
             .catch(e => {
               console.error(e)
               console.error(e)
             })
             })
         } else if (type === 'org') {
         } else if (type === 'org') {
-          remoteRequest('formTemplate', {key}, () => {
+          remoteRequest('formTemplate', { key }, () => {
             return getOrgById({ orgId: id })
             return getOrgById({ orgId: id })
           }).then(response => {
           }).then(response => {
-              const data = response.data
-              if (data) {
-                this.label = data[nameKey]
-                SELECTOR_CACHE[key] = data[nameKey]
-              }
-            })
+            const data = response.data
+            if (data) {
+              this.label = data[nameKey]
+              SELECTOR_CACHE[key] = data[nameKey]
+            }
+          })
             .catch(e => {
             .catch(e => {
               console.error(e)
               console.error(e)
             })
             })
@@ -303,15 +303,15 @@ export default {
               SELECTOR_CACHE[key] = item.positionName + ','
               SELECTOR_CACHE[key] = item.positionName + ','
             }
             }
           })
           })
-          remoteRequest('formTemplate', {key}, () => {
+          remoteRequest('formTemplate', { key }, () => {
             return getPositionById({ positionId: id })
             return getPositionById({ positionId: id })
           }).then(response => {
           }).then(response => {
-              const data = response.data
-              if (data) {
-                this.label = data[nameKey]
-                SELECTOR_CACHE[key] = data[nameKey]
-              }
-            })
+            const data = response.data
+            if (data) {
+              this.label = data[nameKey]
+              SELECTOR_CACHE[key] = data[nameKey]
+            }
+          })
             .catch(e => {
             .catch(e => {
               console.error(e)
               console.error(e)
             })
             })
@@ -322,15 +322,15 @@ export default {
               SELECTOR_CACHE[key] = item.NAME_ + ','
               SELECTOR_CACHE[key] = item.NAME_ + ','
             }
             }
           })
           })
-          remoteRequest('formTemplate', {key}, () => {
+          remoteRequest('formTemplate', { key }, () => {
             return getRoleById({ roleId: id })
             return getRoleById({ roleId: id })
           }).then(response => {
           }).then(response => {
-              const data = response.data
-              if (data) {
-                this.label = data[nameKey]
-                SELECTOR_CACHE[key] = data[nameKey]
-              }
-            })
+            const data = response.data
+            if (data) {
+              this.label = data[nameKey]
+              SELECTOR_CACHE[key] = data[nameKey]
+            }
+          })
             .catch(e => {
             .catch(e => {
               console.error(e)
               console.error(e)
             })
             })
@@ -403,23 +403,23 @@ export default {
       this.label = ''
       this.label = ''
       value.split(',').forEach(id => {
       value.split(',').forEach(id => {
         if (key) {
         if (key) {
-          remoteRequest('formTemplate', {key}, () => {
+          remoteRequest('formTemplate', { key }, () => {
             return getDataById({ id: id, key: key })
             return getDataById({ id: id, key: key })
           })
           })
-          .then(response => {
-            const responseData = response.data
-            const data = responseData.data[0]
-            // const data = response.data
-            const variables = response.data
-            if (this.$utils.isNotEmpty(data)) {
+            .then(response => {
+              const responseData = response.data
+              const data = responseData.data[0]
+              // const data = response.data
+              const variables = response.data
+              if (this.$utils.isNotEmpty(data)) {
               // TODO 多个字段组合处理
               // TODO 多个字段组合处理
-              const a = this.exp(data, variables['title'].name)
-              const val = variables['title'] || ''
-              this.label += this.$utils.isNotEmpty(a) ? a : ''
-            }
-          }).catch((e) => {
-            console.error(e)
-          })
+                const a = this.exp(data, variables['title'].name)
+                const val = variables['title'] || ''
+                this.label += this.$utils.isNotEmpty(a) ? a : ''
+              }
+            }).catch((e) => {
+              console.error(e)
+            })
         } else {
         } else {
           const labelKeys = buildLabelTitle(this.tem)
           const labelKeys = buildLabelTitle(this.tem)
           const a = this.handleLabel(this.data, labelKeys)
           const a = this.handleLabel(this.data, labelKeys)
@@ -465,25 +465,25 @@ export default {
       if (this.$utils.isEmpty(key)) {
       if (this.$utils.isEmpty(key)) {
         return value
         return value
       }
       }
-      remoteRequest('formTemplate', {key}, () => {
+      remoteRequest('formTemplate', { key }, () => {
         return getLinkDataByKey({ key: key })
         return getLinkDataByKey({ key: key })
       }).then(response => {
       }).then(response => {
-          const data = response.data
-          if (this.$utils.isNotEmpty(data)) {
-            const arrayValue = value.split(',')
-            const rtn = []
-            for (var d = 0; d < data.length; d++) {
-              const item = data[d]
-              const v = arrayValue.find(val => {
-                return val === item[__linkKey]
-              })
-              if (v) {
-                rtn.push(item[__linkText] || '')
-              }
+        const data = response.data
+        if (this.$utils.isNotEmpty(data)) {
+          const arrayValue = value.split(',')
+          const rtn = []
+          for (var d = 0; d < data.length; d++) {
+            const item = data[d]
+            const v = arrayValue.find(val => {
+              return val === item[__linkKey]
+            })
+            if (v) {
+              rtn.push(item[__linkText] || '')
             }
             }
-            this.label += rtn.join(',')
           }
           }
-        })
+          this.label += rtn.join(',')
+        }
+      })
         .catch(e => {
         .catch(e => {
           console.error(e)
           console.error(e)
         })
         })

+ 17 - 16
src/business/platform/data/templaterender/linkdata/index.vue

@@ -79,8 +79,8 @@
         :parent-id-key="parentIdKey"
         :parent-id-key="parentIdKey"
         :is-tree="isTree"
         :is-tree="isTree"
         :query-key="queryKey"
         :query-key="queryKey"
-        fieldType="linkdata"
-        :searchPlaceholder="'请输入'"
+        field-type="linkdata"
+        :search-placeholder="'请输入'"
         :template-fields="templateFields"
         :template-fields="templateFields"
         :dynamic-params="dynamicParams"
         :dynamic-params="dynamicParams"
         @init-data="initData"
         @init-data="initData"
@@ -163,28 +163,29 @@ export default {
       showPopup: false, // 弹窗
       showPopup: false, // 弹窗
       selectedData: [], // 选中的数据,这个值是用于展示的
       selectedData: [], // 选中的数据,这个值是用于展示的
       selectedValue: [], // 选中的值 是valueKey的值
       selectedValue: [], // 选中的值 是valueKey的值
-      tem: {}
+      tem: {},
+      valueKey: ''
     }
     }
   },
   },
   computed: {
   computed: {
     showClear() {
     showClear() {
       return this.clearable && this.$utils.isNotEmpty(this.value) && isDef(this.value) && this.editable
       return this.clearable && this.$utils.isNotEmpty(this.value) && isDef(this.value) && this.editable
     },
     },
-    linkValueKey () {
-        return this.fieldOptions['link_config'] ? this.fieldOptions['link_config'].id || '' : ''
+    linkValueKey() {
+      return this.fieldOptions['link_config'] ? this.fieldOptions['link_config'].id || '' : ''
     },
     },
-    linkLabelType () {
-        return this.fieldOptions['link_config'] ? this.fieldOptions['link_config'].type || 'first' : 'first'
+    linkLabelType() {
+      return this.fieldOptions['link_config'] ? this.fieldOptions['link_config'].type || 'first' : 'first'
     },
     },
-    linkLabelKey () {
-        return this.fieldOptions['link_config'] ? this.fieldOptions['link_config'].text || '' : ''
+    linkLabelKey() {
+      return this.fieldOptions['link_config'] ? this.fieldOptions['link_config'].text || '' : ''
     },
     },
-    linkStructure () {
-        return this.fieldOptions['link_config'] ? this.fieldOptions['link_config'].structure || 'list' : 'list'
-    },
-    linkConfig () {
-        return this.fieldOptions['link_config'] ? this.fieldOptions['link_config'] || {} : {}
+    linkStructure() {
+      return this.fieldOptions['link_config'] ? this.fieldOptions['link_config'].structure || 'list' : 'list'
     },
     },
+    linkConfig() {
+      return this.fieldOptions['link_config'] ? this.fieldOptions['link_config'] || {} : {}
+    }
   },
   },
   watch: {
   watch: {
     value: {
     value: {
@@ -208,7 +209,7 @@ export default {
       const params = {}
       const params = {}
       loadDataTemplateByKey(key, params).then((data) => {
       loadDataTemplateByKey(key, params).then((data) => {
         const template = getDataTemplateListTemplate(data)
         const template = getDataTemplateListTemplate(data)
-        this.tem ={...template}
+        this.tem = { ...template }
         this.templateFields = buildDataTemplateFields(data.fields)
         this.templateFields = buildDataTemplateFields(data.fields)
         this.buildKey(data, template)
         this.buildKey(data, template)
       }).catch((e) => {
       }).catch((e) => {
@@ -219,7 +220,7 @@ export default {
       this.idKey = dataTemplate['unique']
       this.idKey = dataTemplate['unique']
       this.queryKey = this.getQueryKey(template['query_columns'])
       this.queryKey = this.getQueryKey(template['query_columns'])
       const resultColumns = template['result_columns']
       const resultColumns = template['result_columns']
-      console.log(resultColumns,'resultColumnsresultColumns')
+      console.log(resultColumns, 'resultColumnsresultColumns')
       if (this.$utils.isEmpty(resultColumns)) { return }
       if (this.$utils.isEmpty(resultColumns)) { return }
       // this.labelKey = resultColumns[0]['name']
       // this.labelKey = resultColumns[0]['name']
       if (dataTemplate.showType === 'tree') { // 树形
       if (dataTemplate.showType === 'tree') { // 树形

+ 400 - 0
src/views/component/facility/facilityData.vue

@@ -0,0 +1,400 @@
+<!--
+    author:luoaoxuan
+    subject:设施环境通用组件
+-->
+<template>
+    <div class="ficily-data">
+        <!-- <el-row type="flex">
+            <el-col style="margin:0 0 5px 0">
+                <div class="button">
+                    <el-button v-if="!isCul" type="danger" size="mini" icon="ibps-icon-close" @click="goRemove">删除</el-button>
+                    <el-button v-if="!isCul" type="success" size="mini" icon="ibps-icon-plus" @click="goAdd">添加</el-button>
+                </div>
+            </el-col>
+        </el-row> -->
+        <van-collapse v-model="activeNames">
+            <van-collapse-item v-for="(item,i) in forms" :key="'van'+i" title="标题1" :name="'van'+i">
+                <template #title>
+                    <div class="col-title">
+                        <div class="van-cell__title">
+                            <i class="van-cell--required" /><van-tag v-if="forms.length !== 1" round type="primary">{{ i+1 }}</van-tag>
+                        </div>
+                    </div>
+                </template>
+                <div>
+                    <van-field v-model="item.label" label="参数名称" :readonly="!(!readonly && !isCul)"/>
+                    <van-field v-model="item.unit" label="参数单位" :readonly="!(!readonly && !isCul)"/>
+                    <van-field v-model="item.rangeStr" label="参数范围限值" :readonly="!(!readonly && !isCul)"/>
+                    <van-field v-model="item.fixValue" label="参数修正值" :readonly="!(!readonly && !isCul)"/>
+                    <van-field v-model="item.rate" label="填写频率" :readonly="!(!readonly && !isCul)" />
+                    <van-field v-model="item.value" label="参数值" :readonly="readonly"/>
+                    <van-field v-model="item.result" label="最终值" :readonly="true"/>
+                    <van-field v-model="item.status" label="状态" :readonly="true"/>
+                </div>
+                <template #right-icon>
+                    <div class="expand">{{ activeNames.includes('van'+i) ? '收起': '展开' }}</div>
+                </template>
+            </van-collapse-item>
+        </van-collapse>
+        <!-- <el-row type="flex">
+            <el-col>
+                <el-table :data="forms" border @selection-change="handleSelectionChange">
+                    <el-table-column
+                        width="50"
+                        type="selection"
+                    />
+                    <el-table-column label="参数名称" prop="label">
+                        <template slot-scope="{row}">
+                            <el-input v-if="!readonly && !isCul" v-model="row.label" size="mini" placeholder="请输入" />
+                            <span v-else>{{ row.label|| '/' }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="参数单位" prop="unit" width="120">
+                        <template slot-scope="{row}">
+                            <el-autocomplete
+                                v-if="!readonly && !isCul"
+                                v-model="row.unit"
+                                class="inline-input"
+                                :fetch-suggestions="querySearch"
+                                placeholder="请输入"
+                                size="mini"
+                            />
+                            <span v-else>{{ row.unit || '/' }}</span>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="参数范围限值" prop="range" width="300">
+                        <template slot-scope="{row}">
+                            <NumberRange v-model="row.range" :precision="2" :disabled="readonly || isCul" /></template>
+                    </el-table-column>
+
+                    <el-table-column label="参数修正值" prop="fixValue" width="120">
+                        <template slot-scope="{row}">
+                            <el-input v-if="!readonly && !isCul" v-model="row.fixValue" size="mini" placeholder="请输入" type="number" />
+                            <span v-else>{{ row.fixValue|| '/' }}</span>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="填写频率" prop="rate">
+                        <template slot="header" slot-scope="">
+                            <el-tooltip class="item" effect="dark" content="配置参数填写周期,适用于参数填写频率与监测周期不一致的情况。若为空则表示该参数每次推送都需填写。" placement="top-start">
+                                <span>
+                                    填写频率
+                                    <i class="el-icon-question" />
+                                </span>
+                            </el-tooltip>
+                        </template>
+                        <template slot-scope="{row,$index}">
+                            <span>{{ row.rate || '/' }}</span>
+                            <el-button v-if="!readonly && !isCul" size="mini" icon="ibps-icon-edit" type="text" style="margin-left:10px" @click="openDialog(row,$index)">编辑</el-button>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column v-if="isCul" label="参数值" prop="value">
+                        <template slot-scope="{row}">
+                            <el-input v-if="!readonly" v-model="row.value" size="mini" placeholder="请输入" type="number" :readonly="readonly" />
+                            <span v-else>{{ row.value || '/' }}</span>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column v-if="isCul" label="最终值" prop="result">
+                        <template slot-scope="{row}">
+                            <span>{{ row.result || '/' }}</span>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column v-if="isCul" label="状态" prop="status">
+                        <template slot-scope="{row}">
+                            <span>{{ row.status || '/' }}</span>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </el-col>
+        </el-row> -->
+        <FacilityDataDialog v-if="dialogShow" :dialog-visible.sync="dialogShow" :params="dialogParams" @submit="dialogSubmit" />
+    </div>
+</template>
+<script>
+import NumberRange from '@/views/component/xcomponent/numberRange.vue'
+import FacilityDataDialog from './facilityDataDialog.vue'
+export default {
+  components: {
+    NumberRange, FacilityDataDialog
+  },
+  props: {
+    formData: {
+      type: Object,
+      default: () => {}
+    },
+    readonly: {
+      type: Boolean,
+      default: false
+    },
+    isCul: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      dialogParams: {},
+      dialogShow: false,
+      isFirst: true,
+      forms: [],
+      multipleSelection: [],
+      config: 1,
+      activeNames: [1]
+    }
+  },
+  computed: {
+  },
+  watch: {
+    formData: {
+      handler(val) {
+        if (val.lieBiaoShuJu) {
+          if (!this.isCul) {
+            this.forms = this.initData(val.lieBiaoShuJu)
+            this.forms.forEach((item, i) => {
+              item['rangeArr'] = item.range.map(t => t === null ? '/' : t)
+              item['rangeStr'] = item.rangeArr.length === 2 ? item.rangeArr.join('至') : item.rangeArr.length === 1 ? `${item.rangeArr[0]}至/` : '/'
+            })
+          } else {
+            if (this.isFirst) {
+              this.forms = this.initData(val.lieBiaoShuJu)
+
+              this.forms.forEach((item, i) => {
+                item['rangeArr'] = item.range.map(t => t === null ? '/' : t)
+                item['rangeStr'] = item.rangeArr.length === 2 ? item.rangeArr.join('至') : item.rangeArr.length === 1 ? `${item.rangeArr[0]}至/` : '/'
+              })
+              this.isFirst = false
+            }
+          }
+        }
+        this.culXiuZheng()
+      },
+      deep: true,
+      immediate: true
+    },
+    forms: {
+      handler(val) {
+        // console.log('forms', val)
+        this.culXiuZheng()
+        this.$emit('change-data', 'lieBiaoShuJu', JSON.stringify(val))
+      },
+      deep: true
+    }
+  },
+  async mounted() {
+    const { setting = {}} = this.$store.getters
+    if (this.$utils.isNotEmpty(setting.facilityEnv) && this.$utils.isNotEmpty(setting.facilityEnv.precision)) {
+      this.config = setting.facilityEnv.precision
+    }
+  },
+  methods: {
+    // 弹窗的提交事件
+    dialogSubmit(data, index) {
+      this.$set(this.forms, index, data)
+      // console.log('form', this.forms)
+    },
+    openDialog(row, $index) {
+      this.dialogParams = {
+        ...row,
+        $index
+      }
+      this.dialogShow = true
+    },
+    // 计算时间差
+    getDayDifference(date1, date2) {
+      // 将两个日期转换为Date对象
+      const d1 = new Date(date1)
+      const d2 = new Date(date2)
+      // 计算两个日期之间的毫秒差
+      const timeDiff = d2.getTime() - d1.getTime()
+      // 将毫秒差转换为天数并返回
+      const dayDiff = Math.ceil(timeDiff / (1000 * 3600 * 24))
+      // console.log(dayDiff)
+      return dayDiff
+    },
+    // 初始化数据
+    initData(data) {
+      data = data.replace(/\n/g, '')
+      const ans = JSON.parse(data)
+      const result = []
+      if (this.isFirst) {
+        console.log(ans)
+        console.log('formData', this.formData)
+      }
+      ans.forEach(item => {
+        if (!Object.hasOwn(item, 'label')) {
+          item.label = ''
+        }
+        if (!Object.hasOwn(item, 'unit')) {
+          item.unit = '℃'
+        }
+        if (!Object.hasOwn(item, 'range')) {
+          item.range = [null, null]
+        }
+        if (!Object.hasOwn(item, 'fixValue')) {
+          item.fixValue = ''
+        }
+        if (!Object.hasOwn(item, 'value')) {
+          item.value = ''
+        }
+        if (!Object.hasOwn(item, 'result')) {
+          item.result = ''
+        }
+        if (!Object.hasOwn(item, 'rate')) {
+          item.rate = ''
+        }
+        if (!Object.hasOwn(item, 'status')) {
+          item.status = ''
+        }
+        if (!Object.hasOwn(item, 'period')) {
+          item.period = ''
+        }
+        if (!Object.hasOwn(item, 'date')) {
+          item.date = ''
+        }
+        if (!Object.hasOwn(item, 'startTime')) {
+          item.startTime = ''
+        }
+
+        // this.formData.jianCeShiJian = '2025-03-01' // 测试用
+        if (!item.result && (item.rate && (this.formData.jianCeShiJian || this.readonly))) {
+          let jianCeShiJian = ''
+          if (this.readonly) {
+            jianCeShiJian = this.formData.bianZhiShiJian?.slice(0, 10)
+          } else {
+            jianCeShiJian = this.formData.jianCeShiJian?.slice(0, 10)
+          }
+          const thatDate = new Date(jianCeShiJian)
+          let day = thatDate.getDay() // 周几
+          if (day === 0) { // 周日得到结果为0 需要特判
+            day = 7
+          }
+          const dayofMonth = thatDate.getDate() // 多少号
+          const monthofYear = thatDate.getMonth() + 1 // 多少月
+          const monthInQuarter = monthofYear % 3 === 0 ? 3 : monthofYear % 3 // 计算当前月在当前季度中的第几个月
+          let dayDiff = ''
+          console.log(`监测时间:${jianCeShiJian},周${day}`)
+          switch (item.period) {
+            case 'day':
+              if (item.date.indexOf(day) > -1) {
+                result.push(item)
+              }
+              break
+            case 'week':
+              if (item.date === day) {
+                result.push(item)
+              }
+              break
+            case 'month':
+              if (item.date === dayofMonth) {
+                result.push(item)
+              }
+              break
+            case 'quarter':
+              if (item.date === monthInQuarter && dayofMonth === 1) {
+                result.push(item)
+              }
+              break
+            case 'repeat':
+              dayDiff = this.getDayDifference(item.startTime, jianCeShiJian)
+              if (dayDiff >= 0 && dayDiff % (item.date + 1) === 0) {
+                result.push(item)
+              }
+              break
+            default:
+              break
+          }
+        } else {
+          result.push(item)
+        }
+      })
+      return result
+    },
+    // 默认单位
+    querySearch(queryString, cb) {
+      const units = [{ value: '℃' }, { value: '%' }, { value: 'Pa' }, { value: 'MΩ·CM' }, { value: 'uS/cm' }, { value: 'cfu/ml' }]
+      // 调用 callback 返回建议列表的数据
+      cb(units)
+    },
+    // 计算状态
+    getStatus(range, result) {
+      let [min, max] = range
+      if (min === null || min === '' || typeof min === 'undefined') min = Number.NEGATIVE_INFINITY
+      if (max === null || max === '' || typeof max === 'undefined') max = Number.POSITIVE_INFINITY
+      if (+min === 0 && +max === 0) {
+        return '正常'
+      }
+      if (+result <= +max && +result >= +min) {
+        return '正常'
+      }
+      return '失控'
+    },
+    // 计算修正值
+    culXiuZheng() {
+      if (!this.isCul) return
+      if (this.readonly) return
+      this.forms.forEach(item => {
+        if (item.value) {
+          if (item.fixValue) {
+            item.result = (+item.fixValue + +item.value).toFixed(this.config)
+          } else {
+            item.result = (+item.value).toFixed(this.config)
+          }
+          item.status = this.getStatus(item.range, item.result)
+        } else {
+          item.result = ''
+          item.status = ''
+        }
+      })
+    },
+    formatData(val) {
+      return JSON.stringify(val)
+    },
+    goAdd() {
+      if (this.forms.length >= 10) {
+        return this.$message({
+          message: '超过最大限制!',
+          type: 'warning'
+        })
+      }
+      this.forms.push({
+        label: '',
+        range: [],
+        fixValue: '',
+        value: '',
+        result: '',
+        status: '',
+        unit: '',
+        period: '',
+        date: ''
+      })
+    },
+    goRemove() {
+      this.forms = this.forms.filter(item => !this.multipleSelection.includes(item))
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.ficily-data{
+    margin-bottom: 20px;
+    .button{
+        display: flex;
+        flex-direction: row-reverse;
+        .el-button{
+            margin-left: 5px;
+        }
+    }
+    .expand {
+      color: #1989fa;
+      cursor: pointer;
+    }
+
+}
+</style>

+ 219 - 0
src/views/component/facility/facilityDataDialog.vue

@@ -0,0 +1,219 @@
+<template>
+    <el-dialog
+        :title="title"
+        :visible.sync="dialogVisible"
+        width="60%"
+        append-to-body
+        class="dialog"
+        :close-on-click-modal="false"
+        :close-on-press-escape="false"
+        :show-close="false"
+    >
+        <div class="contain">
+            <div class="form">
+                <el-form ref="formRef" :model="form" label-width="120" :rules="rules">
+                    <el-row class="item">
+                        <el-col>
+                            <el-form-item label="监测周期:" prop="period">
+                                <el-select v-model="form.period" placeholder="请选择" size="mini" :clearable="true" style="width:100%" @change="periodChange()">
+                                    <el-option
+                                        v-for="item in periodList"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                    />
+                                </el-select>
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                    <el-row v-if="form.period" class="item">
+                        <el-col>
+                            <el-form-item label="监测频率:" prop="date">
+                                <el-select
+                                    v-if="form.period==='day' || form.period==='week'"
+                                    v-model="form.date"
+                                    :multiple="form.period==='day'"
+                                    placeholder="请选择"
+                                    size="mini"
+                                    style="width:100%"
+                                >
+                                    <el-option
+                                        v-for="item in weekDays"
+                                        :key="item.value"
+                                        :label="item.label"
+                                        :value="item.value"
+                                    />
+                                </el-select>
+                                <el-select v-if="form.period==='month'" v-model="form.date" placeholder="请选择" size="mini" style="width:100%">
+                                    <el-option
+                                        v-for="item in 28"
+                                        :key="item"
+                                        :label="`第${item}天`"
+                                        :value="item"
+                                    />
+                                </el-select>
+                                <el-select v-if="form.period==='quarter'" v-model="form.date" placeholder="请选择" size="mini" style="width:100%">
+                                    <el-option
+                                        v-for="item in 3"
+                                        :key="item"
+                                        :label="`第${item}个月`"
+                                        :value="item"
+                                    />
+                                </el-select>
+                                <div v-if="form.period==='repeat'" style="display:flex;align-items: center;width:100%">
+                                    <el-select v-model="form.date" placeholder="请选择" size="mini" style="width:100%">
+                                        <el-option
+                                            v-for="item in 30"
+                                            :key="item"
+                                            :label="`每隔${item}天`"
+                                            :value="item"
+                                        />
+                                    </el-select>
+                                </div>
+
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                    <el-row v-if="form.period==='repeat'" class="item">
+                        <el-col>
+                            <el-form-item label="开始时间:" prop="startTime">
+                                <el-date-picker
+                                    v-model="form.startTime"
+                                    :clearable="false"
+                                    type="date"
+                                    placeholder="选择监测开始时间"
+                                    :picker-options="pickerOptions"
+                                    value-format="yyyy-MM-dd"
+                                    size="mini"
+                                    style="width:100%"
+                                />
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                </el-form>
+
+            </div>
+        </div>
+        <span slot="footer" class="dialog-footer">
+            <el-button type="primary" size="mini" icon="ibps-icon-save" @click="handleConfirm">确 定</el-button>
+            <el-button size="mini" icon="ibps-icon-close" @click="handleClose">取 消</el-button>
+        </span>
+    </el-dialog>
+</template>
+
+<script>
+import dayjs from 'dayjs'
+
+export default {
+    props: {
+        params: {
+            type: Object,
+            default: () => {}
+        },
+        dialogVisible: {
+            type: Boolean,
+            default: false
+        }
+    },
+    data () {
+        return {
+            title: '',
+            rules: {
+                period: [
+                    { required: true, message: '请选择监测周期', trigger: 'blur' }
+                ],
+                date: [
+                    { required: true, message: '请选择查询的日期', trigger: 'blur' }
+                ],
+                startTime: [
+                    { required: true, message: '请选择开始时间', trigger: 'blur' }
+                ]
+            },
+            pickerOptions: {
+                disabledDate (time) {
+                    return time.getTime() < (Date.now() - (24 * 60 * 1000 * 60))
+                }
+            },
+            form: {
+                period: '',
+                date: '',
+                startTime: dayjs().format('YYYY-MM-DD')
+            },
+            periodList: [{ label: '日监测', value: 'day' }, { label: '周监测', value: 'week' }, { label: '月监测', value: 'month' }, { label: '季度监测', value: 'quarter' }, { label: '按时间间隔监测', value: 'repeat' }],
+            weekDays: [{ label: '周一', value: 1 }, { label: '周二', value: 2 }, { label: '周三', value: 3 }, { label: '周四', value: 4 }, { label: '周五', value: 5 }, { label: '周六', value: 6 }, { label: '周日', value: 7 }]
+        }
+    },
+    mounted () {
+        this.form = this.params
+        if (!this.params.rate) {
+            this.title = '新增'
+        } else {
+            this.form = this.params
+            this.title = '修改'
+        }
+        // this.form = this.params
+    },
+    methods: {
+        handleClose () {
+            this.$emit('update:dialogVisible', false)
+        },
+        async handleConfirm () {
+            try {
+                await this.$refs.formRef.validate()
+                let rate = '每天'
+                switch (this.form.period) {
+                    case 'day':
+                        if (this.form.date.length !== 7) {
+                            this.form.date.sort((a, b) => a - b)
+                            rate = '每周' + this.form.date.join(',')
+                        }
+                        break
+                    case 'week':
+                        rate = '每周' + this.form.date
+                        break
+                    case 'month':
+                        rate = '每个月第' + this.form.date + '天'
+                        break
+                    case 'quarter':
+                        rate = '每个季度第' + this.form.date + '个月'
+                        break
+                    case 'repeat':
+                        rate = this.form.startTime + '起每隔' + this.form.date + '天'
+                        break
+                    default:
+                        break
+                }
+                this.form.rate = rate
+                this.$emit('submit', this.form, this.params.$index)
+                this.handleClose()
+            } catch (error) {
+                console.log(error)
+            }
+        },
+        periodChange () {
+            if (this.form.period === 'day') {
+                this.form.date = []
+            } else {
+                this.form.date = ''
+            }
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.contain{
+    padding: 20px;
+    .form{
+        .item{
+            width: 600px;
+        }
+    }
+}
+
+::v-deep{
+    .el-form-item__content{
+        display: flex;
+    }
+}
+</style>

+ 209 - 0
src/views/component/xcomponent/numberRange.vue

@@ -0,0 +1,209 @@
+<!--
+    author:luoaoxuan
+    subject:数字范围选择器
+-->
+<template>
+    <div>
+        <div class="input-number-range" :class="{ 'is-disabled': disabled }">
+            <div class="flex">
+                <div class="from">
+                    <el-input
+                        ref="input_from"
+                        v-model="userInputForm"
+                        size="mini"
+                        :readonly="disabled"
+                        placeholder=""
+                        @blur="handleBlurFrom"
+                        @focus="handleFocusFrom"
+                        @input="handleInputFrom"
+                        @change="handleInputChangeFrom"
+                    />
+                </div>
+                <div class="center">
+                    <span>至</span>
+                </div>
+                <div class="to">
+                    <el-input
+                        ref="input_to"
+                        v-model="userInputTo"
+                        size="mini"
+                        :readonly="disabled"
+                        placeholder=""
+                        @blur="handleBlurTo"
+                        @focus="handleFocusTo"
+                        @input="handleInputTo"
+                        @change="handleInputChangeTo"
+                    />
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'input-number-range',
+
+    props: {
+        value: {
+            required: true,
+            type: Array
+        },
+
+        // 是否禁用
+        disabled: {
+            type: Boolean,
+            default: false
+        },
+
+        // 精度参数
+        precision: {
+            type: Number,
+            default: 0,
+            validator (val) {
+                return val >= 0 && val === parseInt(val, 10)
+            }
+        }
+    },
+
+    data () {
+        return {
+            userInputForm: null,
+            userInputTo: null
+        }
+    },
+
+    watch: {
+        value: {
+            immediate: true,
+            handler (value) {
+                if (value instanceof Array && this.precision !== undefined) {
+                    this.userInputForm = typeof value[0] === 'number' ? value[0] : null
+                    this.userInputTo = typeof value[1] === 'number' ? value[1] : null
+                }
+            }
+        }
+    },
+
+    methods: {
+    // 根据精度保留数字
+        toPrecision (num, precision) {
+            if (precision === undefined) precision = 0
+            return parseFloat(
+                Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision)
+            )
+        },
+
+        handleBlurFrom (event) {
+            this.$emit('blurfrom', event)
+        },
+
+        handleFocusFrom (event) {
+            this.$emit('focusfrom', event)
+        },
+
+        handleBlurTo (event) {
+            this.$emit('blurto', event)
+        },
+
+        handleFocusTo (event) {
+            this.$emit('focusto', event)
+        },
+
+        handleInputFrom (value) {
+            this.$emit('inputfrom', value)
+            // this.userInputFrom = value
+        },
+
+        handleInputTo (value) {
+            this.$emit('inputto', value)
+            // this.userInputTo = value
+        },
+
+        // from输入框change事件
+        handleInputChangeFrom (value) {
+            // 如果是非数字空返回null
+            if (isNaN(value) || value === '') {
+                this.$emit('input', [null, this.userInputTo])
+                this.$emit('changefrom', this.userInputForm)
+                return
+            }
+
+            // 初始化数字精度
+            this.userInputForm = this.setPrecisionValue(value)
+
+            // 如果from > to 将from值替换成to
+            if (typeof this.userInputTo === 'number') {
+                this.userInputForm =
+          parseFloat(this.userInputForm) <= parseFloat(this.userInputTo)
+              ? this.userInputForm
+              : this.userInputTo
+            }
+            this.$emit('input', [this.userInputForm, this.userInputTo])
+            this.$emit('changefrom', this.userInputForm)
+        },
+
+        // to输入框change事件
+        handleInputChangeTo (value) {
+            // 如果是非数字空返回null
+            if (isNaN(value) || value === '') {
+                this.$emit('input', [this.userInputForm, null])
+                this.$emit('changefrom', this.userInputTo)
+                return
+            }
+
+            // 初始化数字精度
+            this.userInputTo = this.setPrecisionValue(value)
+
+            if (typeof this.userInputForm === 'number') {
+                this.userInputTo =
+          parseFloat(this.userInputTo) >= parseFloat(this.userInputForm)
+              ? this.userInputTo
+              : this.userInputForm
+            }
+            this.$emit('input', [this.userInputForm, this.userInputTo])
+            this.$emit('changeto', this.userInputTo)
+        },
+
+        // 设置成精度数字
+        setPrecisionValue (value) {
+            if (this.precision !== undefined) {
+                const val = this.toPrecision(value, this.precision)
+                return val
+            }
+            return null
+        }
+    }
+}
+</script>
+<style lang="scss" scoped>
+// 取消element原有的input框样式
+::v-deep .el-input--mini .el-input__inner {
+  border: 0px;
+  margin: 0;
+  padding: 0 15px;
+  background-color: transparent;
+}
+.input-number-range {
+  background-color: #fff;
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+}
+.flex {
+  display: flex;
+  flex-direction: row;
+  width: 100%;
+  justify-content: center;
+  align-items: center;
+  .center {
+    margin-top: 1px;
+  }
+}
+.is-disabled {
+    :hover{
+        background-color: #eef0f6
+    }
+  border-color: #FFFFFF;
+  cursor: not-allowed;
+}
+</style>