facilityData.vue 13 KB

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