facilityData.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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. const ans = JSON.parse(data)
  178. const result = []
  179. if (this.isFirst) {
  180. console.log(ans)
  181. }
  182. ans.forEach(item => {
  183. if (!Object.hasOwn(item, 'label')) {
  184. item.label = ''
  185. }
  186. if (!Object.hasOwn(item, 'unit')) {
  187. item.unit = '℃'
  188. }
  189. if (!Object.hasOwn(item, 'range')) {
  190. item.range = [null, null]
  191. }
  192. if (!Object.hasOwn(item, 'fixValue')) {
  193. item.fixValue = ''
  194. }
  195. if (!Object.hasOwn(item, 'value')) {
  196. item.value = ''
  197. }
  198. if (!Object.hasOwn(item, 'result')) {
  199. item.result = ''
  200. }
  201. if (!Object.hasOwn(item, 'rate')) {
  202. item.rate = ''
  203. }
  204. if (!Object.hasOwn(item, 'status')) {
  205. item.status = ''
  206. }
  207. if (!Object.hasOwn(item, 'period')) {
  208. item.period = ''
  209. }
  210. if (!Object.hasOwn(item, 'date')) {
  211. item.date = ''
  212. }
  213. if (!Object.hasOwn(item, 'startTime')) {
  214. item.startTime = ''
  215. }
  216. // this.formData.jianCeShiJian = '2024-10-20' // 测试用
  217. if (item.rate && this.formData.jianCeShiJian) {
  218. const jianCeShiJian = this.formData.jianCeShiJian.slice(0, 10)
  219. const thatDate = new Date(jianCeShiJian)
  220. let day = thatDate.getDay() // 周几
  221. if (day === 0) { // 周日得到结果为0 需要特判
  222. day = 7
  223. }
  224. const dayofMonth = thatDate.getDate() // 多少号
  225. let dayDiff = ''
  226. console.log(`监测时间:${jianCeShiJian},周${day}`)
  227. switch (item.period) {
  228. case 'day':
  229. if (item.date.indexOf(day) > -1) {
  230. result.push(item)
  231. }
  232. break
  233. case 'week':
  234. if (item.date === day) {
  235. result.push(item)
  236. }
  237. break
  238. case 'month':
  239. if (item.date === dayofMonth) {
  240. result.push(item)
  241. }
  242. break
  243. case 'repeat':
  244. dayDiff = this.getDayDifference(item.startTime, jianCeShiJian)
  245. if (dayDiff >= 0 && dayDiff % (item.date + 1) === 0) {
  246. result.push(item)
  247. }
  248. break
  249. default:
  250. break
  251. }
  252. } else {
  253. result.push(item)
  254. }
  255. })
  256. return result
  257. },
  258. // 默认单位
  259. querySearch (queryString, cb) {
  260. const units = [{ value: '℃' }, { value: '%' }, { value: 'Pa' }, { value: 'MΩ·CM' }, { value: 'uS/cm' }, { value: 'cfu/ml' }]
  261. // 调用 callback 返回建议列表的数据
  262. cb(units)
  263. },
  264. // 计算状态
  265. getStatus (range, result) {
  266. let [min, max] = range
  267. if (min === null || min === '' || typeof min === 'undefined') min = Number.NEGATIVE_INFINITY
  268. if (max === null || max === '' || typeof max === 'undefined') max = Number.POSITIVE_INFINITY
  269. if (+min === 0 && +max === 0) {
  270. return '正常'
  271. }
  272. if (+result <= +max && +result >= +min) {
  273. return '正常'
  274. }
  275. return '失控'
  276. },
  277. // 计算修正值
  278. culXiuZheng () {
  279. if (!this.isCul) return
  280. if (this.readonly) return
  281. this.forms.forEach(item => {
  282. if (item.value) {
  283. if (item.fixValue) {
  284. item.result = (+item.fixValue + +item.value).toFixed(2)
  285. } else {
  286. item.result = (+item.value).toFixed(2)
  287. }
  288. item.status = this.getStatus(item.range, item.result)
  289. } else {
  290. item.result = ''
  291. item.status = ''
  292. }
  293. })
  294. },
  295. formatData (val) {
  296. return JSON.stringify(val)
  297. },
  298. goAdd () {
  299. if (this.forms.length >= 10) {
  300. return this.$message({
  301. message: '超过最大限制!',
  302. type: 'warning'
  303. })
  304. }
  305. this.forms.push({
  306. label: '',
  307. range: [],
  308. fixValue: '',
  309. value: '',
  310. result: '',
  311. status: '',
  312. unit: '',
  313. period: '',
  314. date: ''
  315. })
  316. },
  317. goRemove () {
  318. this.forms = this.forms.filter(item => !this.multipleSelection.includes(item))
  319. },
  320. handleSelectionChange (val) {
  321. this.multipleSelection = val
  322. }
  323. }
  324. }
  325. </script>
  326. <style lang="scss" scoped>
  327. .ficily-data{
  328. margin-bottom: 20px;
  329. .button{
  330. display: flex;
  331. flex-direction: row-reverse;
  332. .el-button{
  333. margin-left: 5px;
  334. }
  335. }
  336. }
  337. </style>