feat(report): 新增设备稼动率统计功能
- 在 ReportController 中添加 equEfficiency 接口
- 在 IReportService 中添加 queryEquEfficiencyList 方法
- 在 ReportServiceImpl 中实现 queryEquEfficiencyList 方法
- 在 EimsInspectStMapper 中添加 statEquEfficiency 查询
- 更新前端 API定义,添加 getEquEfficiency 方法
- 新增设备稼动率统计页面和相关组件
| | |
| | | import { requestClient } from '#/api/request'; |
| | | |
| | | enum Api { |
| | | equEfficiency = '/eims/report/equEfficiency', |
| | | insp = '/eims/report/insp', |
| | | maint = '/eims/report/maint', |
| | | } |
| | |
| | | return requestClient.get<any[]>(Api.maint, { params }); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢è®¾å¤ç¨¼å¨çå表 |
| | | */ |
| | | export function getEquEfficiency() { |
| | | return requestClient.get<any[]>(Api.equEfficiency); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { VxeGridProps } from '#/adapter/vxe-table'; |
| | | import { ref } from 'vue'; |
| | | import dayjs from 'dayjs'; |
| | | import { type FormSchemaGetter } from '#/adapter/form'; |
| | | |
| | | export const querySchema: FormSchemaGetter = () => [ |
| | | { |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | picker: 'year', |
| | | format: 'YYYY', |
| | | valueFormat: 'YYYY', |
| | | placeholder: 'è¯·éæ©å¹´ä»½', |
| | | allowClear: true, |
| | | defaultValue: dayjs().format('YYYY'), |
| | | getPopupContainer: (triggerNode: HTMLElement) => triggerNode.parentNode as HTMLElement |
| | | }, |
| | | fieldName: 'selectYear', |
| | | defaultValue: dayjs().format('YYYY'), |
| | | label: '年份鿩' |
| | | } |
| | | ]; |
| | | |
| | | export function getEfficiencyColumns() { |
| | | const months = Array.from({ length: 12 }, (_, i) => `${i + 1}æ`); |
| | | const columns: VxeGridProps['columns'] = [ |
| | | { title: '项ç®', field: 'item', width: 160, fixed: 'left' }, |
| | | ...months.map(month => ({ title: month, field: month, align: 'center' as const })), |
| | | { title: 'å
¨å¹´å计', field: 'total', align: 'center' as const } |
| | | ]; |
| | | return columns; |
| | | } |
| | | |
| | | export const columns = ref<VxeGridProps['columns']>(getEfficiencyColumns()); |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <script setup lang="ts"> |
| | | import { onMounted, ref, toRaw, computed } from 'vue'; |
| | | |
| | | import { Page, type VbenFormProps } from '@vben/common-ui'; |
| | | |
| | | import { Space } from 'ant-design-vue'; |
| | | |
| | | import { useVbenVxeGrid, type VxeGridProps, vxeSortEvent } from '#/adapter/vxe-table'; |
| | | import { getEquEfficiency } from '#/api/eims/report'; |
| | | |
| | | import { columns, querySchema } from './data'; |
| | | |
| | | const selYear = ref(''); |
| | | |
| | | const formOptions: VbenFormProps = { |
| | | commonConfig: { |
| | | labelWidth: 80, |
| | | componentProps: { |
| | | allowClear: true |
| | | } |
| | | }, |
| | | schema: querySchema(), |
| | | wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4', |
| | | handleReset: async () => { |
| | | const { formApi, reload } = tableApi; |
| | | await formApi.resetForm(); |
| | | const formValues = formApi.form.values; |
| | | formApi.setLatestSubmissionValues(formValues); |
| | | await reload(formValues); |
| | | } |
| | | }; |
| | | |
| | | const gridOptions: VxeGridProps = { |
| | | border: true, |
| | | size: 'mini', |
| | | columns: columns.value, |
| | | height: 'auto', |
| | | keepSource: true, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async (_ctx, formValues = {}) => { |
| | | const params = toRaw(formValues); |
| | | return await getEquEfficiency(params); |
| | | } |
| | | } |
| | | }, |
| | | rowConfig: { |
| | | isHover: true, |
| | | keyField: 'item' |
| | | }, |
| | | id: 'equ-efficency-index' |
| | | }; |
| | | |
| | | const [BasicTable, tableApi] = useVbenVxeGrid({ |
| | | formOptions, |
| | | gridOptions, |
| | | gridEvents: { |
| | | sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams) |
| | | } |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | tableApi.formApi.updateSchema([ |
| | | { |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | onChange: (sYear: string) => { |
| | | selYear.value = sYear; |
| | | } |
| | | }, |
| | | fieldName: 'selectYear' |
| | | } |
| | | ]); |
| | | // åå§å年份 |
| | | selYear.value = tableApi.formApi.form.values.selectYear; |
| | | }); |
| | | |
| | | const tableTitle = computed(() => `${selYear.value || new Date().getFullYear()}å¹´çäº§è®¾å¤æ£å¸¸è¿è½¬ç`); |
| | | </script> |
| | | |
| | | <template> |
| | | <Page :auto-content-height="true"> |
| | | <div class="flex h-full gap-[8px]"> |
| | | <BasicTable class="flex-1 overflow-hidden" :table-title="tableTitle"> |
| | | <template #toolbar-tools> |
| | | <Space> |
| | | <span class="ml-4 mr-2">稼å¨ç = (æ»è¿è¡æ¶é´-åæºæ¶é´) ÷ æ»è¿è¡æ¶é´ à 100%</span> |
| | | </Space> |
| | | </template> |
| | | </BasicTable> |
| | | </div> |
| | | </Page> |
| | | </template> |
| | |
| | | pageNum: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...params |
| | | });; |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | |
| | | return reportService.queryMaintList(queryParams, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢è®¾å¤ç¨¼å¨çç»è®¡å表 |
| | | */ |
| | | @SaCheckPermission("eims:equEfficiency:list") |
| | | @GetMapping("/equEfficiency") |
| | | public TableDataInfo<Map<String,Object>> equEfficiency(@RequestParam Map<String, Object> queryParams, PageQuery pageQuery) { |
| | | return reportService.queryEquEfficiencyList(queryParams, pageQuery); |
| | | } |
| | | |
| | | } |
| | |
| | | planBoQueryWrapper.eq("ip.status", DictConstants.SYS_NORMAL_DISABLE_DETAIL.NORMAL) |
| | | .eq("equ.status", DictConstants.EIMS_EQU_STATUS_DETAIL.SHIYONG); |
| | | // å¢å è¿æ»¤æ¡ä»¶ 䏿¬¡çææ¥æå°äºå½åæ¥æ |
| | | planBoQueryWrapper.and(wrapper -> wrapper.lt("ip.insp_next_time", DateUtils.getDate()).or().isNull("ip.insp_next_time")); |
| | | planBoQueryWrapper.and(wrapper -> wrapper.le("ip.insp_next_time", DateUtils.getDate()).or().isNull("ip.insp_next_time")); |
| | | // // è¿æ»¤æ²¡æä¸æ¬¡è¿è¡æ¶é´ |
| | | // planBoQueryWrapper.isNotNull(EimsInspectPlan::getInspNextTime); |
| | | // // è¿æ»¤æ²¡æç¹æ£å¨æçæ°æ® |
| | |
| | | import com.baomidou.mybatisplus.core.toolkit.Constants; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.apache.ibatis.annotations.Select; |
| | | import org.dromara.eims.domain.EimsInspectSt; |
| | | import org.dromara.eims.domain.EimsMaintSt; |
| | | import org.dromara.eims.domain.vo.EimsInspectStVo; |
| | | import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; |
| | | import org.dromara.eims.domain.vo.EimsMaintStVo; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * ç¹æ£æ±æ»Mapperæ¥å£ |
| | |
| | | public interface EimsInspectStMapper extends BaseMapperPlus<EimsInspectSt, EimsInspectStVo> { |
| | | Page<EimsInspectStVo> selectInspStList(@Param("page") Page<EimsInspectStVo> page, @Param(Constants.WRAPPER) Wrapper<EimsInspectSt> queryWrapper); |
| | | |
| | | @Select({ |
| | | "<script>", |
| | | "SELECT", |
| | | " MONTH(plan_time) AS month,", |
| | | " SUM(run_times) AS runTimes,", |
| | | " SUM(fault_times) AS faultTimes", |
| | | "FROM eims_inspect_st", |
| | | "WHERE plan_time BETWEEN #{start} AND #{end}", |
| | | " AND type = 'Day'", |
| | | "GROUP BY MONTH(plan_time)", |
| | | "</script>" |
| | | }) |
| | | List<Map<String, Object>> statEquEfficiency(@Param("start") String start, @Param("end") String end); |
| | | } |
| | |
| | | * @return |
| | | */ |
| | | TableDataInfo<Map<String, Object>> queryMaintList(Map<String, Object> queryParams, PageQuery pageQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢è®¾å¤ç¨¼å¨çç»è®¡ |
| | | * @param queryParams |
| | | * @param pageQuery |
| | | * @return |
| | | */ |
| | | TableDataInfo<Map<String, Object>> queryEquEfficiencyList(Map<String, Object> queryParams, PageQuery pageQuery); |
| | | } |
| | |
| | | package org.dromara.eims.service.impl; |
| | | |
| | | import cn.hutool.core.date.DateUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.dromara.common.core.utils.DateUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.mybatis.core.page.PageQuery; |
| | | import org.dromara.common.mybatis.core.page.TableDataInfo; |
| | |
| | | |
| | | return item; |
| | | } |
| | | |
| | | @Override |
| | | public TableDataInfo<Map<String, Object>> queryEquEfficiencyList(Map<String, Object> queryParams, PageQuery pageQuery) { |
| | | Integer selectYear = getYearFromParams(queryParams); |
| | | String start = Year.of(selectYear).atDay(1).toString(); // yyyy-MM-dd |
| | | String end = Year.of(selectYear).atDay(Year.of(selectYear).length()).toString(); |
| | | |
| | | List<Map<String, Object>> statList = inspectStMapper.statEquEfficiency(start, end); |
| | | |
| | | // ç»è£
ç»è®¡ç»æ |
| | | Map<Integer, Integer> runTimes = new HashMap<>(); |
| | | Map<Integer, Integer> faultTimes = new HashMap<>(); |
| | | Map<Integer, Integer> totalTimes = new HashMap<>(); |
| | | int runTotal = 0, faultTotal = 0, totalTotal = 0; |
| | | |
| | | for (Map<String, Object> row : statList) { |
| | | int month = Integer.parseInt(row.get("month").toString()); |
| | | int run = row.get("runTimes") == null ? 0 : Integer.parseInt(row.get("runTimes").toString()); |
| | | int fault = row.get("faultTimes") == null ? 0 : Integer.parseInt(row.get("faultTimes").toString()); |
| | | int total = run + fault; |
| | | runTimes.put(month, run); |
| | | faultTimes.put(month, fault); |
| | | totalTimes.put(month, total); |
| | | runTotal += run; |
| | | faultTotal += fault; |
| | | totalTotal += total; |
| | | } |
| | | |
| | | // ç»è£
è¿åæ°æ®ï¼ååï¼ |
| | | String targetValue = "98.00%"; |
| | | List<Map<String, Object>> resultList = new ArrayList<>(); |
| | | Map<String, Object> row1 = new LinkedHashMap<>(); // æ£å¸¸è¿è½¬æ¶é´ |
| | | Map<String, Object> row2 = new LinkedHashMap<>(); // æ»è¿è½¬æ¶é´ |
| | | Map<String, Object> row3 = new LinkedHashMap<>(); // æ
éæ¶é´ |
| | | Map<String, Object> row4 = new LinkedHashMap<>(); // ç®æ å¼ |
| | | Map<String, Object> row5 = new LinkedHashMap<>(); // æ£å¸¸è¿è½¬çï¼ç¨¼å¨çï¼ |
| | | |
| | | row1.put("item", "æ£å¸¸è¿è½¬æ¶é´"); |
| | | row2.put("item", "æ»è¿è½¬æ¶é´"); |
| | | row3.put("item", "æ
éæ¶é´"); |
| | | row4.put("item", "ç®æ å¼"); |
| | | row5.put("item", "æ£å¸¸è¿è½¬çï¼ç¨¼å¨çï¼"); |
| | | |
| | | for (int m = 1; m <= 12; m++) { |
| | | row1.put(m + "æ", runTimes.getOrDefault(m, 0)); |
| | | row2.put(m + "æ", totalTimes.getOrDefault(m, 0)); |
| | | row3.put(m + "æ", faultTimes.getOrDefault(m, 0)); |
| | | row4.put(m + "æ", targetValue); |
| | | int run = runTimes.getOrDefault(m, 0); |
| | | int total = totalTimes.getOrDefault(m, 0); |
| | | String eff = total > 0 ? String.format("%.2f%%", run * 100.0 / total) : "-"; |
| | | row5.put(m + "æ", eff); |
| | | } |
| | | row1.put("total", runTotal); |
| | | row2.put("total", totalTotal); |
| | | row3.put("total", faultTotal); |
| | | row4.put("total", targetValue); |
| | | row5.put("total", totalTotal > 0 ? String.format("%.2f%%", runTotal * 100.0 / totalTotal) : "-"); |
| | | |
| | | resultList.add(row1); |
| | | resultList.add(row2); |
| | | resultList.add(row3); |
| | | resultList.add(row4); |
| | | resultList.add(row5); |
| | | |
| | | return TableDataInfo.build(resultList); |
| | | } |
| | | } |