index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. <script setup>
  2. import { RecordDrawer } from '@/views/report/components';
  3. import { getHomeCounts, getDailyTable, getDeviceList } from '@/api/report/lab';
  4. import { dayjs } from 'element-plus';
  5. const drawerVisible = ref(false);
  6. const tableLoading = ref(false);
  7. const total = ref(0);
  8. const selectOptions = ref({});
  9. const tableData = ref([]);
  10. const drawerData = ref({});
  11. const currentDateTime = ref('');
  12. const categoryOptions = [
  13. { label: '全部', value: '' },
  14. { label: '化验室设备', value: 1 },
  15. { label: '连续检测设备', value: 2 },
  16. ]
  17. const deviceNameEnum = {
  18. "0": "待机中",
  19. "1": "离线中",
  20. "2": "化验中"
  21. }
  22. const pageCountNums = ref({
  23. deviceTotals: 0,
  24. onDeviceCounts: 0,
  25. standbyDeviceCounts: 0,
  26. offDeviceCounts: 0,
  27. passAssayRates: 0,
  28. assayTotals: 0,
  29. passAssayTotals: 0
  30. });
  31. const queryParams = ref({
  32. assayStatus: '',
  33. assayDate: dayjs().format("YYYY-MM-DD"),
  34. deviceNo: '',
  35. type: '',
  36. pageNum: 1,
  37. pageSize: 10
  38. });
  39. const getDeviceClass = ({ assayStatus: key }) => {
  40. const colorEnum = {
  41. "0": "bg-[#FADB14]",
  42. "1": "bg-[#F5222D]",
  43. "2": "bg-[#52c41a]"
  44. }
  45. const color = colorEnum[key]
  46. return 'block w-[8px] h-[8px] rounded-full ' + color;
  47. }
  48. const initPageData = async () => {
  49. tableLoading.value = true;
  50. const { total: pageTotal, rows } = await getDailyTable(queryParams.value);
  51. total.value = pageTotal;
  52. tableData.value = rows.map(item => ({
  53. ...item,
  54. currentTemperature: item.currentTemperature ? item.currentTemperature + '°' : '',
  55. wasteLiquidAmounts: item.wasteLiquidAmounts ? item.wasteLiquidAmounts + 'L' : '',
  56. }));
  57. tableLoading.value = false;
  58. }
  59. const handleDatePickerChange = () => {
  60. queryParams.value.pageNum = 1;
  61. queryParams.value.pageSize = 10;
  62. initPageData();
  63. }
  64. const handleSelectChange = () => {
  65. queryParams.value.pageNum = 1;
  66. queryParams.value.pageSize = 10;
  67. initPageData();
  68. }
  69. const handleRadioChange = () => {
  70. queryParams.value.pageNum = 1;
  71. queryParams.value.pageSize = 10;
  72. initPageData();
  73. }
  74. // table btn 化验记录
  75. const handleTableBtnClick = async (row) => {
  76. const { deviceNo, deviceName, worksName, type } = row;
  77. const currentDate = queryParams.value.assayDate;
  78. drawerData.value = {
  79. deviceName, deviceNo, worksName, currentDate, type
  80. }
  81. drawerVisible.value = true;
  82. }
  83. // 设备类型变化
  84. const reloadPageData = async (type) => {
  85. queryParams.value.type = type || '';
  86. queryParams.value.deviceNo = '';
  87. queryParams.value.pageNum = 1;
  88. queryParams.value.pageSize = 10;
  89. const { data } = await getHomeCounts({type: queryParams.value.type});
  90. pageCountNums.value = {
  91. ...data,
  92. passAssayRates: data.passAssayRates ? Number(data.passAssayRates?.slice(0, -1)) : 0
  93. };
  94. initPageData();
  95. }
  96. onMounted( async () => {
  97. const { data: deviceData } = await getDeviceList({ type: queryParams.value.type });
  98. selectOptions.value = deviceData;
  99. reloadPageData();
  100. currentDateTime.value = dayjs(new Date()).format('YYYY-MM-DD hh:mm:ss');
  101. })
  102. </script>
  103. <template>
  104. <main>
  105. <div class="lab-day-viewport space-y-[10px]">
  106. <el-card shadow="never" :body-style="{ border: '0px' }">
  107. <template #header>
  108. <p class="space-x-[10px]">
  109. <span class="font-bold">今日数据概览</span>
  110. <span class="text-[#999]">统计时间 {{ currentDateTime }}</span>
  111. </p>
  112. </template>
  113. <el-row class="pt-[5px]" justify="space-between" :gutter="20">
  114. <el-col :span="4">
  115. <el-statistic :value="pageCountNums.deviceTotals">
  116. <template #title>
  117. <p class="flex items-center space-x-[4px]">
  118. <el-icon :size="14" color="#2454ff"><Management /></el-icon>
  119. <span>全国设备总数(台)</span>
  120. </p>
  121. </template>
  122. </el-statistic>
  123. </el-col>
  124. <el-col :span="4">
  125. <el-statistic :value="pageCountNums.onDeviceCounts">
  126. <template #title>
  127. <p class="flex items-center space-x-[4px]">
  128. <el-icon :size="14" color="#00bd28"><Checked /></el-icon>
  129. <span>今日化验中设备(台)</span>
  130. </p>
  131. </template>
  132. </el-statistic>
  133. </el-col>
  134. <el-col :span="4">
  135. <el-statistic title="今日待机设备(台)" :value="pageCountNums.standbyDeviceCounts">
  136. <template #title>
  137. <p class="flex items-center space-x-[4px]">
  138. <el-icon :size="14" color="#e5a528"><List /></el-icon>
  139. <span>今日待机设备(台)</span>
  140. </p>
  141. </template>
  142. </el-statistic>
  143. </el-col>
  144. <el-col :span="4">
  145. <el-statistic title="今日离线设备(台)" :value="pageCountNums.offDeviceCounts">
  146. <template #title>
  147. <p class="flex items-center space-x-[4px]">
  148. <el-icon :size="14" color="#e31518"><TrendCharts /></el-icon>
  149. <span>今日离线设备(台)</span>
  150. </p>
  151. </template>
  152. </el-statistic>
  153. </el-col>
  154. <el-col :span="4">
  155. <el-statistic title="今日质控样合格率" :value="pageCountNums.passAssayRates">
  156. <template #title>
  157. <p class="flex items-center space-x-[4px]">
  158. <el-icon :size="14" color="#8C40FF"><Histogram /></el-icon>
  159. <span>今日质控样合格率</span>
  160. </p>
  161. </template>
  162. <template #suffix>
  163. <el-popover
  164. effect="dark"
  165. placement="top-start"
  166. :width="200"
  167. trigger="hover"
  168. >
  169. <template #reference>
  170. <p>
  171. <span class="text-[14px]">%</span>
  172. <el-icon style="margin-left: 4px" :size="14">
  173. <Warning />
  174. </el-icon>
  175. </p>
  176. </template>
  177. <ul>
  178. <li class="space-x-[4px]">
  179. <span class="text-[12px]">今日质控样检测总数</span>
  180. <span class="font-bold text-[14px]"> {{ pageCountNums.assayTotals || 0 }} </span>
  181. <span class="text-[12px]">次</span>
  182. </li>
  183. <li class="space-x-[4px]">
  184. <span class="text-[12px]">今日质控样合格总数</span>
  185. <span class="font-bold text-[14px]"> {{ pageCountNums.passAssayTotals || 0 }} </span>
  186. <span class="text-[12px]">次</span>
  187. </li>
  188. </ul>
  189. </el-popover>
  190. </template>
  191. </el-statistic>
  192. </el-col>
  193. </el-row>
  194. </el-card>
  195. <el-card shadow="never" :body-style="{ padding: '20px' }">
  196. <div class="flex justify-between items-center mb-[10px]">
  197. <el-radio-group v-model="queryParams.assayStatus" @change="handleRadioChange">
  198. <el-radio-button label="全部设备" value="" />
  199. <el-radio-button label="待机中" value="0" />
  200. <el-radio-button label="离线中" value="1" />
  201. <el-radio-button label="化验中" value="2" />
  202. </el-radio-group>
  203. <div class="flex space-x-[20px]">
  204. <el-select
  205. placeholder="选择设备类型"
  206. v-model="queryParams.type"
  207. @change="reloadPageData"
  208. :empty-values="[null, undefined]"
  209. :value-on-clear="null"
  210. >
  211. <el-option
  212. v-for="item in categoryOptions"
  213. :key="item.value"
  214. :label="item.label"
  215. :value="item.value"
  216. />
  217. </el-select>
  218. <el-select
  219. placeholder="选择设备"
  220. clearable
  221. filterable
  222. v-model="queryParams.deviceNo"
  223. @change="handleSelectChange"
  224. >
  225. <el-option
  226. v-for="item in selectOptions"
  227. :key="item.deviceNo"
  228. :label="item.deviceName"
  229. :value="item.deviceNo"
  230. />
  231. </el-select>
  232. <el-date-picker
  233. type="date"
  234. :clearable="false"
  235. v-model="queryParams.assayDate"
  236. value-format="YYYY-MM-DD"
  237. placeholder="选择日期"
  238. @change="handleDatePickerChange"
  239. style="width: 400px;"
  240. />
  241. </div>
  242. </div>
  243. <el-table :data="tableData" style="width: 100%" v-loading="tableLoading">
  244. <el-table-column prop="deviceName" label="设备名称" width="180" fixed/>
  245. <el-table-column prop="deviceNo" label="设备编号" width="180" />
  246. <el-table-column prop="worksName" label="所属水厂" width="180"/>
  247. <el-table-column prop="assayStatus" label="当前设备状态" width="180">
  248. <template #default="{ row }">
  249. <p class="flex items-center space-x-[8px]">
  250. <span :class="getDeviceClass(row)"></span>
  251. <span>{{ deviceNameEnum[row.assayStatus] }}</span>
  252. </p>
  253. </template>
  254. </el-table-column>
  255. <el-table-column prop="lastAssayTime" label="最近一次化验时间" width="180"/>
  256. <el-table-column prop="beginAssayTime" label="化验开始时间" width="180"/>
  257. <el-table-column prop="assayProgress" label="化验进度" width="180">
  258. <template #default="{ row }">
  259. <el-progress :percentage="row.assayProgress || 0" />
  260. </template>
  261. </el-table-column>
  262. <el-table-column prop="assayCounts" label="检测轮次" width="180"/>
  263. <el-table-column prop="assayTotals" label="检测总次数" width="180"/>
  264. <el-table-column prop="passAssayRates" label="合格率(质控样)" width="180" />
  265. <el-table-column prop="currentTemperature" label="当前温度" width="180"/>
  266. <el-table-column prop="currentHumidity" label="当前湿度" width="180"/>
  267. <el-table-column prop="wasteLiquidAmounts" label="废液产生总量" width="180"/>
  268. <el-table-column prop="address" label="操作" fixed="right">
  269. <template #default="{ row }">
  270. <el-button link type="primary" size="small" @click="handleTableBtnClick(row)">化验记录</el-button>
  271. </template>
  272. </el-table-column>
  273. </el-table>
  274. <div class="">
  275. <pagination
  276. v-show="total > 0"
  277. :total="total"
  278. v-model:page="queryParams.pageNum"
  279. v-model:limit="queryParams.pageSize"
  280. @pagination="initPageData"
  281. />
  282. </div>
  283. </el-card>
  284. </div>
  285. <RecordDrawer v-model:show="drawerVisible" :data="drawerData"></RecordDrawer>
  286. </main>
  287. </template>
  288. <style lang="scss">
  289. .lab-day-viewport {
  290. font-size: 14px;
  291. .el-statistic__number {
  292. font-size: 22px;
  293. font-family: D-DIN-PRO-700-Bold;
  294. }
  295. }
  296. </style>