Ver código fonte

Merge remote-tracking branch 'origin/master'

wuhb 6 meses atrás
pai
commit
72ccf90995

+ 64 - 76
ygtx-admin/src/main/java/com/ygtx/web/controller/system/SysLoginController.java

@@ -148,9 +148,11 @@ public class SysLoginController
             loginUser.setPermissions(permissions);
             tokenService.refreshToken(loginUser);
         }
+        int postType = postService.getHomePostType(user.getUserId());
         AjaxResult ajax = AjaxResult.success();
         ajax.put("user", user);
         ajax.put("roles", roles);
+        ajax.put("postType", postType);
         ajax.put("permissions", permissions);
         ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
         ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
@@ -167,12 +169,8 @@ public class SysLoginController
     {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUser user = loginUser.getUser();
-        List<Long> postIds = postService.selectPostListByUserId(user.getUserId());
-        SysPost post = null;
-        if (!postIds.isEmpty()) {
-            post = postService.selectPostById(postIds.get(0));
-        }
-        List<Map<String, Object>> highUse = operLogService.selectOperLogCountByOperName(user.getUserName(),post);
+        int postType = postService.getHomePostType(user.getUserId());
+        List<Map<String, Object>> highUse = operLogService.selectOperLogCountByOperName(user.getUserName(),postType);
         AjaxResult ajax = AjaxResult.success();
         ajax.put("highUse", highUse);
         return ajax;
@@ -188,12 +186,8 @@ public class SysLoginController
     {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUser user = loginUser.getUser();
-        List<Long> postIds = postService.selectPostListByUserId(user.getUserId());
-        SysPost post = null;
-        if (!postIds.isEmpty()) {
-            post = postService.selectPostById(postIds.get(0));
-        }
-        List<Map<String, Object>> dataList = menuService.getDataList(post);
+        int postType = postService.getHomePostType(user.getUserId());
+        List<Map<String, Object>> dataList = menuService.getDataList(postType);
         AjaxResult ajax = AjaxResult.success();
         ajax.put("statistics", dataList);
         return ajax;
@@ -209,11 +203,7 @@ public class SysLoginController
     {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUser user = loginUser.getUser();
-        List<Long> postIds = postService.selectPostListByUserId(user.getUserId());
-        SysPost post = null;
-        if (!postIds.isEmpty()) {
-            post = postService.selectPostById(postIds.get(0));
-        }
+        int postType = postService.getHomePostType(user.getUserId());
         // 工时分类统计
         List<Map<String, Object>> hourStatistics = null;
         // 班组成员工分分布
@@ -230,65 +220,63 @@ public class SysLoginController
         List<Map<String, Object>> userPointStatistics = null;
         // 扣分工单反馈列表
         List<Map<String, Object>> deductionPointStatistics = null;
-        if (post!=null) {
-            if (post.getPostName().contains("主任")) {
-                hourStatistics = new ArrayList<>();
-                hourStatistics.add(operLogService.createDataMap("工单总工时","3240"));
-                hourStatistics.add(operLogService.createDataMap("接单工时","450"));
-                hourStatistics.add(operLogService.createDataMap("准备工时","680"));
-                hourStatistics.add(operLogService.createDataMap("施工工时","1750"));
-                hourStatistics.add(operLogService.createDataMap("验收工时","360"));
-                classPointStatistics = new ArrayList<>();
-                classPointStatistics.add(operLogService.createDataMap("一班","1250"));
-                classPointStatistics.add(operLogService.createDataMap("二班","1180"));
-                classPointStatistics.add(operLogService.createDataMap("三班","1320"));
-                classPointStatistics.add(operLogService.createDataMap("四班","980"));
-                classPointStatistics.add(operLogService.createDataMap("五班","1450"));
-                classPointStatistics.add(operLogService.createDataMap("六班","1050"));
-                classPointStatistics.add(operLogService.createDataMap("七班","1280"));
-                classPointStatistics.add(operLogService.createDataMap("八班","1120"));
-            } else if (post.getPostName().contains("班长")) {
-                overTimeStatistics = new ArrayList<>();
-                overTimeStatistics.add(operLogService.createDataMap("一月","3"));
-                overTimeStatistics.add(operLogService.createDataMap("二月","2"));
-                overTimeStatistics.add(operLogService.createDataMap("三月","1"));
-                overTimeStatistics.add(operLogService.createDataMap("四月","4"));
-                overTimeStatistics.add(operLogService.createDataMap("五月","2"));
-                overTimeStatistics.add(operLogService.createDataMap("六月","1"));
-                pepolePointStatistics = new ArrayList<>();
-                pepolePointStatistics.add(operLogService.createDataMap("张三","185"));
-                pepolePointStatistics.add(operLogService.createDataMap("李四","210"));
-                pepolePointStatistics.add(operLogService.createDataMap("王五","165"));
-                pepolePointStatistics.add(operLogService.createDataMap("赵六","230"));
-                pepolePointStatistics.add(operLogService.createDataMap("钱七","195"));
-                pepolePointStatistics.add(operLogService.createDataMap("孙八","205"));
-                faultStatistics = new ArrayList<>();
-                faultStatistics.add(operLogService.createDataMap("1月","35"));
-                faultStatistics.add(operLogService.createDataMap("2月","32"));
-                faultStatistics.add(operLogService.createDataMap("3月","40"));
-                faultStatistics.add(operLogService.createDataMap("4月","38"));
-                faultStatistics.add(operLogService.createDataMap("5月","45"));
-                faultStatistics.add(operLogService.createDataMap("6月","50"));
-            } else {
-                userOrderStatistics = new ArrayList<>();
-                userOrderStatistics.add(operLogService.createDataMap("已完成","10"));
-                userOrderStatistics.add(operLogService.createDataMap("进行中","1"));
-                userOrderStatistics.add(operLogService.createDataMap("待处理","0"));
-                userPointStatistics = new ArrayList<>();
-                userPointStatistics.add(operLogService.createDataMap("1月","30"));
-                userPointStatistics.add(operLogService.createDataMap("2月","35"));
-                userPointStatistics.add(operLogService.createDataMap("3月","25"));
-                userPointStatistics.add(operLogService.createDataMap("4月","40"));
-                userPointStatistics.add(operLogService.createDataMap("5月","35"));
-                userPointStatistics.add(operLogService.createDataMap("6月","45"));
-                deductionPointStatistics = new ArrayList<>();
-                Map<String, Object> map = new HashMap<>();
-                map.put("code","WO-2023-0567");
-                map.put("deductionPoint",-10);
-                map.put("remark", "未按规定流程操作");
-                map.put("status", "0");
-                deductionPointStatistics.add(map);
-            }
+        if (postType==2) {
+            hourStatistics = new ArrayList<>();
+            hourStatistics.add(operLogService.createDataMap("工单总工时","3240"));
+            hourStatistics.add(operLogService.createDataMap("接单工时","450"));
+            hourStatistics.add(operLogService.createDataMap("准备工时","680"));
+            hourStatistics.add(operLogService.createDataMap("施工工时","1750"));
+            hourStatistics.add(operLogService.createDataMap("验收工时","360"));
+            classPointStatistics = new ArrayList<>();
+            classPointStatistics.add(operLogService.createDataMap("一班","1250"));
+            classPointStatistics.add(operLogService.createDataMap("二班","1180"));
+            classPointStatistics.add(operLogService.createDataMap("三班","1320"));
+            classPointStatistics.add(operLogService.createDataMap("四班","980"));
+            classPointStatistics.add(operLogService.createDataMap("五班","1450"));
+            classPointStatistics.add(operLogService.createDataMap("六班","1050"));
+            classPointStatistics.add(operLogService.createDataMap("七班","1280"));
+            classPointStatistics.add(operLogService.createDataMap("八班","1120"));
+        } else if (postType==1) {
+            overTimeStatistics = new ArrayList<>();
+            overTimeStatistics.add(operLogService.createDataMap("一月","3"));
+            overTimeStatistics.add(operLogService.createDataMap("二月","2"));
+            overTimeStatistics.add(operLogService.createDataMap("三月","1"));
+            overTimeStatistics.add(operLogService.createDataMap("四月","4"));
+            overTimeStatistics.add(operLogService.createDataMap("五月","2"));
+            overTimeStatistics.add(operLogService.createDataMap("六月","1"));
+            pepolePointStatistics = new ArrayList<>();
+            pepolePointStatistics.add(operLogService.createDataMap("张三","185"));
+            pepolePointStatistics.add(operLogService.createDataMap("李四","210"));
+            pepolePointStatistics.add(operLogService.createDataMap("王五","165"));
+            pepolePointStatistics.add(operLogService.createDataMap("赵六","230"));
+            pepolePointStatistics.add(operLogService.createDataMap("钱七","195"));
+            pepolePointStatistics.add(operLogService.createDataMap("孙八","205"));
+            faultStatistics = new ArrayList<>();
+            faultStatistics.add(operLogService.createDataMap("1月","35"));
+            faultStatistics.add(operLogService.createDataMap("2月","32"));
+            faultStatistics.add(operLogService.createDataMap("3月","40"));
+            faultStatistics.add(operLogService.createDataMap("4月","38"));
+            faultStatistics.add(operLogService.createDataMap("5月","45"));
+            faultStatistics.add(operLogService.createDataMap("6月","50"));
+        } else {
+            userOrderStatistics = new ArrayList<>();
+            userOrderStatistics.add(operLogService.createDataMap("已完成","10"));
+            userOrderStatistics.add(operLogService.createDataMap("进行中","1"));
+            userOrderStatistics.add(operLogService.createDataMap("待处理","0"));
+            userPointStatistics = new ArrayList<>();
+            userPointStatistics.add(operLogService.createDataMap("1月","30"));
+            userPointStatistics.add(operLogService.createDataMap("2月","35"));
+            userPointStatistics.add(operLogService.createDataMap("3月","25"));
+            userPointStatistics.add(operLogService.createDataMap("4月","40"));
+            userPointStatistics.add(operLogService.createDataMap("5月","35"));
+            userPointStatistics.add(operLogService.createDataMap("6月","45"));
+            deductionPointStatistics = new ArrayList<>();
+            Map<String, Object> map = new HashMap<>();
+            map.put("code","WO-2023-0567");
+            map.put("deductionPoint",-10);
+            map.put("remark", "未按规定流程操作");
+            map.put("status", "0");
+            deductionPointStatistics.add(map);
         }
         AjaxResult ajax = AjaxResult.success();
         ajax.put("hourStatistics", hourStatistics);

+ 1 - 1
ygtx-system/src/main/java/com/ygtx/system/service/ISysMenuService.java

@@ -144,5 +144,5 @@ public interface ISysMenuService
      */
     public boolean checkMenuNameUnique(SysMenu menu);
 
-    public List<Map<String, Object>> getDataList(SysPost post);
+    public List<Map<String, Object>> getDataList(int postType);
 }

+ 1 - 1
ygtx-system/src/main/java/com/ygtx/system/service/ISysOperLogService.java

@@ -54,7 +54,7 @@ public interface ISysOperLogService
      * @param operName 操作人员名称
      * @return 结果
      */
-    public List<Map<String, Object>> selectOperLogCountByOperName(String operName, SysPost post);
+    public List<Map<String, Object>> selectOperLogCountByOperName(String operName, int postType);
 
     public Map<String, Object> createDataMap(String key, String value);
 }

+ 2 - 0
ygtx-system/src/main/java/com/ygtx/system/service/ISysPostService.java

@@ -96,4 +96,6 @@ public interface ISysPostService
      * @return 结果
      */
     public int updatePost(SysPost post);
+
+    public int getHomePostType(Long userId);
 }

+ 21 - 21
ygtx-system/src/main/java/com/ygtx/system/service/impl/SysMenuServiceImpl.java

@@ -537,29 +537,29 @@ public class SysMenuServiceImpl implements ISysMenuService
                 new String[] { "", "", "", "/", "/" });
     }
 
-    public List<Map<String, Object>> getDataList(SysPost post){
+    public List<Map<String, Object>> getDataList(int postType){
         List<Map<String, Object>> result = new ArrayList<>();
-        if (post.getPostName().contains("主任")) {
-            result.add(createMenu("计划工单总数", "128", "+12% 较上月", "up", "fas fa-calendar-check", "blue"));
-            result.add(createMenu("非计划工单总数", "45", "+8% 较上月", "down", "fas fa-exclamation-triangle", "orange"));
-            result.add(createMenu("总工时", "3240", "+5% 较上月", "same", "fas fa-clock", "gray"));
-            result.add(createMenu("平均工单完成率", "92%", "+3% 较上月", "up", "fas fa-line-chart", "green"));
-            result.add(createMenu("扣分工单数量", "12", "-2% 较上月", "down", "fas fa-minus-circle", "red"));
-            result.add(createMenu("班组总数", "8", "0 较上月", "same", "fas fa-users", "cyan"));
-        } else if (post.getPostName().contains("班长")) {
-            result.add(createMenu("年度计划工单", "36", "+5% 较上月", "up", "fas fa-calendar", "blue"));
-            result.add(createMenu("年度非计划工单", "12", "+2% 较上月", "up", "fas fa-calendar-times", "orange"));
-            result.add(createMenu("月度计划工单", "3", "0% 较上月", "same", "fas fa-calendar-check", "green"));
-            result.add(createMenu("月度非计划工单", "1", "-1 较上月", "down", "fas fa-exclamation-triangle", "red"));
-            result.add(createMenu("当日计划工单", "0", "0 较上月", "same", "fas fa-calendar-plus", "gray"));
-            result.add(createMenu("当日非计划工单", "0", "0 较上月", "same", "fas fa-exclamation-circle", "cyan"));
+        if (postType==2) {
+            result.add(createMenu("计划工单总数", "128", "+12% 较上月", "up", "fa fa-calendar-check-o", "blue"));
+            result.add(createMenu("非计划工单总数", "45", "+8% 较上月", "down", "fa fa-exclamation-triangle", "orange"));
+            result.add(createMenu("总工时", "3240", "+5% 较上月", "same", "fa fa-clock-o", "gray"));
+            result.add(createMenu("平均工单完成率", "92%", "+3% 较上月", "up", "fa fa-line-chart", "green"));
+            result.add(createMenu("扣分工单数量", "12", "-2% 较上月", "down", "fa fa-minus-circle", "red"));
+            result.add(createMenu("班组总数", "8", "0 较上月", "same", "fa fa-users", "cyan"));
+        } else if (postType==1) {
+            result.add(createMenu("年度计划工单", "36", "+5% 较上月", "up", "fa fa-calendar", "blue"));
+            result.add(createMenu("年度非计划工单", "12", "+2% 较上月", "up", "fa fa-calendar-times-o", "orange"));
+            result.add(createMenu("月度计划工单", "3", "0% 较上月", "same", "fa fa-calendar-check-o", "green"));
+            result.add(createMenu("月度非计划工单", "1", "-1 较上月", "down", "fa fa-exclamation-triangle", "red"));
+            result.add(createMenu("当日计划工单", "0", "0 较上月", "same", "fa fa-calendar-plus-o", "gray"));
+            result.add(createMenu("当日非计划工单", "0", "0 较上月", "same", "fa fa-exclamation-circle", "cyan"));
         } else {
-            result.add(createMenu("年度计划工单", "8", "+2 较上月", "up", "fas fa-calendar", "blue"));
-            result.add(createMenu("年度非计划工单", "3", "+1 较上月", "up", "fas fa-exclamation-triangle", "orange"));
-            result.add(createMenu("月度计划工单", "1", "0 较上月", "same", "fas fa-calendar-check", "green"));
-            result.add(createMenu("月度非计划工单", "0", "0 较上月", "same", "fas fa-exclamation-circle", "red"));
-            result.add(createMenu("当前工分", "210", "+15 较上月", "up", "fas fa-star", "cyan"));
-            result.add(createMenu("扣分工单数", "1", "0 较上月", "same", "fas fa-minus-circle", "gray"));
+            result.add(createMenu("年度计划工单", "8", "+2 较上月", "up", "fa fa-calendar", "blue"));
+            result.add(createMenu("年度非计划工单", "3", "+1 较上月", "up", "fa fa-exclamation-triangle", "orange"));
+            result.add(createMenu("月度计划工单", "1", "0 较上月", "same", "fa fa-calendar-check-o", "green"));
+            result.add(createMenu("月度非计划工单", "0", "0 较上月", "same", "fa fa-exclamation-circle", "red"));
+            result.add(createMenu("当前工分", "210", "+15 较上月", "up", "fa fa-star", "cyan"));
+            result.add(createMenu("扣分工单数", "1", "0 较上月", "same", "fa fa-minus-circle", "gray"));
         }
         return result;
     }

+ 16 - 16
ygtx-system/src/main/java/com/ygtx/system/service/impl/SysOperLogServiceImpl.java

@@ -65,14 +65,14 @@ public class SysOperLogServiceImpl implements ISysOperLogService
      * @return 结果
      */
     @Override
-    public List<Map<String, Object>> selectOperLogCountByOperName(String operName, SysPost post)
+    public List<Map<String, Object>> selectOperLogCountByOperName(String operName, int postType)
     {
         List<Map<String, Object>> wbzr = new ArrayList<>();
-        wbzr.add(createMenu("工单管理", "fas fa-tasks", "blue"));
-        wbzr.add(createMenu("班组管理", "fas fa-users", "cyan"));
-        wbzr.add(createMenu("工分管理", "fas fa-star", "orange"));
-        wbzr.add(createMenu("工时分析", "fas fa-clock", "gray"));
-        wbzr.add(createMenu("通知中心", "fas fa-bell", "red"));
+        wbzr.add(createMenu("工单管理", "fa fa-tasks", "blue"));
+        wbzr.add(createMenu("班组管理", "fa fa-users", "cyan"));
+        wbzr.add(createMenu("工分管理", "fa fa-star", "orange"));
+        wbzr.add(createMenu("工时分析", "fa fa-clock-o", "gray"));
+        wbzr.add(createMenu("通知中心", "fa fa-bell", "red"));
         List<Map<String, Object>> result = operLogMapper.selectOperLogCountByOperName(operName);
         if (!result.isEmpty()) {
             for (int i=0;i<result.size();i++) {
@@ -82,19 +82,19 @@ public class SysOperLogServiceImpl implements ISysOperLogService
         }
         if (result.size()<5) {
             List<Map<String, Object>> zz = new ArrayList<>();
-            zz.add(createMenu("工单分配", "fas fa-tasks", "blue"));
-            zz.add(createMenu("组员管理", "fas fa-user", "cyan"));
-            zz.add(createMenu("工分管理", "fas fa-star", "orange"));
-            zz.add(createMenu("超时工单", "fas fa-exclamation-circle", "red"));
+            zz.add(createMenu("工单分配", "fa fa-tasks", "blue"));
+            zz.add(createMenu("组员管理", "fa fa-user", "cyan"));
+            zz.add(createMenu("工分管理", "fa fa-star", "orange"));
+            zz.add(createMenu("超时工单", "fa fa-exclamation-circle", "red"));
             List<Map<String, Object>> yg = new ArrayList<>();
-            yg.add(createMenu("我的工单", "fas fa-tasks", "blue"));
-            yg.add(createMenu("我的工分", "fas fa-star", "orange"));
-            yg.add(createMenu("扣分工单", "fas fa-minus-circle", "red"));
-            yg.add(createMenu("历史记录", "fas fa-history", "gray"));
+            yg.add(createMenu("我的工单", "fa fa-tasks", "blue"));
+            yg.add(createMenu("我的工分", "fa fa-star", "orange"));
+            yg.add(createMenu("扣分工单", "fa fa-minus-circle", "red"));
+            yg.add(createMenu("历史记录", "fa fa-history", "gray"));
             List<Map<String, Object>> highUse = new ArrayList<>();
-            if (post.getPostName().contains("主任")) {
+            if (postType==2) {
                 highUse.addAll(wbzr);
-            } else if (post.getPostName().contains("班长")) {
+            } else if (postType==1) {
                 highUse.addAll(zz);
             } else {
                 highUse.addAll(yg);

+ 27 - 0
ygtx-system/src/main/java/com/ygtx/system/service/impl/SysPostServiceImpl.java

@@ -175,4 +175,31 @@ public class SysPostServiceImpl implements ISysPostService
     {
         return postMapper.updatePost(post);
     }
+
+    /**
+     * 返回主页类型,0:普通员工,1:班长,2:主任
+     * @param userId
+     * @return
+     */
+    @Override
+    public int getHomePostType(Long userId) {
+        List<Long> postIds = selectPostListByUserId(userId);
+        int result = 0;
+        if (!postIds.isEmpty()) {
+            for (Long postId:postIds) {
+                SysPost post = selectPostById(postId);
+                if (post!=null) {
+                    if (post.getPostName().contains("主任")) {
+                        result = 2;
+                        break;
+                    } else if (post.getPostName().contains("班长")) {
+                        if (result<1) {
+                            result = 1;
+                        }
+                    }
+                }
+            }
+        }
+        return result;
+    }
 }

+ 10 - 1260
ygtx-ui/src/components/Dashboard/ChartDisplay.vue

@@ -1,1272 +1,22 @@
 <template>
   <div class="chart-display">
-    <el-row :gutter="20">
-      <!-- 工时分类统计柱状图 -->
-      <el-col :span="12" v-if="showBarChart">
-        <div class="chart-container floating-card">
-          <div ref="barChart" class="chart"></div>
-        </div>
-      </el-col>
-      <!-- 班组成员工分分布饼图 -->
-      <el-col :span="12" v-if="showPieChart">
-        <div class="chart-container floating-card">
-          <div ref="pieChart" class="chart"></div>
-        </div>
-      </el-col>
-      
-      <!-- 新增的五个图表 -->
-      <!-- 超时工单情况的柱状图 -->
-      <el-col :span="12" v-if="showOvertimeChart">
-        <div class="chart-container floating-card">
-          <div ref="overtimeChart" class="chart"></div>
-        </div>
-      </el-col>
-      
-      <!-- 班组成员工分情况的横向柱状图 -->
-      <el-col :span="12" v-if="showTeamPointsChart">
-        <div class="chart-container floating-card">
-          <div ref="teamPointsChart" class="chart"></div>
-        </div>
-      </el-col>
-      
-      <!-- 平均设备故障复发时间(MTF)的曲线图 -->
-      <el-col :span="24" v-if="showMtfChart">
-        <div class="chart-container floating-card">
-          <div ref="mtfChart" class="chart"></div>
-        </div>
-      </el-col>
-      
-      <!-- 个人工单完成情况的空心饼图 -->
-      <el-col :span="12" v-if="showPersonalWorkOrderChart">
-        <div class="chart-container floating-card">
-          <div ref="personalWorkOrderChart" class="chart"></div>
-        </div>
-      </el-col>
-      
-      <!-- 个人工分统计的曲线图 -->
-      <el-col :span="12" v-if="showPersonalPointsChart">
-        <div class="chart-container floating-card">
-          <div ref="personalPointsChart" class="chart"></div>
-        </div>
-      </el-col>
-    </el-row>
+    <ChartsGroupOne />
+    <ChartsGroupTwo />
+    <ChartsGroupThree />
   </div>
 </template>
 
 <script>
-import * as echarts from 'echarts';
-import '@fortawesome/fontawesome-free/css/all.min.css';
-import { getChartData } from '@/api/system/dashboard';
+import ChartsGroupOne from './ChartsGroupOne.vue';
+import ChartsGroupTwo from './ChartsGroupTwo.vue';
+import ChartsGroupThree from './ChartsGroupThree.vue';
 
 export default {
   name: 'ChartDisplay',
-  data() {
-    return {
-      barChart: null,
-      pieChart: null,
-      overtimeChart: null,
-      teamPointsChart: null,
-      mtfChart: null,
-      personalWorkOrderChart: null,
-      personalPointsChart: null,
-      showBarChart: true, // 控制工时分类统计图表的显示
-      showPieChart: true, // 控制班组成员工分分布饼图的显示
-      showOvertimeChart: true, // 控制超时工单情况图表的显示
-      showTeamPointsChart: true, // 控制班组成员工分情况图表的显示
-      showMtfChart: true, // 控制MTF曲线图的显示
-      showPersonalWorkOrderChart: true, // 控制个人工单完成情况图表的显示
-      showPersonalPointsChart: true, // 控制个人工分统计图表的显示
-      // 添加默认数据
-      defaultTeamPointsData: {
-        names: ['张三', '李四', '王五', '赵六', '钱七'],
-        values: [165, 142, 178, 156, 132]
-      }
-    }
-  },
-  mounted() {
-    this.initCharts()
-    this.updateCharts()
-  },
-  beforeDestroy() {
-    // 销毁所有图表实例
-    const charts = [this.barChart, this.pieChart, this.overtimeChart, this.teamPointsChart, this.mtfChart, this.personalWorkOrderChart, this.personalPointsChart];
-    charts.forEach(chart => {
-      if (chart) {
-        chart.dispose();
-      }
-    });
-  },
-  methods: {
-    // 初始化图表
-    initCharts() {
-      this.barChart = echarts.init(this.$refs.barChart)
-      this.pieChart = echarts.init(this.$refs.pieChart)
-      this.overtimeChart = echarts.init(this.$refs.overtimeChart)
-      this.teamPointsChart = echarts.init(this.$refs.teamPointsChart)
-      this.mtfChart = echarts.init(this.$refs.mtfChart)
-      this.personalWorkOrderChart = echarts.init(this.$refs.personalWorkOrderChart)
-      this.personalPointsChart = echarts.init(this.$refs.personalPointsChart)
-      
-      // 监听窗口大小变化,自适应图表
-      window.addEventListener('resize', this.resizeCharts)
-      
-      // 获取图表数据
-      this.fetchChartData();
-    },
-    
-    // 获取图表数据
-    async fetchChartData() {
-      try {
-        const response = await getChartData();
-        
-        // 处理工时分类统计数据
-        if (response && response.hourStatistics) {
-          // 更新工时分类统计图表
-          this.updateBarChart(response.hourStatistics);
-        } else {
-          // 如果没有获取到数据,隐藏图表
-          this.showBarChart = false;
-          // 销毁图表实例
-          if (this.barChart) {
-            this.barChart.dispose();
-            this.barChart = null;
-          }
-        }
-        
-        // 处理班组成员工分分布饼图数据
-        if (response && response.classPointStatistics) {
-          // 更新班组成员工分分布饼图
-          this.updatePieChart(response.classPointStatistics);
-        } else {
-          // 如果没有获取到数据,隐藏图表
-          this.showPieChart = false;
-          // 销毁图表实例
-          if (this.pieChart) {
-            this.pieChart.dispose();
-            this.pieChart = null;
-          }
-        }
-        
-        // 处理班组成员工分情况数据
-        if (response && response.pepolePointStatistics) {
-          // 更新班组成员工分情况图表
-          this.updateTeamPointsChart(response.pepolePointStatistics);
-        } else {
-          // 如果没有获取到数据,隐藏图表
-          this.showTeamPointsChart = false;
-          // 销毁图表实例
-          if (this.teamPointsChart) {
-            this.teamPointsChart.dispose();
-            this.teamPointsChart = null;
-          }
-        }
-        
-        // 处理超时工单情况数据
-        if (response && response.overTimeStatistics) {
-          // 更新超时工单情况图表
-          this.updateOvertimeChart(response.overTimeStatistics);
-        } else {
-          // 如果没有获取到数据,隐藏图表
-          this.showOvertimeChart = false;
-          // 销毁图表实例
-          if (this.overtimeChart) {
-            this.overtimeChart.dispose();
-            this.overtimeChart = null;
-          }
-        }
-        
-        // 处理平均设备故障复发时间(MTF)数据
-        if (response && response.faultStatistics) {
-          // 更新MTF曲线图
-          this.updateMtfChart(response.faultStatistics);
-        } else {
-          // 如果没有获取到数据,隐藏图表
-          this.showMtfChart = false;
-          // 销毁图表实例
-          if (this.mtfChart) {
-            this.mtfChart.dispose();
-            this.mtfChart = null;
-          }
-        }
-        
-        // 处理个人工单完成情况数据
-        if (response && response.userOrderStatistics) {
-          // 更新个人工单完成情况图表
-          this.updatePersonalWorkOrderChart(response.userOrderStatistics);
-        } else {
-          // 如果没有获取到数据,隐藏图表
-          this.showPersonalWorkOrderChart = false;
-          // 销毁图表实例
-          if (this.personalWorkOrderChart) {
-            this.personalWorkOrderChart.dispose();
-            this.personalWorkOrderChart = null;
-          }
-        }
-        
-        // 处理个人工分统计数据
-        if (response && response.userPointStatistics) {
-          // 更新个人工分统计图表
-          this.updatePersonalPointsChart(response.userPointStatistics);
-        } else {
-          // 如果没有获取到数据,隐藏图表
-          this.showPersonalPointsChart = false;
-          // 销毁图表实例
-          if (this.personalPointsChart) {
-            this.personalPointsChart.dispose();
-            this.personalPointsChart = null;
-          }
-        }
-      } catch (error) {
-        console.error('获取图表数据失败:', error);
-        // 出错时隐藏图表
-        this.showBarChart = false;
-        this.showPieChart = false;
-        this.showTeamPointsChart = false;
-        this.showOvertimeChart = false;
-        this.showMtfChart = false;
-        this.showPersonalWorkOrderChart = false;
-        this.showPersonalPointsChart = false;
-        // 销毁图表实例
-        if (this.barChart) {
-          this.barChart.dispose();
-          this.barChart = null;
-        }
-        if (this.pieChart) {
-          this.pieChart.dispose();
-          this.pieChart = null;
-        }
-        if (this.teamPointsChart) {
-          this.teamPointsChart.dispose();
-          this.teamPointsChart = null;
-        }
-        if (this.overtimeChart) {
-          this.overtimeChart.dispose();
-          this.overtimeChart = null;
-        }
-        if (this.mtfChart) {
-          this.mtfChart.dispose();
-          this.mtfChart = null;
-        }
-        if (this.personalWorkOrderChart) {
-          this.personalWorkOrderChart.dispose();
-          this.personalWorkOrderChart = null;
-        }
-        if (this.personalPointsChart) {
-          this.personalPointsChart.dispose();
-          this.personalPointsChart = null;
-        }
-      }
-    },
-    
-    // 计算轴的最大值和间隔的新方法
-    calculateAxisRange(maxValue) {
-      // 数据中的最大值除以5
-      const dividedValue = maxValue / 5;
-      
-      // 预定义的数组
-      const presetValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 70, 100, 150, 200, 250, 300, 500, 700, 1000, 2000, 5000];
-      
-      // 获取第一个大于dividedValue的值
-      let selectedValue = presetValues[presetValues.length - 1]; // 默认取最大值
-      for (let i = 0; i < presetValues.length; i++) {
-        if (presetValues[i] >= dividedValue) {
-          selectedValue = presetValues[i];
-          break;
-        }
-      }
-      
-      // 乘以5作为最终的最大值
-      const maxAxisValue = selectedValue * 5;
-      
-      // 计算间隔
-      const interval = selectedValue;
-      
-      return { maxAxisValue, interval };
-    },
-    
-    // 更新班组成员工分分布饼图
-    updatePieChart(classPointStatistics) {
-      // 处理后台传回的数据格式 [{"key":"一班","value":"1250"}]
-      let data = [];
-      
-      if (classPointStatistics && Array.isArray(classPointStatistics) && classPointStatistics.length > 0) {
-        // 从后台数据中提取班组名称和工分值
-        data = classPointStatistics.map(item => ({
-          name: item.key,
-          value: parseInt(item.value) || 0
-        }));
-        // 显示图表
-        this.showPieChart = true;
-      } else {
-        // 隐藏图表
-        this.showPieChart = false;
-        // 销毁图表实例
-        if (this.pieChart) {
-          this.pieChart.dispose();
-          this.pieChart = null;
-        }
-        return;
-      }
-      
-      // 定义前八个固定颜色
-      const fixedColors = [
-        'rgba(22, 93, 255, 0.7)',
-        'rgba(54, 207, 201, 0.7)',
-        'rgba(82, 196, 26, 0.7)',
-        'rgba(250, 173, 20, 0.7)',
-        'rgba(255, 77, 79, 0.7)',
-        'rgba(153, 102, 255, 0.7)',
-        'rgba(255, 159, 64, 0.7)',
-        'rgba(231, 233, 237, 0.7)'
-      ];
-      
-      // 班组成员工分分布的实心饼图
-      const pieOption = {
-        title: {
-          text: '班组成员工分分布',
-          left: 'left',
-          top: 'top'
-        },
-        tooltip: {
-          show: true,
-          trigger: 'item',
-          padding: [1, 5],
-          backgroundColor: 'rgba(0, 0, 0, 0.7)',
-          borderColor: 'rgba(0, 0, 0, 0.7)',
-          textStyle: {
-            color: '#fff'
-          },
-          formatter: function(params) {
-            return `
-              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
-              <div style="display: flex; align-items: center; font-size:12px;">
-                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
-                <span >${params.value}</span>
-              </div>
-            `;
-          },
-        },
-        legend: {
-          orient: 'vertical',
-          left: 'right',
-          top: 'bottom',
-        },
-        series: [
-          {
-            name: '工分',
-            label: {
-              show: false
-            },
-            labelLine: {
-              show: false
-            },
-            type: 'pie',
-            radius: '85%', // 实心饼图
-            center: ['50%', '55%'],
-            data: data.map((item, index) => ({
-              name: item.name,
-              value: item.value,
-              itemStyle: { 
-                color: index < 8 ? fixedColors[index] : `rgba(${Math.floor(Math.random() * 200 + 55)}, ${Math.floor(Math.random() * 200 + 55)}, ${Math.floor(Math.random() * 200 + 55)}, 0.7)` 
-              }
-            })),
-            emphasis: {
-              scale: false,
-            }
-          }
-        ]
-      }
-      
-      // 初始化图表实例(如果还没有)
-      if (!this.pieChart) {
-        this.pieChart = echarts.init(this.$refs.pieChart);
-      }
-      
-      // 设置班组成员工分分布饼图配置
-      this.pieChart.setOption(pieOption, true);
-    },
-    
-    // 更新工时分类统计图表
-    updateBarChart(hourStatistics) {
-      // 处理后台传回的数据格式 [{"key":"工单总工时","value":"3240"}]
-      let names = [];
-      let values = [];
-      
-      if (hourStatistics && Array.isArray(hourStatistics) && hourStatistics.length > 0) {
-        // 从后台数据中提取工时类型和工时数
-        names = hourStatistics.map(item => item.key);
-        values = hourStatistics.map(item => parseInt(item.value) || 0);
-        // 显示图表
-        this.showBarChart = true;
-      } else {
-        // 隐藏图表
-        this.showBarChart = false;
-        // 销毁图表实例
-        if (this.barChart) {
-          this.barChart.dispose();
-          this.barChart = null;
-        }
-        return;
-      }
-      
-      // 使用新的计算方法
-      const maxValue = Math.max(...values, 5); // 至少显示到5
-      const { maxAxisValue, interval } = this.calculateAxisRange(maxValue);
-      
-      // 工时分类统计的柱状图
-      const barOption = {
-        title: {
-          text: '工时分类统计',
-          left: 'left',
-          top: 'top'
-        },
-        grid: {
-          left: '2%',   // 左边距 5%
-          right: '2%',  // 右边距 5%
-          top: '20%',   // 上边距(根据需求调整)
-          bottom: '5%', // 下边距(根据需求调整)
-          containLabel: true, // 确保标签在 grid 区域内
-        },
-        tooltip: {
-          show: true,
-          trigger: 'item',
-          padding: [1, 5],
-          backgroundColor: 'rgba(0, 0, 0, 0.7)',
-          borderColor: 'rgba(0, 0, 0, 0.7)',
-          textStyle: {
-            color: '#fff'
-          },
-          formatter: function(params) {
-            return `
-              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
-              <div style="display: flex; align-items: center; font-size:12px;">
-                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
-                <span>工时数:</span>
-                <span style="margin-left: 4px;">${params.value}</span>
-              </div>
-            `;
-          },
-          position: 'top',
-        },
-        xAxis: {
-          type: 'category',
-          data: names, // 工时类型
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        yAxis: {
-          type: 'value',
-          min: 0,
-          max: maxAxisValue,
-          interval: interval,
-          axisLabel: {
-            formatter: '{value}'
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        series: [
-          {
-            data: values, // 工时数
-            type: 'bar',
-            label: {
-              show: false,
-            },
-            barWidth: '70%',
-            itemStyle: {
-              borderRadius: [5, 5, 0, 0],
-              color: function(params) {
-                const colors = [
-                  'rgba(22, 93, 255, 0.7)',
-                  'rgba(54, 207, 201, 0.7)',
-                  'rgba(82, 196, 26, 0.7)',
-                  'rgba(250, 173, 20, 0.7)',
-                  'rgba(255, 77, 79, 0.7)'
-                ];
-                return colors[params.dataIndex] || 'rgba(22, 93, 255, 0.7)';
-              }
-            }
-          }
-        ]
-      }
-      
-      // 初始化图表实例(如果还没有)
-      if (!this.barChart) {
-        this.barChart = echarts.init(this.$refs.barChart);
-      }
-      
-      // 设置工时分类统计图表配置
-      this.barChart.setOption(barOption, true);
-    },
-    
-    // 更新个人工单完成情况图表
-    updatePersonalWorkOrderChart(userOrderStatistics) {
-      // 处理后台传回的数据格式 [{"key":"已完成","value":"45"}]
-      let data = [];
-      
-      if (userOrderStatistics && Array.isArray(userOrderStatistics) && userOrderStatistics.length > 0) {
-        // 从后台数据中提取状态和数量
-        data = userOrderStatistics.map(item => ({
-          name: item.key,
-          value: parseInt(item.value) || 0
-        }));
-        // 显示图表
-        this.showPersonalWorkOrderChart = true;
-      } else {
-        // 隐藏图表
-        this.showPersonalWorkOrderChart = false;
-        // 销毁图表实例
-        if (this.personalWorkOrderChart) {
-          this.personalWorkOrderChart.dispose();
-          this.personalWorkOrderChart = null;
-        }
-        return;
-      }
-      
-      // 定义固定颜色数组
-      const fixedColors = [
-        'rgba(82, 196, 26, 0.7)',   // 第一个颜色
-        'rgba(250, 173, 20, 0.7)',  // 第二个颜色
-        'rgba(22, 93, 255, 0.7)'    // 第三个颜色
-      ];
-      
-      // 个人工单完成情况的空心饼图
-      const personalWorkOrderOption = {
-        title: {
-          text: '个人工单完成情况',
-          left: 'left',
-          top: 'top'
-        },
-        tooltip: {
-          show: true,
-          trigger: 'item',
-          padding: [1, 5],
-          backgroundColor: 'rgba(0, 0, 0, 0.7)',
-          borderColor: 'rgba(0, 0, 0, 0.7)',
-          textStyle: {
-            color: '#fff'
-          },
-          formatter: function(params) {
-            return `
-              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
-              <div style="display: flex; align-items: center; font-size:12px;">
-                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
-                <span >${params.value}</span>
-              </div>
-            `;
-          },
-        },
-        legend: {
-          orient: 'horizontal', // 水平分布
-          left: 'center', // 居中
-          bottom: '0', // 底部
-        },
-        series: [
-          {
-            name: '工单状态',
-            label: {
-              show: false
-            },
-            labelLine: {
-              show: false
-            },
-            type: 'pie',
-            radius: ['50%', '75%'], // 空心饼图
-            center: ['50%', '50%'],
-            data: data.map((item, index) => ({
-              name: item.name,
-              value: item.value,
-              itemStyle: { 
-                color: index < 3 ? fixedColors[index] : `rgba(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, 0.7)` 
-              }
-            })),
-            emphasis: {
-              scale: false,
-            }
-          }
-        ]
-      }
-      
-      // 初始化图表实例(如果还没有)
-      if (!this.personalWorkOrderChart) {
-        this.personalWorkOrderChart = echarts.init(this.$refs.personalWorkOrderChart);
-      }
-      
-      // 设置个人工单完成情况图表配置
-      this.personalWorkOrderChart.setOption(personalWorkOrderOption, true);
-    },
-    
-    // 更新班组成员工分情况图表
-    updateTeamPointsChart(pepolePointStatistics) {
-      // 处理后台传回的数据格式 [{"key":"张三","value":"185"}]
-      let names = [];
-      let values = [];
-      
-      if (pepolePointStatistics && Array.isArray(pepolePointStatistics) && pepolePointStatistics.length > 0) {
-        // 从后台数据中提取姓名和工分值
-        names = pepolePointStatistics.map(item => item.key);
-        values = pepolePointStatistics.map(item => parseInt(item.value) || 0);
-        // 显示图表
-        this.showTeamPointsChart = true;
-      } else {
-        // 使用默认数据
-        names = this.defaultTeamPointsData.names;
-        values = this.defaultTeamPointsData.values;
-        // 隐藏图表
-        this.showTeamPointsChart = false;
-      }
-      
-      // 使用新的计算方法
-      const maxValue = Math.max(...values, 5); // 至少显示到5
-      const { maxAxisValue, interval } = this.calculateAxisRange(maxValue);
-      
-      // 班组成员工分情况的横向柱状图(柱子颜色淡蓝色)
-      const teamPointsOption = {
-        title: {
-          text: '班组成员工分情况',
-          left: 'left',
-          top: 'top'
-        },
-        grid: {
-          left: '2%',   // 左边距 5%
-          right: '2%',  // 右边距 5%
-          top: '20%',   // 上边距(根据需求调整)
-          bottom: '5%', // 下边距(根据需求调整)
-          containLabel: true, // 确保标签在 grid 区域内
-        },
-        tooltip: {
-          show: true,
-          trigger: 'item',
-          padding: [1, 5],
-          backgroundColor: 'rgba(0, 0, 0, 0.7)',
-          borderColor: 'rgba(0, 0, 0, 0.7)',
-          textStyle: {
-            color: '#fff'
-          },
-          formatter: function(params) {
-            return `
-              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
-              <div style="display: flex; align-items: center; font-size:12px;">
-                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
-                <span>工分数:</span>
-                <span style="margin-left: 4px;">${params.value}</span>
-              </div>
-            `;
-          },
-          position: 'top',
-        },
-        xAxis: {
-          type: 'value',
-          min: 0,
-          max: maxAxisValue,
-          interval: interval,
-          axisLabel: {
-            formatter: '{value}'
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        yAxis: {
-          type: 'category',
-          data: names, // 班组成员
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        series: [
-          {
-            data: values,
-            type: 'bar',
-            label: {
-              show: false,
-            },
-            barWidth: '70%',
-            itemStyle: {
-              borderRadius: [0, 5, 5, 0],
-              color: 'rgba(22, 93, 255, 0.7)' // 工单总工时颜色
-            }
-          }
-        ]
-      }
-      
-      // 初始化图表实例(如果还没有)
-      if (!this.teamPointsChart) {
-        this.teamPointsChart = echarts.init(this.$refs.teamPointsChart);
-      }
-      
-      // 设置班组成员工分情况图表配置
-      this.teamPointsChart.setOption(teamPointsOption, true);
-    },
-    
-    // 更新超时工单情况图表
-    updateOvertimeChart(overTimeStatistics) {
-      // 处理后台传回的数据格式 [{"key":"超时1天","value":"25"}]
-      let names = [];
-      let values = [];
-      
-      if (overTimeStatistics && Array.isArray(overTimeStatistics) && overTimeStatistics.length > 0) {
-        // 从后台数据中提取超时天数和工单数
-        names = overTimeStatistics.map(item => item.key);
-        values = overTimeStatistics.map(item => parseInt(item.value) || 0);
-        // 显示图表
-        this.showOvertimeChart = true;
-      } else {
-        // 隐藏图表
-        this.showOvertimeChart = false;
-        // 销毁图表实例
-        if (this.overtimeChart) {
-          this.overtimeChart.dispose();
-          this.overtimeChart = null;
-        }
-        return;
-      }
-      
-      // 使用新的计算方法
-      const maxValue = Math.max(...values, 5); // 至少显示到5
-      const { maxAxisValue, interval } = this.calculateAxisRange(maxValue);
-      
-      // 超时工单情况的柱状图(柱子颜色淡红色)
-      const overtimeOption = {
-        title: {
-          text: '超时工单情况',
-          left: 'left',
-          top: 'top'
-        },
-        grid: {
-          left: '2%',   // 左边距 5%
-          right: '2%',  // 右边距 5%
-          top: '20%',   // 上边距(根据需求调整)
-          bottom: '5%', // 下边距(根据需求调整)
-          containLabel: true, // 确保标签在 grid 区域内
-        },
-        tooltip: {
-          show: true,
-          trigger: 'item',
-          padding: [1, 5],
-          backgroundColor: 'rgba(0, 0, 0, 0.7)',
-          borderColor: 'rgba(0, 0, 0, 0.7)',
-          textStyle: {
-            color: '#fff'
-          },
-          formatter: function(params) {
-            return `
-              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
-              <div style="display: flex; align-items: center; font-size:12px;">
-                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
-                <span>工单数:</span>
-                <span style="margin-left: 4px;">${params.value}</span>
-              </div>
-            `;
-          },
-          position: 'top',
-        },
-        xAxis: {
-          type: 'category',
-          data: names, // 超时天数
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        yAxis: {
-          type: 'value',
-          min: 0,
-          max: maxAxisValue,
-          interval: interval,
-          axisLabel: {
-            formatter: '{value}天'
-          },
-          name: '天数',
-          nameLocation: 'middle',
-          nameRotate: 90,
-          nameGap: 40,
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        series: [
-          {
-            data: values, // 工单数
-            type: 'bar',
-            label: {
-              show: false,
-            },
-            barWidth: '70%',
-            itemStyle: {
-              borderRadius: [5, 5, 0, 0],
-              color: 'rgba(255, 77, 79, 0.7)' // 淡红色
-            }
-          }
-        ]
-      }
-      
-      // 初始化图表实例(如果还没有)
-      if (!this.overtimeChart) {
-        this.overtimeChart = echarts.init(this.$refs.overtimeChart);
-      }
-      
-      // 设置超时工单情况图表配置
-      this.overtimeChart.setOption(overtimeOption, true);
-    },
-    
-    // 更新平均设备故障复发时间(MTF)曲线图
-    updateMtfChart(faultStatistics) {
-      // 处理后台传回的数据格式 [{"key":"1月","value":"45"}]
-      let names = [];
-      let values = [];
-      
-      if (faultStatistics && Array.isArray(faultStatistics) && faultStatistics.length > 0) {
-        // 从后台数据中提取月份和MTF值
-        names = faultStatistics.map(item => item.key);
-        values = faultStatistics.map(item => parseInt(item.value) || 0);
-        // 显示图表
-        this.showMtfChart = true;
-      } else {
-        // 隐藏图表
-        this.showMtfChart = false;
-        // 销毁图表实例
-        if (this.mtfChart) {
-          this.mtfChart.dispose();
-          this.mtfChart = null;
-        }
-        return;
-      }
-      
-      // 使用新的计算方法
-      const maxValue = Math.max(...values, 5); // 至少显示到5
-      const { maxAxisValue, interval } = this.calculateAxisRange(maxValue);
-      
-      // 平均设备故障复发时间(MTF)的曲线图(绿色曲线,浅绿色区域)
-      const mtfOption = {
-        title: {
-          text: '平均设备故障复发时间(MTF)',
-          left: 'left',
-          top: 'top'
-        },
-        grid: {
-          left: '2%',   // 左边距 5%
-          right: '2%',  // 右边距 5%
-          top: '20%',   // 上边距(根据需求调整)
-          bottom: '5%', // 下边距(根据需求调整)
-          containLabel: true, // 确保标签在 grid 区域内
-        },
-        tooltip: {
-          show: true,
-          trigger: 'item',
-          padding: [1, 5],
-          backgroundColor: 'rgba(0, 0, 0, 0.7)',
-          borderColor: 'rgba(0, 0, 0, 0.7)',
-          textStyle: {
-            color: '#fff'
-          },
-          formatter: function(params) {
-            return `
-              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
-              <div style="display: flex; align-items: center; font-size:12px;">
-                <span style="display:inline-block; width:12px; height:12px; background:rgba(0, 200, 0, 0.8);margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
-                <span>平均设备故障复发时间(天):</span>
-                <span style="margin-left: 4px;">${params.value}</span>
-              </div>
-            `;
-          }
-        },
-        xAxis: {
-          type: 'category',
-          data: names, // 月份
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          },
-          // 确保0点也能显示x轴第一个名字
-          boundaryGap: false
-        },
-        yAxis: {
-          name: '天数',
-          nameLocation: 'middle',
-          nameGap: 30,
-          type: 'value',
-          min: 0,
-          max: maxAxisValue,
-          interval: interval,
-          axisLabel: {
-            formatter: '{value}'
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        series: [
-          {
-            name: 'MTF',
-            data: values, // MTF值
-            type: 'line',
-            smooth: true,
-            symbolSize: 8,
-            lineStyle: {
-              color: 'rgba(0, 200, 0, 0.8)', // 绿色曲线
-              width: 3
-            },
-            areaStyle: {
-              color: 'rgba(0, 200, 0, 0.2)' // 浅绿色区域
-            }
-          }
-        ]
-      }
-      
-      // 初始化图表实例(如果还没有)
-      if (!this.mtfChart) {
-        this.mtfChart = echarts.init(this.$refs.mtfChart);
-      }
-      
-      // 设置MTF曲线图配置
-      this.mtfChart.setOption(mtfOption, true);
-    },
-    
-    // 更新个人工分统计图表
-    updatePersonalPointsChart(userPointStatistics) {
-      // 处理后台传回的数据格式 [{"key":"周一","value":"25"}]
-      let names = [];
-      let values = [];
-      
-      if (userPointStatistics && Array.isArray(userPointStatistics) && userPointStatistics.length > 0) {
-        // 从后台数据中提取日期和工分值
-        names = userPointStatistics.map(item => item.key);
-        values = userPointStatistics.map(item => parseInt(item.value) || 0);
-        // 显示图表
-        this.showPersonalPointsChart = true;
-      } else {
-        // 隐藏图表
-        this.showPersonalPointsChart = false;
-        // 销毁图表实例
-        if (this.personalPointsChart) {
-          this.personalPointsChart.dispose();
-          this.personalPointsChart = null;
-        }
-        return;
-      }
-      
-      // 使用新的计算方法
-      const maxValue = Math.max(...values, 5); // 至少显示到5
-      const { maxAxisValue, interval } = this.calculateAxisRange(maxValue);
-      
-      // 个人工分统计的曲线图(蓝色曲线,浅蓝色区域)
-      const personalPointsOption = {
-        title: {
-          text: '个人工分统计',
-          left: 'left',
-          top: 'top'
-        },
-        grid: {
-          left: '2%',   // 左边距 5%
-          right: '2%',  // 右边距 5%
-          top: '20%',   // 上边距(根据需求调整)
-          bottom: '5%', // 下边距(根据需求调整)
-          containLabel: true, // 确保标签在 grid 区域内
-        },
-        tooltip: {
-          show: true,
-          trigger: 'item',
-          padding: [1, 5],
-          backgroundColor: 'rgba(0, 0, 0, 0.7)',
-          borderColor: 'rgba(0, 0, 0, 0.7)',
-          textStyle: {
-            color: '#fff'
-          },
-          formatter: function(params) {
-            return `
-              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
-              <div style="display: flex; align-items: center; font-size:12px;">
-                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
-                <span>工分数:</span>
-                <span style="margin-left: 4px;">${params.value}</span>
-              </div>
-            `;
-          },
-        },
-        xAxis: {
-          type: 'category',
-          data: names, // 日期
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          },
-          // 确保0点也能显示x轴第一个名字
-          boundaryGap: false
-        },
-        yAxis: {
-          type: 'value',
-          min: 0,
-          max: maxAxisValue,
-          interval: interval,
-          axisLabel: {
-            formatter: '{value}'
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        series: [
-          {
-            name: '工分',
-            data: values, // 工分值
-            type: 'line',
-            smooth: true,
-            symbolSize: 8,
-            lineStyle: {
-              color: 'rgba(30, 144, 255, 0.8)', // 蓝色曲线
-              width: 3
-            },
-            areaStyle: {
-              color: 'rgba(30, 144, 255, 0.2)' // 浅蓝色区域
-            }
-          }
-        ]
-      }
-      
-      // 初始化图表实例(如果还没有)
-      if (!this.personalPointsChart) {
-        this.personalPointsChart = echarts.init(this.$refs.personalPointsChart);
-      }
-      
-      // 设置个人工分统计图表配置
-      this.personalPointsChart.setOption(personalPointsOption, true);
-    },
-    
-    // 更新图表数据
-    updateCharts() {
-      // 移除原有的工时分类统计柱状图配置,因为现在通过fetchChartData动态加载
-      // 原有的饼图配置已移至updatePieChart方法
-      
-      // 超时工单情况的柱状图(柱子颜色淡红色)
-      const overtimeOption = {
-        title: {
-          text: '超时工单情况',
-          left: 'left',
-          top: 'top'
-        },
-        grid: {
-          left: '2%',   // 左边距 5%
-          right: '2%',  // 右边距 5%
-          top: '20%',   // 上边距(根据需求调整)
-          bottom: '5%', // 下边距(根据需求调整)
-          containLabel: true, // 确保标签在 grid 区域内
-        },
-        tooltip: {
-          show: true,
-          trigger: 'item',
-          padding: [1, 5],
-          backgroundColor: 'rgba(0, 0, 0, 0.7)',
-          borderColor: 'rgba(0, 0, 0, 0.7)',
-          textStyle: {
-            color: '#fff'
-          },
-          formatter: function(params) {
-            return `
-              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
-              <div style="display: flex; align-items: center; font-size:12px;">
-                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
-                <span>工单数:</span>
-                <span style="margin-left: 4px;">${params.value}</span>
-              </div>
-            `;
-          },
-          position: 'top',
-        },
-        xAxis: {
-          type: 'category',
-          data: ['超时1天', '超时2天', '超时3天', '超时4天', '超时5天以上'],
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        yAxis: {
-          type: 'value',
-          min: 0,
-          max: 100,
-          interval: 20,
-          axisLabel: {
-            formatter: '{value}'
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        series: [
-          {
-            data: [25, 18, 12, 8, 5],
-            type: 'bar',
-            label: {
-              show: false,
-            },
-            barWidth: '70%',
-            itemStyle: {
-              borderRadius: [5, 5, 0, 0],
-              color: 'rgba(255, 77, 79, 0.7)' // 验收工时颜色
-            }
-          }
-        ]
-      }
-      
-      // 注意:平均设备故障复发时间(MTF)曲线图由updateMtfChart方法处理
-      
-      // 注意:个人工单完成情况图表由fetchChartData方法处理
-      
-      // 注意:班组成员工分情况图表由fetchChartData方法处理
-      
-      // 注意:工时分类统计图表由fetchChartData方法处理
-      
-      // 个人工分统计的曲线图(蓝色曲线,浅蓝色区域)
-      const personalPointsOption = {
-        title: {
-          text: '个人工分统计',
-          left: 'left',
-          top: 'top'
-        },
-        grid: {
-          left: '2%',   // 左边距 5%
-          right: '2%',  // 右边距 5%
-          top: '20%',   // 上边距(根据需求调整)
-          bottom: '5%', // 下边距(根据需求调整)
-          containLabel: true, // 确保标签在 grid 区域内
-        },
-        tooltip: {
-          show: true,
-          trigger: 'axis',
-          padding: [1, 5],
-          backgroundColor: 'rgba(0, 0, 0, 0.7)',
-          borderColor: 'rgba(0, 0, 0, 0.7)',
-          textStyle: {
-            color: '#fff'
-          },
-          formatter: function(params) {
-            let result = `<div style="font-weight:bold; font-size:12px;">${params[0].name}</div>`;
-            params.forEach(item => {
-              result += `
-                <div style="display: flex; align-items: center; font-size:12px;">
-                  <span style="display:inline-block; width:12px; height:12px; background:${item.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
-                  <span>${item.seriesName}:</span>
-                  <span style="margin-left: 4px;">${item.value}</span>
-                </div>
-              `;
-            });
-            return result;
-          },
-          position: 'top',
-        },
-        xAxis: {
-          type: 'category',
-          data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          },
-          // 确保0点也能显示x轴第一个名字
-          boundaryGap: false
-        },
-        yAxis: {
-          type: 'value',
-          min: 0,
-          max: 50,
-          interval: 10,
-          axisLabel: {
-            formatter: '{value}分'
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: 'rgba(200, 200, 200, 0.3)',
-              type: 'solid'
-            }
-          }
-        },
-        series: [
-          {
-            name: '工分',
-            data: [25, 32, 28, 35, 30, 40, 38],
-            type: 'line',
-            smooth: true,
-            symbolSize: 8,
-            lineStyle: {
-              color: 'rgba(30, 144, 255, 0.8)', // 蓝色曲线
-              width: 3
-            },
-            areaStyle: {
-              color: 'rgba(30, 144, 255, 0.2)' // 浅蓝色区域
-            }
-          }
-        ]
-      }
-      
-      // 设置图表配置(除了工时分类统计图表)
-      // this.pieChart.setOption(pieOption) // 已移至updatePieChart方法
-      this.overtimeChart.setOption(overtimeOption)
-      // 注意:平均设备故障复发时间(MTF)曲线图由updateMtfChart方法处理
-      // 注意:个人工单完成情况图表由fetchChartData方法处理
-      // 注意:班组成员工分情况图表由fetchChartData方法处理
-      // 注意:工时分类统计图表由fetchChartData方法处理
-      this.personalPointsChart.setOption(personalPointsOption)
-    },
-    
-    // 图表自适应
-    resizeCharts() {
-      const charts = [this.barChart, this.pieChart, this.overtimeChart, this.teamPointsChart, this.mtfChart, this.personalWorkOrderChart, this.personalPointsChart];
-      charts.forEach(chart => {
-        if (chart) {
-          chart.resize();
-        }
-      });
-    }
+  components: {
+    ChartsGroupOne,
+    ChartsGroupTwo,
+    ChartsGroupThree
   }
 }
 </script>

+ 399 - 0
ygtx-ui/src/components/Dashboard/ChartsGroupOne.vue

@@ -0,0 +1,399 @@
+<template>
+  <el-row :gutter="20">
+    <!-- 工时分类统计柱状图 -->
+    <el-col :span="12" v-if="showBarChart">
+      <div class="chart-container floating-card">
+        <div ref="barChart" class="chart"></div>
+      </div>
+    </el-col>
+    <!-- 班组成员工分分布饼图 -->
+    <el-col :span="12" v-if="showPieChart">
+      <div class="chart-container floating-card">
+        <div ref="pieChart" class="chart"></div>
+      </div>
+    </el-col>
+  </el-row>
+</template>
+
+<script>
+import * as echarts from 'echarts';
+import { getChartData } from '@/api/system/dashboard';
+
+export default {
+  name: 'ChartsGroupOne',
+  data() {
+    return {
+      barChart: null,
+      pieChart: null,
+      showBarChart: true, // 控制工时分类统计图表的显示
+      showPieChart: true, // 控制班组成员工分分布饼图的显示
+    }
+  },
+  mounted() {
+    this.initCharts()
+  },
+  beforeDestroy() {
+    // 销毁图表实例
+    const charts = [this.barChart, this.pieChart];
+    charts.forEach(chart => {
+      if (chart) {
+        chart.dispose();
+      }
+    });
+  },
+  methods: {
+    // 初始化图表
+    initCharts() {
+      this.barChart = echarts.init(this.$refs.barChart)
+      this.pieChart = echarts.init(this.$refs.pieChart)
+      
+      // 获取图表数据
+      this.fetchChartData();
+    },
+    
+    // 计算轴的最大值和间隔的新方法
+    calculateAxisRange(maxValue) {
+      // 数据中的最大值除以5
+      const dividedValue = maxValue / 5;
+      
+      // 预定义的数组
+      const presetValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 70, 100, 150, 200, 250, 300, 500, 700, 1000, 2000, 5000];
+      
+      // 获取第一个大于dividedValue的值
+      let selectedValue = presetValues[presetValues.length - 1]; // 默认取最大值
+      for (let i = 0; i < presetValues.length; i++) {
+        if (presetValues[i] >= dividedValue) {
+          selectedValue = presetValues[i];
+          break;
+        }
+      }
+      
+      // 乘以5作为最终的最大值
+      const maxAxisValue = selectedValue * 5;
+      
+      // 计算间隔
+      const interval = selectedValue;
+      
+      return { maxAxisValue, interval };
+    },
+    
+    // 获取图表数据
+    async fetchChartData() {
+      try {
+        const response = await getChartData();
+        
+        // 处理工时分类统计数据
+        if (response && response.hourStatistics) {
+          // 更新工时分类统计图表
+          this.updateBarChart(response.hourStatistics);
+        } else {
+          // 如果没有获取到数据,隐藏图表
+          this.showBarChart = false;
+          // 销毁图表实例
+          if (this.barChart) {
+            this.barChart.dispose();
+            this.barChart = null;
+          }
+        }
+        
+        // 处理班组成员工分分布饼图数据
+        if (response && response.classPointStatistics) {
+          // 更新班组成员工分分布饼图
+          this.updatePieChart(response.classPointStatistics);
+        } else {
+          // 如果没有获取到数据,隐藏图表
+          this.showPieChart = false;
+          // 销毁图表实例
+          if (this.pieChart) {
+            this.pieChart.dispose();
+            this.pieChart = null;
+          }
+        }
+      } catch (error) {
+        console.error('获取图表数据失败:', error);
+        // 出错时隐藏图表
+        this.showBarChart = false;
+        this.showPieChart = false;
+        // 销毁图表实例
+        if (this.barChart) {
+          this.barChart.dispose();
+          this.barChart = null;
+        }
+        if (this.pieChart) {
+          this.pieChart.dispose();
+          this.pieChart = null;
+        }
+      }
+    },
+    
+    // 更新班组成员工分分布饼图
+    updatePieChart(classPointStatistics) {
+      // 处理后台传回的数据格式 [{"key":"一班","value":"1250"}]
+      let data = [];
+      
+      if (classPointStatistics && Array.isArray(classPointStatistics) && classPointStatistics.length > 0) {
+        // 从后台数据中提取班组名称和工分值
+        data = classPointStatistics.map(item => ({
+          name: item.key,
+          value: parseInt(item.value) || 0
+        }));
+        // 显示图表
+        this.showPieChart = true;
+      } else {
+        // 隐藏图表
+        this.showPieChart = false;
+        // 销毁图表实例
+        if (this.pieChart) {
+          this.pieChart.dispose();
+          this.pieChart = null;
+        }
+        return;
+      }
+      
+      // 定义前八个固定颜色
+      const fixedColors = [
+        'rgba(22, 93, 255, 0.7)',
+        'rgba(54, 207, 201, 0.7)',
+        'rgba(82, 196, 26, 0.7)',
+        'rgba(250, 173, 20, 0.7)',
+        'rgba(255, 77, 79, 0.7)',
+        'rgba(153, 102, 255, 0.7)',
+        'rgba(255, 159, 64, 0.7)',
+        'rgba(231, 233, 237, 0.7)'
+      ];
+      
+      // 班组成员工分分布的实心饼图
+      const pieOption = {
+        title: {
+          text: '班组成员工分分布',
+          left: 'left',
+          top: 'top'
+        },
+        tooltip: {
+          show: true,
+          trigger: 'item',
+          padding: [1, 5],
+          backgroundColor: 'rgba(0, 0, 0, 0.7)',
+          borderColor: 'rgba(0, 0, 0, 0.7)',
+          textStyle: {
+            color: '#fff'
+          },
+          formatter: function(params) {
+            return `
+              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
+              <div style="display: flex; align-items: center; font-size:12px;">
+                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
+                <span >${params.value}</span>
+              </div>
+            `;
+          },
+        },
+        legend: {
+          orient: 'vertical',
+          left: 'right',
+          top: 'bottom',
+        },
+        series: [
+          {
+            name: '工分',
+            label: {
+              show: false
+            },
+            labelLine: {
+              show: false
+            },
+            type: 'pie',
+            radius: '85%', // 实心饼图
+            center: ['50%', '55%'],
+            data: data.map((item, index) => ({
+              name: item.name,
+              value: item.value,
+              itemStyle: { 
+                color: index < 8 ? fixedColors[index] : `rgba(${Math.floor(Math.random() * 200 + 55)}, ${Math.floor(Math.random() * 200 + 55)}, ${Math.floor(Math.random() * 200 + 55)}, 0.7)` 
+              }
+            })),
+            emphasis: {
+              scale: false,
+            }
+          }
+        ]
+      }
+      
+      // 初始化图表实例(如果还没有)
+      if (!this.pieChart) {
+        this.pieChart = echarts.init(this.$refs.pieChart);
+      }
+      
+      // 设置班组成员工分分布饼图配置
+      this.pieChart.setOption(pieOption, true);
+    },
+    
+    // 更新工时分类统计图表
+    updateBarChart(hourStatistics) {
+      // 处理后台传回的数据格式 [{"key":"工单总工时","value":"3240"}]
+      let names = [];
+      let values = [];
+      
+      if (hourStatistics && Array.isArray(hourStatistics) && hourStatistics.length > 0) {
+        // 从后台数据中提取工时类型和工时数
+        names = hourStatistics.map(item => item.key);
+        values = hourStatistics.map(item => parseInt(item.value) || 0);
+        // 显示图表
+        this.showBarChart = true;
+      } else {
+        // 隐藏图表
+        this.showBarChart = false;
+        // 销毁图表实例
+        if (this.barChart) {
+          this.barChart.dispose();
+          this.barChart = null;
+        }
+        return;
+      }
+      
+      // 使用新的计算方法
+      const maxValue = Math.max(...values, 5); // 至少显示到5
+      const { maxAxisValue, interval } = this.calculateAxisRange(maxValue);
+      
+      // 工时分类统计的柱状图
+      const barOption = {
+        title: {
+          text: '工时分类统计',
+          left: 'left',
+          top: 'top'
+        },
+        grid: {
+          left: '2%',   // 左边距 5%
+          right: '2%',  // 右边距 5%
+          top: '20%',   // 上边距(根据需求调整)
+          bottom: '5%', // 下边距(根据需求调整)
+          containLabel: true, // 确保标签在 grid 区域内
+        },
+        tooltip: {
+          show: true,
+          trigger: 'item',
+          padding: [1, 5],
+          backgroundColor: 'rgba(0, 0, 0, 0.7)',
+          borderColor: 'rgba(0, 0, 0, 0.7)',
+          textStyle: {
+            color: '#fff'
+          },
+          formatter: function(params) {
+            return `
+              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
+              <div style="display: flex; align-items: center; font-size:12px;">
+                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
+                <span>工时数:</span>
+                <span style="margin-left: 4px;">${params.value}</span>
+              </div>
+            `;
+          },
+          position: 'top',
+        },
+        xAxis: {
+          type: 'category',
+          data: names, // 工时类型
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(200, 200, 200, 0.3)',
+              type: 'solid'
+            }
+          }
+        },
+        yAxis: {
+          type: 'value',
+          min: 0,
+          max: maxAxisValue,
+          interval: interval,
+          axisLabel: {
+            formatter: '{value}'
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(200, 200, 200, 0.3)',
+              type: 'solid'
+            }
+          }
+        },
+        series: [
+          {
+            data: values, // 工时数
+            type: 'bar',
+            label: {
+              show: false,
+            },
+            barWidth: '70%',
+            itemStyle: {
+              borderRadius: [5, 5, 0, 0],
+              color: function(params) {
+                const colors = [
+                  'rgba(22, 93, 255, 0.7)',
+                  'rgba(54, 207, 201, 0.7)',
+                  'rgba(82, 196, 26, 0.7)',
+                  'rgba(250, 173, 20, 0.7)',
+                  'rgba(255, 77, 79, 0.7)'
+                ];
+                return colors[params.dataIndex] || 'rgba(22, 93, 255, 0.7)';
+              }
+            }
+          }
+        ]
+      }
+      
+      // 初始化图表实例(如果还没有)
+      if (!this.barChart) {
+        this.barChart = echarts.init(this.$refs.barChart);
+      }
+      
+      // 设置工时分类统计图表配置
+      this.barChart.setOption(barOption, true);
+    },
+    
+    // 图表自适应
+    resizeCharts() {
+      const charts = [this.barChart, this.pieChart];
+      charts.forEach(chart => {
+        if (chart) {
+          chart.resize();
+        }
+      });
+    }
+  }
+}
+</script>
+
+<style scoped>
+/* 悬浮卡片通用样式 */
+.floating-card {
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
+  transition: all 0.3s ease;
+}
+
+.floating-card:hover {
+  transform: translateY(-8px);
+  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
+}
+
+/* 图表样式 */
+.chart-container {
+  height: 340px;
+  background-color: rgba(255, 255, 255, 0.7);
+  border-radius: 8px;
+  padding: 20px;
+  margin-top: 20px;
+  box-sizing: border-box;
+  backdrop-filter: blur(5px);
+}
+
+.chart-container:hover {
+  transform: translateY(-8px);
+  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
+}
+
+.chart {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 389 - 0
ygtx-ui/src/components/Dashboard/ChartsGroupThree.vue

@@ -0,0 +1,389 @@
+<template>
+  <el-row :gutter="20">
+    <!-- 个人工单完成情况的空心饼图 -->
+    <el-col :span="12" v-if="showPersonalWorkOrderChart">
+      <div class="chart-container floating-card">
+        <div ref="personalWorkOrderChart" class="chart"></div>
+      </div>
+    </el-col>
+    
+    <!-- 个人工分统计的曲线图 -->
+    <el-col :span="12" v-if="showPersonalPointsChart">
+      <div class="chart-container floating-card">
+        <div ref="personalPointsChart" class="chart"></div>
+      </div>
+    </el-col>
+  </el-row>
+</template>
+
+<script>
+import * as echarts from 'echarts';
+import { getChartData } from '@/api/system/dashboard';
+
+export default {
+  name: 'ChartsGroupThree',
+  data() {
+    return {
+      personalWorkOrderChart: null,
+      personalPointsChart: null,
+      showPersonalWorkOrderChart: true, // 控制个人工单完成情况图表的显示
+      showPersonalPointsChart: true, // 控制个人工分统计图表的显示
+    }
+  },
+  mounted() {
+    this.initCharts()
+  },
+  beforeDestroy() {
+    // 销毁图表实例
+    const charts = [this.personalWorkOrderChart, this.personalPointsChart];
+    charts.forEach(chart => {
+      if (chart) {
+        chart.dispose();
+      }
+    });
+  },
+  methods: {
+    // 初始化图表
+    initCharts() {
+      this.personalWorkOrderChart = echarts.init(this.$refs.personalWorkOrderChart)
+      this.personalPointsChart = echarts.init(this.$refs.personalPointsChart)
+      
+      // 获取图表数据
+      this.fetchChartData();
+    },
+    
+    // 获取图表数据
+    async fetchChartData() {
+      try {
+        const response = await getChartData();
+        
+        // 处理个人工单完成情况数据
+        if (response && response.userOrderStatistics) {
+          // 更新个人工单完成情况图表
+          this.updatePersonalWorkOrderChart(response.userOrderStatistics);
+        } else {
+          // 如果没有获取到数据,隐藏图表
+          this.showPersonalWorkOrderChart = false;
+          // 销毁图表实例
+          if (this.personalWorkOrderChart) {
+            this.personalWorkOrderChart.dispose();
+            this.personalWorkOrderChart = null;
+          }
+        }
+        
+        // 处理个人工分统计数据
+        if (response && response.userPointStatistics) {
+          // 更新个人工分统计图表
+          this.updatePersonalPointsChart(response.userPointStatistics);
+        } else {
+          // 如果没有获取到数据,隐藏图表
+          this.showPersonalPointsChart = false;
+          // 销毁图表实例
+          if (this.personalPointsChart) {
+            this.personalPointsChart.dispose();
+            this.personalPointsChart = null;
+          }
+        }
+      } catch (error) {
+        console.error('获取图表数据失败:', error);
+        // 出错时隐藏图表
+        this.showPersonalWorkOrderChart = false;
+        this.showPersonalPointsChart = false;
+        // 销毁图表实例
+        if (this.personalWorkOrderChart) {
+          this.personalWorkOrderChart.dispose();
+          this.personalWorkOrderChart = null;
+        }
+        if (this.personalPointsChart) {
+          this.personalPointsChart.dispose();
+          this.personalPointsChart = null;
+        }
+      }
+    },
+    
+    // 计算轴的最大值和间隔的新方法
+    calculateAxisRange(maxValue) {
+      // 数据中的最大值除以5
+      const dividedValue = maxValue / 5;
+      
+      // 预定义的数组
+      const presetValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 70, 100, 150, 200, 250, 300, 500, 700, 1000, 2000, 5000];
+      
+      // 获取第一个大于dividedValue的值
+      let selectedValue = presetValues[presetValues.length - 1]; // 默认取最大值
+      for (let i = 0; i < presetValues.length; i++) {
+        if (presetValues[i] >= dividedValue) {
+          selectedValue = presetValues[i];
+          break;
+        }
+      }
+      
+      // 乘以5作为最终的最大值
+      const maxAxisValue = selectedValue * 5;
+      
+      // 计算间隔
+      const interval = selectedValue;
+      
+      return { maxAxisValue, interval };
+    },
+    
+    // 更新个人工单完成情况图表
+    updatePersonalWorkOrderChart(userOrderStatistics) {
+      // 处理后台传回的数据格式 [{"key":"已完成","value":"45"}]
+      let data = [];
+      
+      if (userOrderStatistics && Array.isArray(userOrderStatistics) && userOrderStatistics.length > 0) {
+        // 从后台数据中提取状态和数量
+        data = userOrderStatistics.map(item => ({
+          name: item.key,
+          value: parseInt(item.value) || 0
+        }));
+        // 显示图表
+        this.showPersonalWorkOrderChart = true;
+      } else {
+        // 隐藏图表
+        this.showPersonalWorkOrderChart = false;
+        // 销毁图表实例
+        if (this.personalWorkOrderChart) {
+          this.personalWorkOrderChart.dispose();
+          this.personalWorkOrderChart = null;
+        }
+        return;
+      }
+      
+      // 定义固定颜色数组
+      const fixedColors = [
+        'rgba(82, 196, 26, 0.7)',   // 第一个颜色
+        'rgba(250, 173, 20, 0.7)',  // 第二个颜色
+        'rgba(22, 93, 255, 0.7)'    // 第三个颜色
+      ];
+      
+      // 个人工单完成情况的空心饼图
+      const personalWorkOrderOption = {
+        title: {
+          text: '个人工单完成情况',
+          left: 'left',
+          top: 'top'
+        },
+        tooltip: {
+          show: true,
+          trigger: 'item',
+          padding: [1, 5],
+          backgroundColor: 'rgba(0, 0, 0, 0.7)',
+          borderColor: 'rgba(0, 0, 0, 0.7)',
+          textStyle: {
+            color: '#fff'
+          },
+          formatter: function(params) {
+            return `
+              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
+              <div style="display: flex; align-items: center; font-size:12px;">
+                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
+                <span >${params.value}</span>
+              </div>
+            `;
+          },
+        },
+        legend: {
+          orient: 'horizontal', // 水平分布
+          left: 'center', // 居中
+          bottom: '0', // 底部
+        },
+        series: [
+          {
+            name: '工单状态',
+            label: {
+              show: false
+            },
+            labelLine: {
+              show: false
+            },
+            type: 'pie',
+            radius: ['50%', '75%'], // 空心饼图
+            center: ['50%', '50%'],
+            data: data.map((item, index) => ({
+              name: item.name,
+              value: item.value,
+              itemStyle: { 
+                color: index < 3 ? fixedColors[index] : `rgba(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, 0.7)` 
+              }
+            })),
+            emphasis: {
+              scale: false,
+            }
+          }
+        ]
+      }
+      
+      // 初始化图表实例(如果还没有)
+      if (!this.personalWorkOrderChart) {
+        this.personalWorkOrderChart = echarts.init(this.$refs.personalWorkOrderChart);
+      }
+      
+      // 设置个人工单完成情况图表配置
+      this.personalWorkOrderChart.setOption(personalWorkOrderOption, true);
+    },
+    
+    // 更新个人工分统计图表
+    updatePersonalPointsChart(userPointStatistics) {
+      // 处理后台传回的数据格式 [{"key":"周一","value":"25"}]
+      let names = [];
+      let values = [];
+      
+      if (userPointStatistics && Array.isArray(userPointStatistics) && userPointStatistics.length > 0) {
+        // 从后台数据中提取日期和工分值
+        names = userPointStatistics.map(item => item.key);
+        values = userPointStatistics.map(item => parseInt(item.value) || 0);
+        // 显示图表
+        this.showPersonalPointsChart = true;
+      } else {
+        // 隐藏图表
+        this.showPersonalPointsChart = false;
+        // 销毁图表实例
+        if (this.personalPointsChart) {
+          this.personalPointsChart.dispose();
+          this.personalPointsChart = null;
+        }
+        return;
+      }
+      
+      // 使用新的计算方法
+      const maxValue = Math.max(...values, 5); // 至少显示到5
+      const { maxAxisValue, interval } = this.calculateAxisRange(maxValue);
+      
+      // 个人工分统计的曲线图(蓝色曲线,浅蓝色区域)
+      const personalPointsOption = {
+        title: {
+          text: '个人工分统计',
+          left: 'left',
+          top: 'top'
+        },
+        grid: {
+          left: '2%',   // 左边距 5%
+          right: '2%',  // 右边距 5%
+          top: '20%',   // 上边距(根据需求调整)
+          bottom: '5%', // 下边距(根据需求调整)
+          containLabel: true, // 确保标签在 grid 区域内
+        },
+        tooltip: {
+          show: true,
+          trigger: 'item',
+          padding: [1, 5],
+          backgroundColor: 'rgba(0, 0, 0, 0.7)',
+          borderColor: 'rgba(0, 0, 0, 0.7)',
+          textStyle: {
+            color: '#fff'
+          },
+          formatter: function(params) {
+            return `
+              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
+              <div style="display: flex; align-items: center; font-size:12px;">
+                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
+                <span>工分数:</span>
+                <span style="margin-left: 4px;">${params.value}</span>
+              </div>
+            `;
+          },
+        },
+        xAxis: {
+          type: 'category',
+          data: names, // 日期
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(200, 200, 200, 0.3)',
+              type: 'solid'
+            }
+          },
+          // 确保0点也能显示x轴第一个名字
+          boundaryGap: false
+        },
+        yAxis: {
+          type: 'value',
+          min: 0,
+          max: maxAxisValue,
+          interval: interval,
+          axisLabel: {
+            formatter: '{value}'
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(200, 200, 200, 0.3)',
+              type: 'solid'
+            }
+          }
+        },
+        series: [
+          {
+            name: '工分',
+            data: values, // 工分值
+            type: 'line',
+            smooth: true,
+            symbolSize: 8,
+            lineStyle: {
+              color: 'rgba(30, 144, 255, 0.8)', // 蓝色曲线
+              width: 3
+            },
+            areaStyle: {
+              color: 'rgba(30, 144, 255, 0.2)' // 浅蓝色区域
+            }
+          }
+        ]
+      }
+      
+      // 初始化图表实例(如果还没有)
+      if (!this.personalPointsChart) {
+        this.personalPointsChart = echarts.init(this.$refs.personalPointsChart);
+      }
+      
+      // 设置个人工分统计图表配置
+      this.personalPointsChart.setOption(personalPointsOption, true);
+    },
+    
+    // 图表自适应
+    resizeCharts() {
+      const charts = [this.personalWorkOrderChart, this.personalPointsChart];
+      charts.forEach(chart => {
+        if (chart) {
+          chart.resize();
+        }
+      });
+    }
+  }
+}
+</script>
+
+<style scoped>
+/* 悬浮卡片通用样式 */
+.floating-card {
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
+  transition: all 0.3s ease;
+}
+
+.floating-card:hover {
+  transform: translateY(-8px);
+  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
+}
+
+/* 图表样式 */
+.chart-container {
+  height: 340px;
+  background-color: rgba(255, 255, 255, 0.7);
+  border-radius: 8px;
+  padding: 20px;
+  margin-top: 20px;
+  box-sizing: border-box;
+  backdrop-filter: blur(5px);
+}
+
+.chart-container:hover {
+  transform: translateY(-8px);
+  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
+}
+
+.chart {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 556 - 0
ygtx-ui/src/components/Dashboard/ChartsGroupTwo.vue

@@ -0,0 +1,556 @@
+<template>
+  <el-row :gutter="20">
+    <!-- 超时工单情况的柱状图 -->
+    <el-col :span="12" v-if="showOvertimeChart">
+      <div class="chart-container floating-card">
+        <div ref="overtimeChart" class="chart"></div>
+      </div>
+    </el-col>
+    
+    <!-- 班组成员工分情况的横向柱状图 -->
+    <el-col :span="12" v-if="showTeamPointsChart">
+      <div class="chart-container floating-card">
+        <div ref="teamPointsChart" class="chart"></div>
+      </div>
+    </el-col>
+    
+    <!-- 平均设备故障复发时间(MTF)的曲线图 -->
+    <el-col :span="24" v-if="showMtfChart">
+      <div class="chart-container floating-card">
+        <div ref="mtfChart" class="chart"></div>
+      </div>
+    </el-col>
+  </el-row>
+</template>
+
+<script>
+import * as echarts from 'echarts';
+import { getChartData } from '@/api/system/dashboard';
+
+export default {
+  name: 'ChartsGroupTwo',
+  data() {
+    return {
+      overtimeChart: null,
+      teamPointsChart: null,
+      mtfChart: null,
+      showOvertimeChart: true, // 控制超时工单情况图表的显示
+      showTeamPointsChart: true, // 控制班组成员工分情况图表的显示
+      showMtfChart: true, // 控制MTF曲线图的显示
+    }
+  },
+  mounted() {
+    this.initCharts()
+  },
+  beforeDestroy() {
+    // 销毁所有图表实例
+    const charts = [this.overtimeChart, this.teamPointsChart, this.mtfChart];
+    charts.forEach(chart => {
+      if (chart) {
+        chart.dispose();
+      }
+    });
+  },
+  methods: {
+    // 初始化图表
+    initCharts() {
+      this.overtimeChart = echarts.init(this.$refs.overtimeChart)
+      this.teamPointsChart = echarts.init(this.$refs.teamPointsChart)
+      this.mtfChart = echarts.init(this.$refs.mtfChart)
+      
+      // 获取图表数据
+      this.fetchChartData();
+    },
+    
+    // 获取图表数据
+    async fetchChartData() {
+      try {
+        const response = await getChartData();
+        
+        // 处理班组成员工分情况数据
+        if (response && response.pepolePointStatistics) {
+          // 更新班组成员工分情况图表
+          this.updateTeamPointsChart(response.pepolePointStatistics);
+        } else {
+          // 如果没有获取到数据,隐藏图表
+          this.showTeamPointsChart = false;
+          // 销毁图表实例
+          if (this.teamPointsChart) {
+            this.teamPointsChart.dispose();
+            this.teamPointsChart = null;
+          }
+        }
+        
+        // 处理超时工单情况数据
+        if (response && response.overTimeStatistics) {
+          // 更新超时工单情况图表
+          this.updateOvertimeChart(response.overTimeStatistics);
+        } else {
+          // 如果没有获取到数据,隐藏图表
+          this.showOvertimeChart = false;
+          // 销毁图表实例
+          if (this.overtimeChart) {
+            this.overtimeChart.dispose();
+            this.overtimeChart = null;
+          }
+        }
+        
+        // 处理平均设备故障复发时间(MTF)数据
+        if (response && response.faultStatistics) {
+          // 更新MTF曲线图
+          this.updateMtfChart(response.faultStatistics);
+        } else {
+          // 如果没有获取到数据,隐藏图表
+          this.showMtfChart = false;
+          // 销毁图表实例
+          if (this.mtfChart) {
+            this.mtfChart.dispose();
+            this.mtfChart = null;
+          }
+        }
+      } catch (error) {
+        console.error('获取图表数据失败:', error);
+        // 出错时隐藏图表
+        this.showTeamPointsChart = false;
+        this.showOvertimeChart = false;
+        this.showMtfChart = false;
+        // 销毁图表实例
+        if (this.teamPointsChart) {
+          this.teamPointsChart.dispose();
+          this.teamPointsChart = null;
+        }
+        if (this.overtimeChart) {
+          this.overtimeChart.dispose();
+          this.overtimeChart = null;
+        }
+        if (this.mtfChart) {
+          this.mtfChart.dispose();
+          this.mtfChart = null;
+        }
+      }
+    },
+    
+    // 计算轴的最大值和间隔的新方法
+    calculateAxisRange(maxValue) {
+      // 数据中的最大值除以5
+      const dividedValue = maxValue / 5;
+      
+      // 预定义的数组
+      const presetValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 70, 100, 150, 200, 250, 300, 500, 700, 1000, 2000, 5000];
+      
+      // 获取第一个大于dividedValue的值
+      let selectedValue = presetValues[presetValues.length - 1]; // 默认取最大值
+      for (let i = 0; i < presetValues.length; i++) {
+        if (presetValues[i] >= dividedValue) {
+          selectedValue = presetValues[i];
+          break;
+        }
+      }
+      
+      // 乘以5作为最终的最大值
+      const maxAxisValue = selectedValue * 5;
+      
+      // 计算间隔
+      const interval = selectedValue;
+      
+      return { maxAxisValue, interval };
+    },
+    
+    // 更新班组成员工分情况图表
+    updateTeamPointsChart(pepolePointStatistics) {
+      // 处理后台传回的数据格式 [{"key":"张三","value":"185"}]
+      let names = [];
+      let values = [];
+      
+      if (pepolePointStatistics && Array.isArray(pepolePointStatistics) && pepolePointStatistics.length > 0) {
+        // 从后台数据中提取姓名和工分值
+        names = pepolePointStatistics.map(item => item.key);
+        values = pepolePointStatistics.map(item => parseInt(item.value) || 0);
+        // 显示图表
+        this.showTeamPointsChart = true;
+      } else {
+        // 隐藏图表
+        this.showTeamPointsChart = false;
+        // 销毁图表实例
+        if (this.teamPointsChart) {
+          this.teamPointsChart.dispose();
+          this.teamPointsChart = null;
+        }
+        return;
+      }
+      
+      // 使用新的计算方法
+      const maxValue = Math.max(...values, 5); // 至少显示到5
+      const { maxAxisValue, interval } = this.calculateAxisRange(maxValue);
+      
+      // 班组成员工分情况的横向柱状图(柱子颜色淡蓝色)
+      const teamPointsOption = {
+        title: {
+          text: '班组成员工分情况',
+          left: 'left',
+          top: 'top'
+        },
+        grid: {
+          left: '2%',   // 左边距 5%
+          right: '2%',  // 右边距 5%
+          top: '20%',   // 上边距(根据需求调整)
+          bottom: '5%', // 下边距(根据需求调整)
+          containLabel: true, // 确保标签在 grid 区域内
+        },
+        tooltip: {
+          show: true,
+          trigger: 'item',
+          padding: [1, 5],
+          backgroundColor: 'rgba(0, 0, 0, 0.7)',
+          borderColor: 'rgba(0, 0, 0, 0.7)',
+          textStyle: {
+            color: '#fff'
+          },
+          formatter: function(params) {
+            return `
+              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
+              <div style="display: flex; align-items: center; font-size:12px;">
+                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
+                <span>工分数:</span>
+                <span style="margin-left: 4px;">${params.value}</span>
+              </div>
+            `;
+          },
+          position: 'top',
+        },
+        xAxis: {
+          type: 'value',
+          min: 0,
+          max: maxAxisValue,
+          interval: interval,
+          axisLabel: {
+            formatter: '{value}'
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(200, 200, 200, 0.3)',
+              type: 'solid'
+            }
+          }
+        },
+        yAxis: {
+          type: 'category',
+          data: names, // 班组成员
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(200, 200, 200, 0.3)',
+              type: 'solid'
+            }
+          }
+        },
+        series: [
+          {
+            data: values,
+            type: 'bar',
+            label: {
+              show: false,
+            },
+            barWidth: '70%',
+            itemStyle: {
+              borderRadius: [0, 5, 5, 0],
+              color: 'rgba(22, 93, 255, 0.7)' // 工单总工时颜色
+            }
+          }
+        ]
+      }
+      
+      // 初始化图表实例(如果还没有)
+      if (!this.teamPointsChart) {
+        this.teamPointsChart = echarts.init(this.$refs.teamPointsChart);
+      }
+      
+      // 设置班组成员工分情况图表配置
+      this.teamPointsChart.setOption(teamPointsOption, true);
+    },
+    
+    // 更新超时工单情况图表
+    updateOvertimeChart(overTimeStatistics) {
+      // 处理后台传回的数据格式 [{"key":"超时1天","value":"25"}]
+      let names = [];
+      let values = [];
+      
+      if (overTimeStatistics && Array.isArray(overTimeStatistics) && overTimeStatistics.length > 0) {
+        // 从后台数据中提取超时天数和工单数
+        names = overTimeStatistics.map(item => item.key);
+        values = overTimeStatistics.map(item => parseInt(item.value) || 0);
+        // 显示图表
+        this.showOvertimeChart = true;
+      } else {
+        // 隐藏图表
+        this.showOvertimeChart = false;
+        // 销毁图表实例
+        if (this.overtimeChart) {
+          this.overtimeChart.dispose();
+          this.overtimeChart = null;
+        }
+        return;
+      }
+      
+      // 使用新的计算方法
+      const maxValue = Math.max(...values, 5); // 至少显示到5
+      const { maxAxisValue, interval } = this.calculateAxisRange(maxValue);
+      
+      // 超时工单情况的柱状图(柱子颜色淡红色)
+      const overtimeOption = {
+        title: {
+          text: '超时工单情况',
+          left: 'left',
+          top: 'top'
+        },
+        grid: {
+          left: '2%',   // 左边距 5%
+          right: '2%',  // 右边距 5%
+          top: '20%',   // 上边距(根据需求调整)
+          bottom: '5%', // 下边距(根据需求调整)
+          containLabel: true, // 确保标签在 grid 区域内
+        },
+        tooltip: {
+          show: true,
+          trigger: 'item',
+          padding: [1, 5],
+          backgroundColor: 'rgba(0, 0, 0, 0.7)',
+          borderColor: 'rgba(0, 0, 0, 0.7)',
+          textStyle: {
+            color: '#fff'
+          },
+          formatter: function(params) {
+            return `
+              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
+              <div style="display: flex; align-items: center; font-size:12px;">
+                <span style="display:inline-block; width:12px; height:12px; background:${params.color};margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
+                <span>工单数:</span>
+                <span style="margin-left: 4px;">${params.value}</span>
+              </div>
+            `;
+          },
+          position: 'top',
+        },
+        xAxis: {
+          type: 'category',
+          data: names, // 超时天数
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(200, 200, 200, 0.3)',
+              type: 'solid'
+            }
+          }
+        },
+        yAxis: {
+          type: 'value',
+          min: 0,
+          max: maxAxisValue,
+          interval: interval,
+          axisLabel: {
+            formatter: '{value}天'
+          },
+          name: '天数',
+          nameLocation: 'middle',
+          nameRotate: 90,
+          nameGap: 40,
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(200, 200, 200, 0.3)',
+              type: 'solid'
+            }
+          }
+        },
+        series: [
+          {
+            data: values, // 工单数
+            type: 'bar',
+            label: {
+              show: false,
+            },
+            barWidth: '70%',
+            itemStyle: {
+              borderRadius: [5, 5, 0, 0],
+              color: 'rgba(255, 77, 79, 0.7)' // 淡红色
+            }
+          }
+        ]
+      }
+      
+      // 初始化图表实例(如果还没有)
+      if (!this.overtimeChart) {
+        this.overtimeChart = echarts.init(this.$refs.overtimeChart);
+      }
+      
+      // 设置超时工单情况图表配置
+      this.overtimeChart.setOption(overtimeOption, true);
+    },
+    
+    // 更新平均设备故障复发时间(MTF)曲线图
+    updateMtfChart(faultStatistics) {
+      // 处理后台传回的数据格式 [{"key":"1月","value":"45"}]
+      let names = [];
+      let values = [];
+      
+      if (faultStatistics && Array.isArray(faultStatistics) && faultStatistics.length > 0) {
+        // 从后台数据中提取月份和MTF值
+        names = faultStatistics.map(item => item.key);
+        values = faultStatistics.map(item => parseInt(item.value) || 0);
+        // 显示图表
+        this.showMtfChart = true;
+      } else {
+        // 隐藏图表
+        this.showMtfChart = false;
+        // 销毁图表实例
+        if (this.mtfChart) {
+          this.mtfChart.dispose();
+          this.mtfChart = null;
+        }
+        return;
+      }
+      
+      // 使用新的计算方法
+      const maxValue = Math.max(...values, 5); // 至少显示到5
+      const { maxAxisValue, interval } = this.calculateAxisRange(maxValue);
+      
+      // 平均设备故障复发时间(MTF)的曲线图(绿色曲线,浅绿色区域)
+      const mtfOption = {
+        title: {
+          text: '平均设备故障复发时间(MTF)',
+          left: 'left',
+          top: 'top'
+        },
+        grid: {
+          left: '2%',   // 左边距 5%
+          right: '2%',  // 右边距 5%
+          top: '20%',   // 上边距(根据需求调整)
+          bottom: '5%', // 下边距(根据需求调整)
+          containLabel: true, // 确保标签在 grid 区域内
+        },
+        tooltip: {
+          show: true,
+          trigger: 'item',
+          padding: [1, 5],
+          backgroundColor: 'rgba(0, 0, 0, 0.7)',
+          borderColor: 'rgba(0, 0, 0, 0.7)',
+          textStyle: {
+            color: '#fff'
+          },
+          formatter: function(params) {
+            return `
+              <div style="font-weight:bold; font-size:12px;">${params.name}</div>
+              <div style="display: flex; align-items: center; font-size:12px;">
+                <span style="display:inline-block; width:12px; height:12px; background:rgba(0, 200, 0, 0.8);margin-right: 4px;box-shadow: 0 0 0 0.5px white;"></span>
+                <span>平均设备故障复发时间(天):</span>
+                <span style="margin-left: 4px;">${params.value}</span>
+              </div>
+            `;
+          }
+        },
+        xAxis: {
+          type: 'category',
+          data: names, // 月份
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(200, 200, 200, 0.3)',
+              type: 'solid'
+            }
+          },
+          // 确保0点也能显示x轴第一个名字
+          boundaryGap: false
+        },
+        yAxis: {
+          name: '天数',
+          nameLocation: 'middle',
+          nameGap: 30,
+          type: 'value',
+          min: 0,
+          max: maxAxisValue,
+          interval: interval,
+          axisLabel: {
+            formatter: '{value}'
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(200, 200, 200, 0.3)',
+              type: 'solid'
+            }
+          }
+        },
+        series: [
+          {
+            name: 'MTF',
+            data: values, // MTF值
+            type: 'line',
+            smooth: true,
+            symbolSize: 8,
+            lineStyle: {
+              color: 'rgba(0, 200, 0, 0.8)', // 绿色曲线
+              width: 3
+            },
+            areaStyle: {
+              color: 'rgba(0, 200, 0, 0.2)' // 浅绿色区域
+            }
+          }
+        ]
+      }
+      
+      // 初始化图表实例(如果还没有)
+      if (!this.mtfChart) {
+        this.mtfChart = echarts.init(this.$refs.mtfChart);
+      }
+      
+      // 设置MTF曲线图配置
+      this.mtfChart.setOption(mtfOption, true);
+    },
+    
+    // 图表自适应
+    resizeCharts() {
+      const charts = [this.overtimeChart, this.teamPointsChart, this.mtfChart];
+      charts.forEach(chart => {
+        if (chart) {
+          chart.resize();
+        }
+      });
+    }
+  }
+}
+</script>
+
+<style scoped>
+/* 悬浮卡片通用样式 */
+.floating-card {
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
+  transition: all 0.3s ease;
+}
+
+.floating-card:hover {
+  transform: translateY(-8px);
+  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
+}
+
+/* 图表样式 */
+.chart-container {
+  height: 340px;
+  background-color: rgba(255, 255, 255, 0.7);
+  border-radius: 8px;
+  padding: 20px;
+  margin-top: 20px;
+  box-sizing: border-box;
+  backdrop-filter: blur(5px);
+}
+
+.chart-container:hover {
+  transform: translateY(-8px);
+  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
+}
+
+.chart {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 1 - 1
ygtx-ui/src/components/Dashboard/DataStatistics.vue

@@ -6,7 +6,7 @@
           <div class="stat-icon-wrapper">
             <div class="stat-icon-bg" :style="{ backgroundColor: stat.color + '15' }">
               <i 
-                v-if="stat.icon && stat.icon.startsWith('fas ')" 
+                v-if="stat.icon && (stat.icon.startsWith('fa ') || stat.icon.startsWith('fa-'))" 
                 :class="stat.icon" 
                 :style="{ color: stat.color }">
               </i>

+ 7 - 7
ygtx-ui/src/components/Dashboard/FrequentFeatures.vue

@@ -9,7 +9,7 @@
         @click="handleFeatureClick(feature)">
         <div class="feature-icon" :style="{ backgroundColor: feature.color.bgcolor }">
           <i 
-            v-if="feature.icon && feature.icon.startsWith('fas ')" 
+            v-if="feature.icon && feature.icon.startsWith('fa ')" 
             :class="feature.icon" 
             :style="{ color: feature.color.color }">
           </i>
@@ -57,7 +57,7 @@ export default {
           const colorKey = item.color || 'blue'
           return {
             name: item.title,
-            icon: item.icon || 'fas fa-tasks',
+            icon: item.icon || 'fa fa-tasks',
             color: this.colorList[colorKey] || this.colorList.blue
           }
         })
@@ -65,11 +65,11 @@ export default {
         console.error('获取高频功能数据失败:', error)
         // 如果获取失败,使用默认数据
         this.features = [
-          { name: '工单管理', icon: 'fas fa-tasks', color: this.colorList.blue },
-          { name: '班组管理', icon: 'fas fa-users', color: this.colorList.cyan },
-          { name: '工分管理', icon: 'fas fa-star', color: this.colorList.orange },
-          { name: '工时分析', icon: 'fas fa-clock', color: this.colorList.gray },
-          { name: '通知中心', icon: 'fas fa-bell', color: this.colorList.red }
+          { name: '工单管理', icon: 'fa fa-tasks', color: this.colorList.blue },
+          { name: '班组管理', icon: 'fa fa-users', color: this.colorList.cyan },
+          { name: '工分管理', icon: 'fa fa-star', color: this.colorList.orange },
+          { name: '工时分析', icon: 'fa fa-clock', color: this.colorList.gray },
+          { name: '通知中心', icon: 'fa fa-bell', color: this.colorList.red }
         ]
       }
     },