facilityData.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <!--
  2. author:luoaoxuan
  3. subject:设施环境通用组件
  4. -->
  5. <template>
  6. <div class="ficily-data">
  7. <el-row type="flex">
  8. <el-col style="margin:0 0 5px 0">
  9. <div class="button">
  10. <el-button v-if="!isCul" type="danger" size="mini" icon="ibps-icon-close" @click="goRemove">删除</el-button>
  11. <el-button v-if="!isCul" type="success" size="mini" icon="ibps-icon-plus" @click="goAdd">添加</el-button>
  12. </div>
  13. </el-col>
  14. </el-row>
  15. <el-row type="flex">
  16. <el-col>
  17. <el-table :data="forms" border @selection-change="handleSelectionChange">
  18. <el-table-column
  19. width="50"
  20. type="selection"
  21. />
  22. <el-table-column label="参数名称" prop="label">
  23. <template slot-scope="{row}">
  24. <el-input v-if="!readonly && !isCul" v-model="row.label" size="mini" placeholder="请输入" />
  25. <span v-else>{{ row.label|| '/' }}</span>
  26. </template>
  27. </el-table-column>
  28. <el-table-column label="参数单位" prop="unit" width="120">
  29. <template slot-scope="{row}">
  30. <el-autocomplete
  31. v-if="!readonly && !isCul"
  32. v-model="row.unit"
  33. class="inline-input"
  34. :fetch-suggestions="querySearch"
  35. placeholder="请输入"
  36. size="mini"
  37. />
  38. <span v-else>{{ row.unit || '/' }}</span>
  39. </template>
  40. </el-table-column>
  41. <el-table-column label="参数范围限值" prop="range" width="300">
  42. <template slot-scope="{row}">
  43. <NumberRange v-model="row.range" :precision="2" :disabled="readonly || isCul" /></template>
  44. </el-table-column>
  45. <el-table-column label="参数修正值" prop="fixValue" width="120">
  46. <template slot-scope="{row}">
  47. <el-input v-if="!readonly && !isCul" v-model="row.fixValue" size="mini" placeholder="请输入" type="number" />
  48. <span v-else>{{ row.fixValue|| '/' }}</span>
  49. </template>
  50. </el-table-column>
  51. <el-table-column label="填写频率" prop="rate">
  52. <template slot="header" slot-scope="">
  53. <el-tooltip class="item" effect="dark" content="配置参数填写周期,适用于参数填写频率与监测周期不一致的情况。若为空则表示该参数每次推送都需填写。" placement="top-start">
  54. <span>
  55. 填写频率
  56. <i class="el-icon-question" />
  57. </span>
  58. </el-tooltip>
  59. </template>
  60. <template slot-scope="{row,$index}">
  61. <span>{{ row.rate || '/' }}</span>
  62. <el-button v-if="!readonly && !isCul" size="mini" icon="ibps-icon-edit" type="text" style="margin-left:10px" @click="openDialog(row,$index)">编辑</el-button>
  63. </template>
  64. </el-table-column>
  65. <el-table-column v-if="isCul" label="参数值" prop="value">
  66. <template slot-scope="{row}">
  67. <el-input v-if="!readonly" v-model="row.value" size="mini" placeholder="请输入" type="number" :readonly="readonly" />
  68. <span v-else>{{ row.value || '/' }}</span>
  69. </template>
  70. </el-table-column>
  71. <el-table-column v-if="isCul" label="最终值" prop="result">
  72. <template slot-scope="{row}">
  73. <span>{{ row.result || '/' }}</span>
  74. </template>
  75. </el-table-column>
  76. <el-table-column v-if="isCul" label="状态" prop="status">
  77. <template slot-scope="{row}">
  78. <span>{{ row.status || '/' }}</span>
  79. </template>
  80. </el-table-column>
  81. </el-table>
  82. </el-col>
  83. </el-row>
  84. <FacilityDataDialog v-if="dialogShow" :dialog-visible.sync="dialogShow" :params="dialogParams" @submit="dialogSubmit" />
  85. </div>
  86. </template>
  87. <script>
  88. import NumberRange from '@/views/component/xcomponent/numberRange.vue'
  89. import FacilityDataDialog from './facilityDataDialog.vue'
  90. export default {
  91. components: {
  92. NumberRange, FacilityDataDialog
  93. },
  94. props: {
  95. formData: {
  96. type: Object,
  97. default: () => {}
  98. },
  99. readonly: {
  100. type: Boolean,
  101. default: false
  102. },
  103. isCul: {
  104. type: Boolean,
  105. default: true
  106. }
  107. },
  108. data () {
  109. return {
  110. dialogParams: {},
  111. dialogShow: false,
  112. isFirst: true,
  113. forms: [],
  114. multipleSelection: []
  115. }
  116. },
  117. computed: {
  118. },
  119. watch: {
  120. formData: {
  121. handler (val) {
  122. // console.log('formData', val)
  123. if (val.lieBiaoShuJu) {
  124. if (!this.isCul) {
  125. this.forms = this.initData(val.lieBiaoShuJu)
  126. } else {
  127. if (this.isFirst) {
  128. this.forms = this.initData(val.lieBiaoShuJu)
  129. this.isFirst = false
  130. }
  131. }
  132. }
  133. this.culXiuZheng()
  134. },
  135. deep: true,
  136. immediate: true
  137. },
  138. forms: {
  139. handler (val) {
  140. // console.log('forms', val)
  141. this.culXiuZheng()
  142. this.$emit('change-data', 'lieBiaoShuJu', JSON.stringify(val))
  143. },
  144. deep: true
  145. }
  146. },
  147. mounted () {
  148. // console.log('mounted', this.formData)
  149. },
  150. methods: {
  151. // 弹窗的提交事件
  152. dialogSubmit (data, index) {
  153. this.$set(this.forms, index, data)
  154. // console.log('form', this.forms)
  155. },
  156. openDialog (row, $index) {
  157. this.dialogParams = {
  158. ...row,
  159. $index
  160. }
  161. this.dialogShow = true
  162. },
  163. // 计算时间差
  164. getDayDifference (date1, date2) {
  165. // 将两个日期转换为Date对象
  166. const d1 = new Date(date1)
  167. const d2 = new Date(date2)
  168. // 计算两个日期之间的毫秒差
  169. const timeDiff = d2.getTime() - d1.getTime()
  170. // 将毫秒差转换为天数并返回
  171. const dayDiff = Math.ceil(timeDiff / (1000 * 3600 * 24))
  172. // console.log(dayDiff)
  173. return dayDiff
  174. },
  175. // 初始化数据
  176. initData (data) {
  177. data = data.replace(/\n/g, '')
  178. const ans = JSON.parse(data)
  179. const result = []
  180. if (this.isFirst) {
  181. console.log(ans)
  182. console.log('formData', this.formData)
  183. }
  184. ans.forEach(item => {
  185. if (!Object.hasOwn(item, 'label')) {
  186. item.label = ''
  187. }
  188. if (!Object.hasOwn(item, 'unit')) {
  189. item.unit = '℃'
  190. }
  191. if (!Object.hasOwn(item, 'range')) {
  192. item.range = [null, null]
  193. }
  194. if (!Object.hasOwn(item, 'fixValue')) {
  195. item.fixValue = ''
  196. }
  197. if (!Object.hasOwn(item, 'value')) {
  198. item.value = ''
  199. }
  200. if (!Object.hasOwn(item, 'result')) {
  201. item.result = ''
  202. }
  203. if (!Object.hasOwn(item, 'rate')) {
  204. item.rate = ''
  205. }
  206. if (!Object.hasOwn(item, 'status')) {
  207. item.status = ''
  208. }
  209. if (!Object.hasOwn(item, 'period')) {
  210. item.period = ''
  211. }
  212. if (!Object.hasOwn(item, 'date')) {
  213. item.date = ''
  214. }
  215. if (!Object.hasOwn(item, 'startTime')) {
  216. item.startTime = ''
  217. }
  218. // this.formData.jianCeShiJian = '2024-10-20' // 测试用
  219. if (!item.result && (item.rate && (this.formData.jianCeShiJian || this.readonly))) {
  220. let jianCeShiJian = ''
  221. if (this.readonly) {
  222. jianCeShiJian = this.formData.bianZhiShiJian?.slice(0, 10)
  223. } else {
  224. jianCeShiJian = this.formData.jianCeShiJian?.slice(0, 10)
  225. }
  226. const thatDate = new Date(jianCeShiJian)
  227. let day = thatDate.getDay() // 周几
  228. if (day === 0) { // 周日得到结果为0 需要特判
  229. day = 7
  230. }
  231. const dayofMonth = thatDate.getDate() // 多少号
  232. let dayDiff = ''
  233. console.log(`监测时间:${jianCeShiJian},周${day}`)
  234. switch (item.period) {
  235. case 'day':
  236. if (item.date.indexOf(day) > -1) {
  237. result.push(item)
  238. }
  239. break
  240. case 'week':
  241. if (item.date === day) {
  242. result.push(item)
  243. }
  244. break
  245. case 'month':
  246. if (item.date === dayofMonth) {
  247. result.push(item)
  248. }
  249. break
  250. case 'repeat':
  251. dayDiff = this.getDayDifference(item.startTime, jianCeShiJian)
  252. if (dayDiff >= 0 && dayDiff % (item.date + 1) === 0) {
  253. result.push(item)
  254. }
  255. break
  256. default:
  257. break
  258. }
  259. } else {
  260. result.push(item)
  261. }
  262. })
  263. return result
  264. },
  265. // 默认单位
  266. querySearch (queryString, cb) {
  267. const units = [{ value: '℃' }, { value: '%' }, { value: 'Pa' }, { value: 'MΩ·CM' }, { value: 'uS/cm' }, { value: 'cfu/ml' }]
  268. // 调用 callback 返回建议列表的数据
  269. cb(units)
  270. },
  271. // 计算状态
  272. getStatus (range, result) {
  273. let [min, max] = range
  274. if (min === null || min === '' || typeof min === 'undefined') min = Number.NEGATIVE_INFINITY
  275. if (max === null || max === '' || typeof max === 'undefined') max = Number.POSITIVE_INFINITY
  276. if (+min === 0 && +max === 0) {
  277. return '正常'
  278. }
  279. if (+result <= +max && +result >= +min) {
  280. return '正常'
  281. }
  282. return '失控'
  283. },
  284. // 计算修正值
  285. culXiuZheng () {
  286. if (!this.isCul) return
  287. if (this.readonly) return
  288. this.forms.forEach(item => {
  289. if (item.value) {
  290. if (item.fixValue) {
  291. item.result = (+item.fixValue + +item.value).toFixed(2)
  292. } else {
  293. item.result = (+item.value).toFixed(2)
  294. }
  295. item.status = this.getStatus(item.range, item.result)
  296. } else {
  297. item.result = ''
  298. item.status = ''
  299. }
  300. })
  301. },
  302. formatData (val) {
  303. return JSON.stringify(val)
  304. },
  305. goAdd () {
  306. if (this.forms.length >= 10) {
  307. return this.$message({
  308. message: '超过最大限制!',
  309. type: 'warning'
  310. })
  311. }
  312. this.forms.push({
  313. label: '',
  314. range: [],
  315. fixValue: '',
  316. value: '',
  317. result: '',
  318. status: '',
  319. unit: '',
  320. period: '',
  321. date: ''
  322. })
  323. },
  324. goRemove () {
  325. this.forms = this.forms.filter(item => !this.multipleSelection.includes(item))
  326. },
  327. handleSelectionChange (val) {
  328. this.multipleSelection = val
  329. }
  330. }
  331. }
  332. </script>
  333. <style lang="scss" scoped>
  334. .ficily-data{
  335. margin-bottom: 20px;
  336. .button{
  337. display: flex;
  338. flex-direction: row-reverse;
  339. .el-button{
  340. margin-left: 5px;
  341. }
  342. }
  343. }
  344. </style>