车间能级提升-智能设备管理系统
zhuguifei
2025-06-23 5eca16c096db71a3a419c655cdcf1326a32f01ea
eims-ui: 新增点检、保养报表
已添加11个文件
1122 ■■■■■ 文件已修改
eims-ui/apps/web-antd/src/api/eims/report/index.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/report/model.d.ts 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/insp-report/data.tsx 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/insp-report/index.vue 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/maint-report/data.tsx 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/maint-report/index.vue 213 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/ReportController.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/ReportReqBo.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsInspectReportVo.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IReportService.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/ReportServiceImpl.java 310 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/report/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
import { requestClient } from '#/api/request';
enum Api {
  insp = '/eims/report/insp',
  maint = '/eims/report/maint',
}
/**
 * æŸ¥è¯¢ç‚¹æ£€è®°å½•列表
 * @param query
 * @returns {*}
 */
export function insp(params?: any) {
  return requestClient.get<any[]>(Api.insp, { params });
}
/**
 * æŸ¥è¯¢ä¿å…»è®°å½•列表
 * @param query
 * @returns {*}
 */
export function maint(params?: any) {
  return requestClient.get<any[]>(Api.maint, { params });
}
eims-ui/apps/web-antd/src/api/eims/report/model.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,97 @@
export interface InspectRecordVO {
  /**
   * id
   */
  id: string | number;
  /**
   * è®¾å¤‡di
   */
  equId: string | number;
  /**
   * è®¾å¤‡åç§°
   */
  equName: string;
  /**
   * èµ„产编号
   */
  assteNo: string;
  /**
   * ç‚¹æ£€åç§°
   */
  inspName: string;
  /**
   * ç‚¹æ£€æè¿°
   */
  inspDesc: string;
  /**
   * çŠ¶æ€
   */
  status: string;
  /**
   * ç‚¹æ£€ç¼–码
   */
  inspCode: string;
  /**
   * å€¼è®°å½•方式(字典)
   */
  recordMode: string;
  /**
   * å‚考值
   */
  referenceValue: string;
  /**
   * ä¸Šé™
   */
  upperLimit: string;
  /**
   * ä¸‹é™
   */
  lowLimit: string;
  /**
   * æ£€æŸ¥å€¼
   */
  checkValue: string;
  /**
   * ç‚¹æ£€ç»“果(字典)
   */
  inspResult: string;
  /**
   * ç‚¹æ£€æ—¶é—´
   */
  inspTime: string;
  /**
   * è®¡åˆ’点检日期
   */
  planTime: string;
  /**
   * éªŒè¯äºº
   */
  verifyUser: number;
  /**
   * è®¡åˆ’id
   */
  planId: string | number;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
eims-ui/apps/web-antd/src/views/eims/insp-report/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
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: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'equId',
    label: '设备名称'
  },*/
  {
    component: 'Input',
    fieldName: 'keyword',
    componentProps: {
      placeholder: '请输入设备名称或资产编号'
    },
    label: '关键字'
  },
  {
    component: 'DatePicker',
    componentProps: {
      picker: 'month',
      format: 'YYYY-MM',
      valueFormat: 'YYYY-MM',
      placeholder: '请选择月份',
      allowClear: true,
      defaultValue: dayjs().format('YYYY-MM'),
      getPopupContainer: (triggerNode: HTMLElement) => triggerNode.parentNode as HTMLElement
    },
    fieldName: 'selectMonth',
    defaultValue: dayjs().format('YYYY-MM'),
    label: '月份选择'
  }
];
export const columns = ref<VxeGridProps['columns']>([
  { type: 'checkbox', width: 60, fixed: 'left' },
  {
    title: '设备名称',
    field: 'equName',
    minWidth: 200,
    fixed: 'left'
  }
]);
eims-ui/apps/web-antd/src/views/eims/insp-report/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,235 @@
<script setup lang="ts">
import { h, onMounted, ref, toRaw } from 'vue';
import { Page, type VbenFormProps } from '@vben/common-ui';
import { Space } from 'ant-design-vue';
import dayjs from 'dayjs';
import { useVbenVxeGrid, type VxeGridProps, vxeSortEvent } from '#/adapter/vxe-table';
import { insp } from '#/api/eims/report';
import { columns as dynamicColumns, querySchema } from './data';
// æ•°æ®æ˜¯å¦åˆå§‹åŒ–
const initFlag = ref(false);
const baseColumns: VxeGridProps['columns'] = [
  {
    title: '设备名称',
    field: 'equName',
    minWidth: 120,
    fixed: 'left'
  },
  {
    title: '资产编号 - æ—¥æœŸ',
    field: 'assetNo',
    minWidth: 120,
    fixed: 'left'
  }
];
initColumns();
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 () => {
    // eslint-disable-next-line no-use-before-define
    const { formApi, reload } = tableApi;
    await formApi.resetForm();
    const formValues = formApi.form.values;
    formApi.setLatestSubmissionValues(formValues);
    await reload(formValues);
    initFlag.value = false;
    initColumns(dayjs().format('YYYY-MM'), true);
  },
  // æ—¥æœŸé€‰æ‹©æ ¼å¼åŒ–
  fieldMappingTime: [['changeDate', ['params[beginTime]', 'params[endTime]'], ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59']]]
};
const gridOptions: VxeGridProps = {
  checkboxConfig: {
    // é«˜äº®
    highlight: true,
    // ç¿»é¡µæ—¶ä¿ç•™é€‰ä¸­çŠ¶æ€
    reserve: true
    // ç‚¹å‡»è¡Œé€‰ä¸­
    // trigger: 'row'
  },
  border: true,
  size: 'mini',
  columns: dynamicColumns.value,
  height: 'auto',
  keepSource: true,
  pagerConfig: {
    // é»˜è®¤æ¡æ•°
    pageSize: 20,
    // åˆ†é¡µå¯é€‰æ¡æ•°
    pageSizes: [10, 20, 30, 50, 100, 200, 300, 500]
  },
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues = {}) => {
        // TODO æš‚时解决动态修改表头后参数丢失问题
        // eslint-disable-next-line no-use-before-define
        const p = await tableApi.formApi.getValues();
        const params = toRaw(p);
        return await insp({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...params
        });;
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'inspReport'
  },
  sortConfig: {
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true
  },
  id: 'eims-report-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
onMounted(async () => {
  initListener();
  // await setupEquSelect();
});
const selMonth = ref('');
function initListener() {
  tableApi.formApi.updateSchema([
    {
      component: 'DatePicker',
      componentProps: {
        onChange: (sMonth: string) => {
          selMonth.value = sMonth;
          dynamicColumns.value = [];
          initFlag.value = false;
          initColumns(sMonth, true);
        }
      },
      fieldName: 'selectMonth'
    }
  ]);
}
function initColumns(selectMonth: string = dayjs().format('YYYY-MM'), isUpdate: boolean = false) {
  if (initFlag.value) {
    return false;
  }
  const dayNumbers = getDayNumbers(selectMonth);
  const newColumns: VxeGridProps['columns'] = dayNumbers.map((day: number) => ({
    title: `${day}`,
    field: `day_${day}`,
    width: 40,
    align: 'center',
    slots: {
      default: ({ row }) => {
        const value = row[`day_${day}`];
        let className = '';
        switch (value) {
          case '已完成': {
            className = 'dot-green';
            break;
          }
          case '待验证': {
            className = 'dot-orange';
            break;
          }
          case '未点检': {
            className = 'dot-gray';
            break;
          }
          default: {
            return '-';
          }
        }
        return h('span', { class: className });
      }
    }
    // formatter: ({ row }: { row: any }) => {
    //   return row[`day_${day}`] || '-';
    // }
  }));
  dynamicColumns.value = [...(baseColumns || []), ...newColumns];
  initFlag.value = true;
  if (isUpdate) {
    tableApi.setGridOptions({
      ...gridOptions,
      columns: dynamicColumns.value
    });
    tableApi.query();
  }
}
function getDayNumbers(yearMonth: string): number[] {
  const days = dayjs(yearMonth).daysInMonth();
  return Array.from({ length: days }).map((_, i) => i + 1);
}
</script>
<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-[8px]">
      <BasicTable class="flex-1 overflow-hidden" table-title="试产列表">
        <template #toolbar-tools>
          <Space>
            <span class="ml-4 mr-2">-</span>未生成计划 <span class="dot-gray ml-4"></span>未点检 <span class="dot-orange ml-4"></span>待验证
            <span class="dot-green ml-4"></span>已点检
          </Space>
        </template>
        <template #insp="{ row }">
          <Space>
            <span>{{ row.equName }}</span>
          </Space>
        </template>
      </BasicTable>
    </div>
  </Page>
</template>
<style lang="less" scoped>
:deep(.dot-green) {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #52c41a;
}
:deep(.dot-orange) {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #faad14;
}
:deep(.dot-gray) {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #d9d9d9;
}
</style>
eims-ui/apps/web-antd/src/views/eims/maint-report/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
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: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'equId',
    label: '设备名称'
  },*/
  {
    component: 'Input',
    fieldName: 'keyword',
    componentProps: {
      placeholder: '请输入设备名称或资产编号'
    },
    label: '关键字'
  },
  {
    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 const columns = ref<VxeGridProps['columns']>([
]);
eims-ui/apps/web-antd/src/views/eims/maint-report/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,213 @@
<script setup lang="ts">
import { h, onMounted, ref, toRaw } 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 { maint } from '#/api/eims/report';
import { columns as dynamicColumns, querySchema } from './data';
// æ•°æ®æ˜¯å¦åˆå§‹åŒ–
const initFlag = ref(false);
const baseColumns: VxeGridProps['columns'] = [
  { type: 'checkbox', width: 60, fixed: 'left' },
  {
    title: '设备名称',
    field: 'equName',
    width: 200,
    fixed: 'left'
  },
  {
    title: '资产编号',
    field: 'assetNo',
    width: 200,
    fixed: 'left'
  }
];
initColumns();
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 () => {
    // eslint-disable-next-line no-use-before-define
    const { formApi, reload } = tableApi;
    await formApi.resetForm();
    const formValues = formApi.form.values;
    formApi.setLatestSubmissionValues(formValues);
    await reload(formValues);
  }
};
const gridOptions: VxeGridProps = {
  checkboxConfig: {
    // é«˜äº®
    highlight: true,
    // ç¿»é¡µæ—¶ä¿ç•™é€‰ä¸­çŠ¶æ€
    reserve: true
    // ç‚¹å‡»è¡Œé€‰ä¸­
    // trigger: 'row'
  },
  border: true,
  size: 'mini',
  columns: dynamicColumns.value,
  height: 'auto',
  keepSource: true,
  pagerConfig: {
    // é»˜è®¤æ¡æ•°
    pageSize: 20,
    // åˆ†é¡µå¯é€‰æ¡æ•°
    pageSizes: [10, 20, 30, 50, 100, 200, 300, 500]
  },
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues = {}) => {
        // TODO æš‚时解决动态修改表头后参数丢失问题
        // eslint-disable-next-line no-use-before-define
        const p = await tableApi.formApi.getValues();
        const params = toRaw(p);
        return await maint({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...params
        });
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'maintReport'
  },
  sortConfig: {
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true
  },
  id: 'mainit-report-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
onMounted(async () => {
  initListener();
  // await setupEquSelect();
});
const selYear = ref('');
function initListener() {
  tableApi.formApi.updateSchema([
    {
      component: 'DatePicker',
      componentProps: {
        onChange: (sYear: string) => {
          selYear.value = sYear;
        }
      },
      fieldName: 'selectYear'
    }
  ]);
}
function initColumns() {
  if (initFlag.value) {
    return false;
  }
  const dayNumbers = getMonthNumbers();
  const newColumns: VxeGridProps['columns'] = dayNumbers.map((month: number) => ({
    title: `${month}月`,
    field: `month_${month}`,
    align: 'center',
    slots: {
      default: ({ row }) => {
        const value = row[`month_${month}`];
        let className = '';
        switch (value) {
          case '已完成': {
            className = 'dot-green';
            break;
          }
          case '未完成': {
            className = 'dot-orange';
            break;
          }
          default: {
            return '-';
          }
        }
        return h('span', { class: className });
      }
    }
  }));
  dynamicColumns.value = [...(baseColumns || []), ...newColumns];
  initFlag.value = true;
}
function getMonthNumbers(): number[] {
  return Array.from({ length: 12 }, (_, i) => i + 1);
}
</script>
<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-[8px]">
      <BasicTable class="flex-1 overflow-hidden" table-title="试产列表">
        <template #toolbar-tools>
          <Space>
            <span class="ml-4 mr-2">-</span>未生成计划 <span class="dot-orange ml-4"></span>未完成 <span class="dot-green ml-4"></span>已完成
          </Space>
        </template>
      </BasicTable>
    </div>
  </Page>
</template>
<style lang="less" scoped>
:deep(.dot-green) {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #52c41a;
}
:deep(.dot-orange) {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #faad14;
}
:deep(.dot-blue) {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #2a5dd8;
}
:deep(.dot-purple) {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #8a2ad8;
}
</style>
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/ReportController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
package org.dromara.eims.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import lombok.RequiredArgsConstructor;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.eims.service.IReportService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
 * ç‚¹æ£€æŠ¥è¡¨
 *
 * @author zhuguifei
 * @date
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/report")
public class ReportController extends BaseController {
    private final IReportService reportService;
    /**
     * æŸ¥è¯¢ç‚¹æ£€è®°å½•列表
     */
    @SaCheckPermission("eims:inspReport:list")
    @GetMapping("/insp")
    public TableDataInfo<Map<String,Object>> list(@RequestParam Map<String, Object> queryParams,  PageQuery pageQuery) {
        return reportService.queryPageListCustom(queryParams, pageQuery);
    }
    /**
     * æŸ¥è¯¢ä¿å…»è®°å½•列表
     */
    @SaCheckPermission("eims:maintReport:list")
    @GetMapping("/maint")
    public TableDataInfo<Map<String,Object>> maint(@RequestParam Map<String, Object> queryParams,  PageQuery pageQuery) {
        return reportService.queryMaintList(queryParams, pageQuery);
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/ReportReqBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package org.dromara.eims.domain.bo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
 * ç‚¹æ£€æŠ¥è¡¨è¯·æ±‚参数
 *
 * @author zhuguifei
 * @date
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class ReportReqBo extends BaseEntity {
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsInspectReportVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
package org.dromara.eims.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.eims.domain.EimsInspectRecord;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
 * ç‚¹æ£€æŠ¥è¡¨è§†å›¾å¯¹è±¡
 *
 * @author zhuguifei
 * @date
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class EimsInspectReportVo extends BaseEntity implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    private Integer year;
    private Integer month;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IReportService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package org.dromara.eims.service;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import java.util.Map;
/**
 * ç‚¹æ£€æŠ¥è¡¨Service接口
 *
 * @author zhuguifei
 * @date
 */
public interface IReportService {
    /**
     * åˆ†é¡µæŸ¥è¯¢ç‚¹æ£€è®°å½•列表-多表查询
     *
     * @param queryParams        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return ç‚¹æ£€è®°å½•分页列表
     */
    TableDataInfo<Map<String,Object>> queryPageListCustom(Map<String, Object> queryParams, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢ä¿å…»è®°å½•
     * @param queryParams
     * @param pageQuery
     * @return
     */
    TableDataInfo<Map<String, Object>> queryMaintList(Map<String, Object> queryParams, PageQuery pageQuery);
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/ReportServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,310 @@
package org.dromara.eims.service.impl;
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.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.eims.domain.*;
import org.dromara.eims.domain.vo.EimsEquVo;
import org.dromara.eims.mapper.*;
import org.dromara.eims.service.IReportService;
import org.dromara.system.mapper.SysDeptMapper;
import org.springframework.stereotype.Service;
import java.time.*;
import java.util.*;
import java.util.stream.Collectors;
@RequiredArgsConstructor
@Service
public class ReportServiceImpl implements IReportService {
    private static final String UNCHECKED = "未点检";
    private static final String PENDING_VERIFICATION = "待验证";
    private static final String COMPLETED = "已完成";
    private static final String NOT_APPLICABLE = "/";
    private static final String MAINT_0 = "待保养";
    private static final String MAINT_1 = "保养中";
    private static final String MAINT_2 = "待验证";
    private static final String MAINT_3 = "已完成";
    private final EimsInspectRecordMapper baseMapper;
    private final EimsInspectStMapper inspectStMapper;
    private final EimsInspectPlanMapper inspectPlanMapper;
    private final SysDeptMapper sysDeptMapper;
    private final EimsEquMapper equMapper;
    private final EimsMaintOrderMapper maintOrderMapper;
    private final EimsMaintPlanMapper maintPlanMapper;
    @Override
    public TableDataInfo<Map<String, Object>> queryPageListCustom(Map<String, Object> queryParams, PageQuery pageQuery) {
        LambdaQueryWrapper<EimsEqu> equWrapper = Wrappers.lambdaQuery();
        if (queryParams.containsKey("keyword")) {
            String keyword = (String) queryParams.get("keyword");
            equWrapper.and(StringUtils.isNotBlank(keyword),
                wrapper -> wrapper
                    .like(EimsEqu::getEquName, keyword)
                    .or()
                    .like(EimsEqu::getAssetNo, keyword)
            );
        }
        Page<EimsEquVo> equList = equMapper.selectVoPage(pageQuery.build(), equWrapper);
        return TableDataInfo.build(fitInspData(equList, queryParams));
    }
    @Override
    public TableDataInfo<Map<String, Object>> queryMaintList(Map<String, Object> queryParams, PageQuery pageQuery) {
        LambdaQueryWrapper<EimsEqu> equWrapper = Wrappers.lambdaQuery();
        if (queryParams.containsKey("keyword")) {
            String keyword = (String) queryParams.get("keyword");
            equWrapper.and(StringUtils.isNotBlank(keyword),
                wrapper -> wrapper
                    .like(EimsEqu::getEquName, keyword)
                    .or()
                    .like(EimsEqu::getAssetNo, keyword)
            );
        }
        Page<EimsEquVo> equList = equMapper.selectVoPage(pageQuery.build(), equWrapper);
        return TableDataInfo.build(fitMaintData(equList, queryParams));
    }
    private  Page<Map<String, Object>> fitMaintData(Page<EimsEquVo> equPageList, Map<String, Object> queryParams) {
        Integer selectYear = getYearFromParams(queryParams);
        LocalDate firstDay = Year.of(selectYear).atDay(1); // ç¬¬ä¸€å¤©
        LocalDate lastDay = Year.of(selectYear).atDay(Year.of(selectYear).length());
        Page<Map<String, Object>> page = new Page<>(
            equPageList.getCurrent(),
            equPageList.getSize(),
            equPageList.getTotal(),
            equPageList.searchCount()
        );
        if (equPageList.getRecords().isEmpty()) {
            return page;
        }
        List<Long> equIds = equPageList.getRecords().stream()
            .map(EimsEquVo::getEquId)
            .collect(Collectors.toList());
        Map<Long, List<EimsMaintOrder>> maintOrderMap = getMaintOrderMap(equIds, firstDay, lastDay);
        Map<Long, List<EimsMaintPlan>> maintPlanMap = getMaintPlanMap(equIds,selectYear);
        List<Map<String, Object>> resultList = equPageList.getRecords().stream()
            .map(equ -> buildMaintReport(equ, maintOrderMap, maintPlanMap))
            .collect(Collectors.toList());
        page.setRecords(resultList);
        return page;
    }
    private Page<Map<String, Object>> fitInspData(Page<EimsEquVo> equPageList, Map<String, Object> queryParams) {
        YearMonth yearMonth = getYearMonthFromParams(queryParams);
        LocalDate firstDay = yearMonth.atDay(1);
        LocalDate lastDay = yearMonth.atEndOfMonth();
        Page<Map<String, Object>> page = new Page<>(
            equPageList.getCurrent(),
            equPageList.getSize(),
            equPageList.getTotal(),
            equPageList.searchCount()
        );
        if (equPageList.getRecords().isEmpty()) {
            return page;
        }
        List<Long> equIds = equPageList.getRecords().stream()
            .map(EimsEquVo::getEquId)
            .collect(Collectors.toList());
        Map<Long, List<EimsInspectSt>> inspectStMap = getInspectStMap(equIds, firstDay, lastDay);
        Map<Long, List<EimsInspectPlan>> inspectPlanMap = getInspectPlanMap(equIds, yearMonth);
        List<Map<String, Object>> resultList = equPageList.getRecords().stream()
            .map(equ -> buildEquipmentReport(equ, inspectStMap, inspectPlanMap, yearMonth))
            .collect(Collectors.toList());
        page.setRecords(resultList);
        return page;
    }
    private YearMonth getYearMonthFromParams(Map<String, Object> queryParams) {
        if (queryParams.containsKey("selectMonth")) {
            String[] parts = queryParams.get("selectMonth").toString().split("-");
            return YearMonth.of(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]));
        }
        return YearMonth.now();
    }
    private Map<Long, List<EimsInspectSt>> getInspectStMap(List<Long> equIds, LocalDate firstDay, LocalDate lastDay) {
        LambdaQueryWrapper<EimsInspectSt> sWrapper = Wrappers.lambdaQuery();
        sWrapper.in(EimsInspectSt::getEquId, equIds)
            .between(EimsInspectSt::getPlanTime, firstDay, lastDay)
            .eq(EimsInspectSt::getType, "Day");
        return inspectStMapper.selectList(sWrapper).stream()
            .collect(Collectors.groupingBy(EimsInspectSt::getEquId));
    }
    private Map<Long, List<EimsInspectPlan>> getInspectPlanMap(List<Long> equIds, YearMonth yearMonth) {
        LocalDateTime firstDayTime = yearMonth.atDay(1).atStartOfDay();
        LocalDateTime lastDayTime = yearMonth.atEndOfMonth().atTime(23, 59, 59);
        LambdaQueryWrapper<EimsInspectPlan> pWrapper = Wrappers.lambdaQuery();
        pWrapper.in(EimsInspectPlan::getEquId, equIds)
            .between(EimsInspectPlan::getCreateTime, firstDayTime, lastDayTime);
        return inspectPlanMapper.selectList(pWrapper).stream()
            .collect(Collectors.groupingBy(EimsInspectPlan::getEquId));
    }
    private Map<String, Object> buildEquipmentReport(EimsEquVo equ,
                                                     Map<Long, List<EimsInspectSt>> inspectStMap,
                                                     Map<Long, List<EimsInspectPlan>> inspectPlanMap,
                                                     YearMonth yearMonth) {
        Map<String, Object> item = new HashMap<>();
        item.put("equName", equ.getEquName());
        item.put("assetNo", equ.getAssetNo());
        List<EimsInspectSt> equInspList = inspectStMap.getOrDefault(equ.getEquId(), Collections.emptyList());
        List<EimsInspectPlan> equPlanList = inspectPlanMap.getOrDefault(equ.getEquId(), Collections.emptyList());
        Map<String, EimsInspectSt> stMap = equInspList.stream()
            .collect(Collectors.toMap(
                inspSt -> String.valueOf(inspSt.getPlanTime().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate().getDayOfMonth()),
                inspSt -> inspSt,
                (existing, replacement) -> existing
            ));
        Map<String, EimsInspectPlan> planMap = equPlanList.stream()
            .collect(Collectors.toMap(
                inspPlan -> String.valueOf(inspPlan.getCreateTime().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate().getDayOfMonth()),
                inspPlan -> inspPlan,
                (existing, replacement) -> existing
            ));
        int daysInMonth = yearMonth.lengthOfMonth();
        for (int day = 1; day <= daysInMonth; day++) {
            String dayKey = "day_" + day;
            if (planMap.containsKey(String.valueOf(day))) {
                item.put(dayKey, UNCHECKED);
            } else if (stMap.containsKey(String.valueOf(day))) {
                EimsInspectSt st = stMap.get(String.valueOf(day));
                switch (st.getStatus()) {
                    case "0":
                        item.put(dayKey, UNCHECKED);
                        break;
                    case "1":
                        item.put(dayKey, PENDING_VERIFICATION);
                        break;
                    case "2":
                        item.put(dayKey, COMPLETED);
                        break;
                    default:
                        item.put(dayKey, NOT_APPLICABLE);
                }
            } else {
                item.put(dayKey, NOT_APPLICABLE);
            }
        }
        return item;
    }
    private Integer getYearFromParams(Map<String, Object> queryParams) {
        if (queryParams.containsKey("selectYear")) {
            String year = queryParams.get("selectYear").toString();
            return  Integer.parseInt(year);
        }
        return LocalDate.now().getYear();
    }
    private Map<Long, List<EimsMaintOrder>> getMaintOrderMap(List<Long> equIds, LocalDate firstDay, LocalDate lastDay) {
        LambdaQueryWrapper<EimsMaintOrder> sWrapper = Wrappers.lambdaQuery();
        sWrapper.in(EimsMaintOrder::getEquId, equIds)
            .between(EimsMaintOrder::getPlanTime, firstDay, lastDay);
        return maintOrderMapper.selectList(sWrapper).stream()
            .collect(Collectors.groupingBy(EimsMaintOrder::getEquId));
    }
    private Map<Long, List<EimsMaintPlan>> getMaintPlanMap(List<Long> equIds, Integer year) {
        LocalDateTime firstDay = Year.of(year).atDay(1).atStartOfDay();
        LocalDateTime lastDay = Year.of(year).atDay(Year.of(year).length())
            .atTime(23, 59, 59);
        LambdaQueryWrapper<EimsMaintPlan> pWrapper = Wrappers.lambdaQuery();
        pWrapper.in(EimsMaintPlan::getEquId, equIds)
            .between(EimsMaintPlan::getCreateTime, firstDay, lastDay);
        return maintPlanMapper.selectList(pWrapper).stream()
            .collect(Collectors.groupingBy(EimsMaintPlan::getEquId));
    }
    private Map<String, Object> buildMaintReport(EimsEquVo equ,
                                                     Map<Long, List<EimsMaintOrder>> maintOrderMap,
                                                     Map<Long, List<EimsMaintPlan>> maintPlanMap) {
        Map<String, Object> item = new HashMap<>();
        item.put("equName", equ.getEquName());
        item.put("assetNo", equ.getAssetNo());
        List<EimsMaintOrder> equMaintOrderList = maintOrderMap.getOrDefault(equ.getEquId(), Collections.emptyList());
        List<EimsMaintPlan> equMaintPlanList = maintPlanMap.getOrDefault(equ.getEquId(), Collections.emptyList());
        Map<String, String> orderMap = equMaintOrderList.stream()
            .collect(Collectors.groupingBy(
                order -> String.valueOf(order.getPlanTime().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate().getMonthValue()),
                // æŒ‰æœˆä»½åˆ†ç»„后,判断该月是否全部status=3
                Collectors.collectingAndThen(
                    Collectors.toList(),
                    orders -> orders.stream().allMatch(o -> o.getStatus().equals("3"))
                        ? "已完成"
                        : "未完成"
                )
            ));
        Map<String, EimsMaintPlan> planMap = equMaintPlanList.stream()
            .collect(Collectors.toMap(
                maintPlan -> String.valueOf(maintPlan.getCreateTime().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate().getMonthValue()),
                maintPlan -> maintPlan,
                (existing, replacement) -> existing
            ));
        int monthInYear = 12;
        for (int month = 1; month <= monthInYear; month++) {
            String monthKey = "month_" + month;
            if (planMap.containsKey(String.valueOf(month))) {
                item.put(monthKey, UNCHECKED);
            } else if (orderMap.containsKey(String.valueOf(month))) {
                String result  = orderMap.get(String.valueOf(month));
                item.put(monthKey, result);
            } else {
                item.put(monthKey, NOT_APPLICABLE);
            }
        }
        return item;
    }
}