ouyj 4 месяцев назад
Родитель
Сommit
a04269028c

+ 20 - 0
ygtx-gxt/src/main/java/com/ygtx/gxt/controller/GxtOrderScoreController.java

@@ -204,4 +204,24 @@ public class GxtOrderScoreController extends BaseController
             return AjaxResult.error(e.getMessage());
         }
     }
+    
+    /**
+     * 发起申诉
+     */
+    @PreAuthorize("@ss.hasPermi('gxt:orderScore:appeal')")
+    @Log(title = "工单评分", businessType = BusinessType.UPDATE)
+    @ApiOperation("发起申诉")
+    @PutMapping("/appeal")
+    public AjaxResult appeal(@RequestBody OrderScoreInfo orderScoreInfo)
+    {
+        try {
+            int result = gxtOrderScoreService.appeal(orderScoreInfo);
+            if (result > 0) {
+                return toAjax(result);
+            }
+            return AjaxResult.error("无效的工单类型");
+        } catch (Exception e) {
+            return AjaxResult.error(e.getMessage());
+        }
+    }
 }

+ 48 - 2
ygtx-gxt/src/main/java/com/ygtx/gxt/domain/GxtRepairOrder.java

@@ -179,7 +179,7 @@ public class GxtRepairOrder extends BaseEntity
 //    @Excel(name = "恢复时间", dateFormat = "yyyy-MM-dd HH:mm")
     private Date restartTime;
 
-    /** 评分状态(to_self-待自评,to_re-待复评,to_confirm-待确认,to_final-待终评,to_archive-待归档,archived-已归档) */
+    /** 评分状态(to_self-待自评,to_re-待复评,to_confirm-待确认,to_final-待终评,to_archive-待归档,archived-已归档,appealing-申诉中) */
     private String scoringStatus;
     
     /** 复评次数 */
@@ -223,7 +223,7 @@ public class GxtRepairOrder extends BaseEntity
     /** 反馈理由 */
     private String feedbackReason;
 
-    /** 确认状态(0-未确认,1-确认,2-已反馈) */
+    /** 确认状态(0-未确认,1-确认,2-已反馈,3-已申诉) */
     private Integer confirmStatus;
 
     /** 外委人员数 */
@@ -251,6 +251,19 @@ public class GxtRepairOrder extends BaseEntity
 
     private String homePageParam;
 
+    /** 申诉人用户ID */
+    private Long appealUserId;
+
+    /** 申诉人姓名 */
+    private String appealUserName;
+
+    /** 申诉时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
+    private Date appealTime;
+
+    /** 申诉理由 */
+    private String appealReason;
+
     public void setId(Long id) 
     {
         this.id = id;
@@ -859,6 +872,38 @@ public class GxtRepairOrder extends BaseEntity
         this.homePageParam = homePageParam;
     }
 
+    public String getAppealUserName() {
+        return appealUserName;
+    }
+
+    public void setAppealUserName(String appealUserName) {
+        this.appealUserName = appealUserName;
+    }
+
+    public Date getAppealTime() {
+        return appealTime;
+    }
+
+    public void setAppealTime(Date appealTime) {
+        this.appealTime = appealTime;
+    }
+
+    public String getAppealReason() {
+        return appealReason;
+    }
+
+    public void setAppealReason(String appealReason) {
+        this.appealReason = appealReason;
+    }
+
+    public Long getAppealUserId() {
+        return appealUserId;
+    }
+
+    public void setAppealUserId(Long appealUserId) {
+        this.appealUserId = appealUserId;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -906,6 +951,7 @@ public class GxtRepairOrder extends BaseEntity
             .append("repairMethod", getRepairMethod())
             .append("resetMethod", getResetMethod())
             .append("invalidReason", getInvalidReason())
+            .append("appealReason", getAppealReason())
             .toString();
     }
 }

+ 1 - 1
ygtx-gxt/src/main/java/com/ygtx/gxt/domain/GxtRepairOrderFlow.java

@@ -28,7 +28,7 @@ public class GxtRepairOrderFlow extends BaseEntity
     @Excel(name = "工单编码")
     private String orderCode;
 
-    /** 操作类型:create-创建工单,assign-下发工单,accept-接单,process-处理工单,pause-暂停,suspend-挂起,restart-重启,approve-审批,complete-完成工单,create_to_assign-创建并下发工单,to_approve-申请挂起工单,approved-挂起审批通过,rejected-挂起审批驳回,rating-工单评分,restart-设备恢复运行,archive-工单归档,to_archive-工单待归档,invalid-作废工单 ,selfRating-工单自评 ,reviewRating-工单复评,finalRating-工单终评 ,confirmRating-评分确认 ,feedbackRating-评分反馈 */
+    /** 操作类型:create-创建工单,assign-下发工单,accept-接单,process-处理工单,pause-暂停,suspend-挂起,restart-重启,approve-审批,complete-完成工单,create_to_assign-创建并下发工单,to_approve-申请挂起工单,approved-挂起审批通过,rejected-挂起审批驳回,rating-工单评分,restart-设备恢复运行,archive-工单归档,to_archive-工单待归档,invalid-作废工单 ,selfRating-工单自评 ,reviewRating-工单复评,finalRating-工单终评 ,confirmRating-评分确认 ,feedbackRating-评分反馈 ,appealRating-评分申诉*/
     //@Excel(name = "操作类型:create-创建工单,assign-下发工单,accept-接单,process-处理工单,pause-暂停,suspend-挂起,restart-重启,approve-审批,complete-完成工单,create_to_assign-创建并下发工单,to_approve-申请挂起工单,approved-挂起审批通过,rejected-挂起审批驳回,rating-工单评分")
     private String actionType;
 

+ 21 - 0
ygtx-gxt/src/main/java/com/ygtx/gxt/domain/OrderScoreInfo.java

@@ -182,6 +182,9 @@ public class OrderScoreInfo {
     /** 反馈理由 */
     private String feedbackReason;
 
+    /** 申诉理由 - 仅维修工单有此字段 */
+    private String appealReason;
+
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
     private Date createTime;
 
@@ -653,6 +656,24 @@ public class OrderScoreInfo {
         this.feedbackReason = feedbackReason;
     }
 
+    /**
+     * 获取申诉理由 - 仅维修工单有此字段
+     *
+     * @return 申诉理由
+     */
+    public String getAppealReason() {
+        return appealReason;
+    }
+
+    /**
+     * 设置申诉理由 - 仅维修工单有此字段
+     *
+     * @param appealReason 申诉理由
+     */
+    public void setAppealReason(String appealReason) {
+        this.appealReason = appealReason;
+    }
+
     public Date getCreateTime() {
         return createTime;
     }

+ 9 - 1
ygtx-gxt/src/main/java/com/ygtx/gxt/service/IGxtOrderScoreService.java

@@ -66,6 +66,14 @@ public interface IGxtOrderScoreService {
      */
     public int confirm(OrderScoreInfo orderScoreInfo);
 
+    /**
+     * 发起申诉
+     *
+     * @param orderScoreInfo 工单评分信息
+     * @return 结果
+     */
+    public int appeal(OrderScoreInfo orderScoreInfo);
+
     /**
      * 查询合并的工单列表(维修工单和维保工单)
      *
@@ -76,4 +84,4 @@ public interface IGxtOrderScoreService {
     public List<OrderScoreInfo> selectMobileUnionOrderList(GxtRepairOrder repairOrder, GxtWorkOrder workOrder, String keyword);
 
     public List<OrderScoreInfo> selectMobileUnionOrderList(Long userId, GxtRepairOrder repairOrder, GxtWorkOrder workOrder, String keyword);
-}
+}

+ 149 - 3
ygtx-gxt/src/main/java/com/ygtx/gxt/service/impl/GxtOrderScoreServiceImpl.java

@@ -22,6 +22,8 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Calendar;
+import java.util.Date;
 
 /**
  * 工单评分Service业务层处理
@@ -587,12 +589,18 @@ public class GxtOrderScoreServiceImpl implements IGxtOrderScoreService {
                 order.setMaintenanceType(orderScoreInfo.getMaintenanceType());
                 order.setModifyReason(orderScoreInfo.getModifyReason());
                 order.setReviewScoreNum(orderScoreInfo.getReviewScoreNum());
-                if(orderScoreInfo.getReviewScoreNum() == 1){
+                /*if(orderScoreInfo.getReviewScoreNum() == 1){
                     order.setScoringStatus("to_confirm");
                 }else if(orderScoreInfo.getReviewScoreNum() == 2){
                     order.setScoringStatus("to_final");
-                }
+                }*/
 
+                if(oldOrder.getRestartTime() != null){
+                    order.setScoringStatus("archived");
+                    order.setWorkOrderStatus("archived");
+                }else{
+                    order.setScoringStatus("to_archive");
+                }
                 // 计算复评总分并设置到工单对象
                 if (orderScoreInfo.getScorePersonList() != null) {
                     double totalScore = orderScoreInfo.getScorePersonList().stream()
@@ -631,6 +639,21 @@ public class GxtOrderScoreServiceImpl implements IGxtOrderScoreService {
                 flow.setActionRemark("提交复评");
                 repairOrderFlowService.insertGxtRepairOrderFlow(flow);
 
+                if("archived".equals(order.getWorkOrderStatus())){
+                    // 添加归档流程记录
+                    flow = new GxtRepairOrderFlow();
+                    flow.setOrderId(order.getId());
+                    flow.setOrderCode(orderScoreInfo.getWorkOrderProjectNo());
+                    flow.setActionType("archive");
+                    flow.setFromStatus("to_archive");
+                    flow.setToStatus("archived");
+                    flow.setOperatorId(1L); // 系统自动操作,使用系统用户ID
+                    flow.setOperatorName("系统自动");
+                    flow.setActionTime(DateUtils.getNowDate());
+                    flow.setActionRemark("系统自动归档工单");
+                    repairOrderFlowService.insertGxtRepairOrderFlow(flow);
+                }
+
                 return result;
             } else if (orderScoreInfo.getOrderType() == 2) {
                 // 维保工单复评
@@ -996,6 +1019,129 @@ public class GxtOrderScoreServiceImpl implements IGxtOrderScoreService {
         }
     }
 
+    /**
+     * 发起申诉
+     *
+     * @param orderScoreInfo 工单评分信息
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int appeal(OrderScoreInfo orderScoreInfo) {
+        try {
+            GxtRepairOrder order = gxtRepairOrderService.selectGxtRepairOrderById(orderScoreInfo.getId());
+            /*
+            // 只有维修工单能发起申诉
+            if (orderScoreInfo.getOrderType() != 1) {
+                throw new RuntimeException("只有维修工单才能发起申诉");
+            }
+
+            // 检查申诉时效性(本月工单或上月工单延期5天)
+            if (order.getRealEndTime() == null) {
+                throw new RuntimeException("工单尚未完成,不能发起申诉");
+            }
+
+            Calendar now = Calendar.getInstance();
+            Calendar orderEnd = Calendar.getInstance();
+            orderEnd.setTime(order.getRealEndTime());
+
+            // 当前月份和年份
+            int currentYear = now.get(Calendar.YEAR);
+            int currentMonth = now.get(Calendar.MONTH);
+            int currentDay = now.get(Calendar.DAY_OF_MONTH);
+
+            // 工单完成月份和年份
+            int orderYear = orderEnd.get(Calendar.YEAR);
+            int orderMonth = orderEnd.get(Calendar.MONTH);
+
+            // 判断是否符合申诉时效
+            boolean isValidAppealPeriod = false;
+            if (currentYear == orderYear && currentMonth == orderMonth) {
+                // 本月工单
+                isValidAppealPeriod = true;
+            } else if (currentYear == orderYear && currentMonth == orderMonth + 1) {
+                // 上月工单,在本月5号之前可申诉
+                if (currentDay <= 5) {
+                    isValidAppealPeriod = true;
+                }
+            } else if (currentYear == orderYear + 1 && currentMonth == 0 && orderMonth == 11) {
+                // 跨年情况:当前1月,工单完成于上年12月,在1月5号之前可申诉
+                if (currentDay <= 5) {
+                    isValidAppealPeriod = true;
+                }
+            }
+
+            if (!isValidAppealPeriod) {
+                throw new RuntimeException("超出申诉时效,不能发起申诉");
+            }
+
+            // 检查工单状态是否为"待归档"或"已归档"
+            String scoringStatus = order.getScoringStatus();
+            if (!"to_archive".equals(scoringStatus) && !"archived".equals(scoringStatus)) {
+                throw new RuntimeException("只有状态为\"待归档\"或\"已归档\"的工单才能发起申诉");
+            }
+
+            // 检查是否已经申诉过(通过confirmStatus字段判断)
+            if (order.getConfirmStatus() != null && order.getConfirmStatus() == 3) {
+                throw new RuntimeException("该工单已经发起过申诉,不能重复申诉");
+            }
+
+            // 检查当前用户是否有权限发起申诉(工作负责人或检修人员)
+            Long currentUserId = SecurityUtils.getUserId();
+            boolean hasPermission = false;
+            
+            // 检查是否为工作负责人
+            if (order.getTeamLeaderId() != null && order.getTeamLeaderId().equals(currentUserId)) {
+                hasPermission = true;
+            }
+            
+            // 检查是否为检修人员
+            if (!hasPermission) {
+                List<GxtRepairOrderPerson> persons = gxtRepairOrderService.selectRepairOrderPersonListByOrderId(orderScoreInfo.getId());
+                for (GxtRepairOrderPerson person : persons) {
+                    if (person.getUserId() != null && person.getUserId().equals(currentUserId)) {
+                        hasPermission = true;
+                        break;
+                    }
+                }
+            }
+
+            if (!hasPermission) {
+                throw new RuntimeException("您没有权限对此工单发起申诉");
+            }
+            */
+            // 更新工单状态为申诉中
+            GxtRepairOrder updateOrder = new GxtRepairOrder();
+            updateOrder.setId(orderScoreInfo.getId());
+            updateOrder.setConfirmStatus(3); // 使用confirmStatus字段标记为已申诉(值为3)
+            updateOrder.setAppealReason(orderScoreInfo.getAppealReason());
+            updateOrder.setScoringStatus("appealing"); // 申诉中状态
+            updateOrder.setAppealUserId(SecurityUtils.getUserId());
+            updateOrder.setAppealUserName(SecurityUtils.getLoginUser().getUser().getNickName());
+            updateOrder.setAppealTime(DateUtils.getNowDate());
+            int result = gxtRepairOrderService.updateGxtRepairOrderForScore(updateOrder);
+
+            // 添加工单流转记录
+            GxtRepairOrderFlow flow = new GxtRepairOrderFlow();
+            flow.setOrderId(orderScoreInfo.getId());
+            flow.setOrderCode(order.getWorkOrderProjectNo());
+            flow.setActionType("appealRating");
+            flow.setFromStatus(order.getWorkOrderStatus());
+            flow.setToStatus(order.getWorkOrderStatus());
+            flow.setFromScoreStatus(order.getScoringStatus());
+            flow.setToScoreStatus("appealing");
+            flow.setOperatorId(SecurityUtils.getUserId());
+            flow.setOperatorName(SecurityUtils.getLoginUser().getUser().getNickName());
+            flow.setActionTime(DateUtils.getNowDate());
+            flow.setActionRemark("发起申诉:" + orderScoreInfo.getFeedbackReason());
+            repairOrderFlowService.insertGxtRepairOrderFlow(flow);
+
+            return result;
+        } catch (Exception e) {
+            throw new RuntimeException("发起申诉失败:" + e.getMessage(), e);
+        }
+    }
+
     @Override
     public List<OrderScoreInfo> selectMobileUnionOrderList(GxtRepairOrder repairOrder, GxtWorkOrder workOrder, String keyword) {
         return selectMobileUnionOrderList(null, repairOrder, workOrder, keyword);
@@ -1496,4 +1642,4 @@ public class GxtOrderScoreServiceImpl implements IGxtOrderScoreService {
 
         return filteredOrders;
     }
-}
+}

+ 14 - 12
ygtx-gxt/src/main/resources/mapper/gxt/GxtOrderScoreMapper.xml

@@ -58,6 +58,8 @@
         <result property="updateTime"    column="update_time"    />
         <result property="feedbackReason"    column="feedback_reason"    />
         <result property="confirmStatus"    column="confirm_status"    />
+        <!-- 申诉理由 - 仅维修工单有此字段 -->
+        <result property="appealReason"    column="appeal_reason"    />
     </resultMap>
 
     <select id="selectUnionOrderList" resultMap="OrderScoreInfoResult">
@@ -113,7 +115,8 @@
                 feedback_reason as feedback_reason,
                 confirm_status as confirm_status,
                 create_time as create_time,
-                update_time as update_time
+                update_time as update_time,
+                appeal_reason as appeal_reason
             FROM gxt_repair_order t
             <where>
                 <if test="keyword != null and keyword != ''">
@@ -195,7 +198,8 @@
                 feedback_reason as feedback_reason,
                 confirm_status as confirm_status,
                 create_time as create_time,
-                update_time as update_time
+                update_time as update_time,
+                null as appeal_reason
             FROM gxt_work_order t
             <where>
                 <if test="keyword != null and keyword != ''">
@@ -279,7 +283,8 @@
         feedback_reason as feedback_reason,
         confirm_status as confirm_status,
         create_time as create_time,
-        update_time as update_time
+        update_time as update_time,
+        appeal_reason as appeal_reason
         FROM gxt_repair_order t
         <where>
             <if test="keyword != null and keyword != ''">
@@ -367,7 +372,8 @@
         feedback_reason as feedback_reason,
         confirm_status as confirm_status,
         create_time as create_time,
-        update_time as update_time
+        update_time as update_time,
+        null as appeal_reason
         FROM gxt_work_order t
         <where>
             <if test="keyword != null and keyword != ''">
@@ -421,10 +427,8 @@
                     AND wrk.user_id = #{workOrder.params.currentUserId}
                 </if>
             <where>
-                t.scoring_status IS NOT NULL AND t.scoring_status != '' AND t.work_order_status != 'invalid'
-                <if test="workOrder.scoringStatus != null and workOrder.scoringStatus != ''"> 
-                    AND t.scoring_status = #{workOrder.scoringStatus}
-                </if>
+                t.scoring_status IS NOT NULL AND (t.scoring_status = 'to_archive' OR t.scoring_status = 'archived') AND t.work_order_status != 'invalid'
+
                 <if test="month != null and month != ''">
                     AND DATE_FORMAT(t.create_time, '%Y-%m') = #{month}
                 </if>
@@ -446,10 +450,8 @@
                     AND rep.user_id = #{repairOrder.params.currentUserId}
                 </if>
             <where>
-                t.scoring_status IS NOT NULL AND t.scoring_status != '' AND t.work_order_status != 'invalid'
-                <if test="repairOrder.scoringStatus != null and repairOrder.scoringStatus != ''"> 
-                    AND t.scoring_status = #{repairOrder.scoringStatus}
-                </if>
+                t.scoring_status IS NOT NULL AND (t.scoring_status = 'to_archive' OR t.scoring_status = 'archived') AND t.work_order_status != 'invalid'
+
                 <if test="month != null and month != ''">
                     AND DATE_FORMAT(t.occur_time, '%Y-%m') = #{month}
                 </if>

+ 17 - 1
ygtx-gxt/src/main/resources/mapper/gxt/GxtRepairOrderMapper.xml

@@ -73,6 +73,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="realFailureReason"    column="real_failure_reason"    />
         <result property="lostPower"    column="lost_power"    />
         <result property="workPermitNum"    column="work_permit_num"    />
+        <result property="appealUserName"    column="appeal_user_name"    />
+        <result property="appealUserId"    column="appeal_user_id"    />
+        <result property="appealTime"    column="appeal_time"    />
+        <result property="appealReason"    column="appeal_reason"    />
     </resultMap>
 
     <resultMap type="GxtRepairOrder" id="GxtRepairOrderWithPersonResult" extends="GxtRepairOrderResult">
@@ -110,7 +114,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                review_content, maintenance_type, occur_time, fault_barcode, suspend_reason, suspend_description, approval_status,
                rejection_reason, modify_reason, finalization_remark, related_order_code, related_order_content, mis_order_no, restart_time,
                scoring_status, pcs_station_pid, attachment_urls, review_score_num, final_coefficient, order_type, repair_method, reset_method, invalid_reason, return_type, return_reason, feedback_reason, confirm_status,
-               wwry_num, wlry_num, work_area, info_entry, real_failure_reason, lost_power, work_permit_num
+               wwry_num, wlry_num, work_area, info_entry, real_failure_reason, lost_power, work_permit_num, appeal_user_name, appeal_user_id, appeal_time, appeal_reason
         from gxt_repair_order t
         left join sys_user u on u.user_name = t.create_by
         left join sys_dept d on u.dept_id = d.dept_id
@@ -268,6 +272,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="realFailureReason != null and realFailureReason != ''">real_failure_reason,</if>
             <if test="lostPower != null">lost_power,</if>
             <if test="workPermitNum != null and workPermitNum != ''">work_permit_num,</if>
+            <if test="appealUserName != null and appealUserName != ''">appeal_user_name,</if>
+            <if test="appealUserId != null">appeal_user_id,</if>
+            <if test="appealTime != null">appeal_time,</if>
+            <if test="appealReason != null and appealReason != ''">appeal_reason,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="workOrderProjectNo != null and workOrderProjectNo != ''">#{workOrderProjectNo},</if>
@@ -337,6 +345,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="realFailureReason != null and realFailureReason != ''">#{realFailureReason},</if>
             <if test="lostPower != null">#{lostPower},</if>
             <if test="workPermitNum != null and workPermitNum != ''">#{workPermitNum},</if>
+            <if test="appealUserName != null and appealUserName != ''">#{appealUserName},</if>
+            <if test="appealUserId != null">#{appealUserId},</if>
+            <if test="appealTime != null">#{appealTime},</if>
+            <if test="appealReason != null and appealReason != ''">#{appealReason},</if>
          </trim>
     </insert>
 
@@ -410,6 +422,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="realFailureReason != null and realFailureReason != ''">real_failure_reason = #{realFailureReason},</if>
             <if test="lostPower != null">lost_power = #{lostPower},</if>
             <if test="workPermitNum != null and workPermitNum != ''">work_permit_num = #{workPermitNum},</if>
+            <if test="appealUserName != null and appealUserName != ''">appeal_user_name = #{appealUserName},</if>
+            <if test="appealUserId != null">appeal_user_id = #{appealUserId},</if>
+            <if test="appealTime != null">appeal_time = #{appealTime},</if>
+            <if test="appealReason != null and appealReason != ''">appeal_reason = #{appealReason},</if>
         </trim>
         where id = #{id}
     </update>

+ 9 - 0
ygtx-ui/src/api/gxt/orderScore.js

@@ -51,4 +51,13 @@ export function finalEvaluation(data) {
     method: 'put',
     data: data
   })
+}
+
+// 发起申诉
+export function appeal(data) {
+  return request({
+    url: '/gxt/orderScore/appeal',
+    method: 'put',
+    data: data
+  })
 }

+ 516 - 99
ygtx-ui/src/views/gxt/orderScore/index.vue

@@ -82,7 +82,17 @@
       <el-button icon="Refresh" @click="resetQuery">重置</el-button>
       <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
     </div>
-
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+            type="danger"
+            icon=""
+            :disabled="!canAppeal"
+            @click="handleAppeal"
+            v-hasPermi="['gxt:orderScore:appeal']"
+        >发起申诉</el-button>
+      </el-col>
+    </el-row>
     <!-- 工单评分列表 -->
     <el-table
       v-loading="loading"
@@ -91,7 +101,7 @@
       style="width: 100%"
       :max-height="tableHeight"
     >
-<!--      <el-table-column type="selection" width="55" align="center" />-->
+      <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="工单编码" align="center" prop="workOrderProjectNo" :show-overflow-tooltip="true" />
       <el-table-column label="工单类型" align="center" prop="orderType" >
         <template #default="scope">
@@ -138,7 +148,7 @@
           <el-button
             type="success"
             link
-            v-if="scope.row.scoringStatus == 'to_final'"
+            v-if="scope.row.scoringStatus == 'to_final' || scope.row.scoringStatus == 'appealing'"
             @click="handleFinalEvaluation(scope.row)"
             v-hasPermi="['gxt:orderScore:finalEvaluation']"
           ><i class="fa fa-flag-checkered"></i>终评</el-button>
@@ -557,107 +567,233 @@
     <!-- 终评对话框 -->
     <el-dialog :title="finalEvaluationForm.orderType === 1 ? '维修工单终评' : '维保工单终评'" v-model="finalEvaluationDialogVisible" width="800px" append-to-body>
       <el-form ref="finalEvaluationRef" :model="finalEvaluationForm" :rules="finalEvaluationRules" label-width="120px" label-position="top">
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="工单编码">
-              <el-input v-model="finalEvaluationForm.workOrderProjectNo" disabled />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="风机编号">
-              <el-input v-model="finalEvaluationForm.pcsDeviceName" disabled />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="场站">
-              <el-input v-model="finalEvaluationForm.pcsStationName" disabled />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        
-        <el-form-item :label="finalEvaluationForm.orderType === 1 ? '维修总结' : '维保总结'">
-          <el-input
-            v-model="finalEvaluationForm.workSummary"
-            type="textarea"
-            disabled
-            :rows="4"
-          />
-        </el-form-item>
-        
-        <el-row :gutter="20">
-          <el-col :span="12" v-if="finalEvaluationForm.orderType === 1">
-            <el-form-item label="检修类型">
-              <el-select v-model="finalEvaluationForm.maintenanceType" disabled style="width: 100%">
-                <el-option
-                  v-for="item in maintenanceTypeOptions"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value">
-                </el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12" v-if="finalEvaluationForm.orderType === 2">
-            <el-form-item label="维保类型">
-              <el-select v-model="finalEvaluationForm.inspectionType" disabled style="width: 100%">
-                <el-option 
-                  v-for="item in inspectionTypeOptions" 
-                  :key="item.inspectionTypeId" 
-                  :label="getDictLabel(gxt_inspection_type, item.inspectionTypeId)" 
-                  :value="item.inspectionTypeId.toString()">
-                </el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="系数" prop="finalCoefficient">
-              <el-input-number 
-                v-model="finalEvaluationForm.finalCoefficient" 
-                :min="finalEvaluationForm.orderType === 1 ? 0.5 : 0.8" 
-                :max="finalEvaluationForm.orderType === 1 ? 1.5 : 1.2" 
-                :step="0.01" 
-                style="width: 100%"
-                controls-position="right"
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-form-item v-if="finalEvaluationForm.orderType === 1 && finalEvaluationForm.feedbackReason" label="反馈理由" prop="feedbackReason">
+        <template v-if="finalEvaluationForm.orderType === 2" >
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="工单编码">
+                <el-input v-model="finalEvaluationForm.workOrderProjectNo" disabled />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="风机编号">
+                <el-input v-model="finalEvaluationForm.pcsDeviceName" disabled />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="场站">
+                <el-input v-model="finalEvaluationForm.pcsStationName" disabled />
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-form-item :label="finalEvaluationForm.orderType === 1 ? '维修总结' : '维保总结'">
+            <el-input
+                v-model="finalEvaluationForm.workSummary"
+                type="textarea"
+                disabled
+                :rows="4"
+            />
+          </el-form-item>
+
+          <el-row :gutter="20">
+            <el-col :span="12" v-if="finalEvaluationForm.orderType === 1">
+              <el-form-item label="检修类型">
+                <el-select v-model="finalEvaluationForm.maintenanceType" disabled style="width: 100%">
+                  <el-option
+                      v-for="item in maintenanceTypeOptions"
+                      :key="item.value"
+                      :label="item.label"
+                      :value="item.value">
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" v-if="finalEvaluationForm.orderType === 2">
+              <el-form-item label="维保类型">
+                <el-select v-model="finalEvaluationForm.inspectionType" disabled style="width: 100%">
+                  <el-option
+                      v-for="item in inspectionTypeOptions"
+                      :key="item.inspectionTypeId"
+                      :label="getDictLabel(gxt_inspection_type, item.inspectionTypeId)"
+                      :value="item.inspectionTypeId.toString()">
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="系数" prop="finalCoefficient">
+                <el-input-number
+                    v-model="finalEvaluationForm.finalCoefficient"
+                    :min="finalEvaluationForm.orderType === 1 ? 0.5 : 0.8"
+                    :max="finalEvaluationForm.orderType === 1 ? 1.5 : 1.2"
+                    :step="0.01"
+                    style="width: 100%"
+                    controls-position="right"
+                />
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <!-- 维保工单保持原有样式 -->
+          <el-form-item label="得分明细">
+            <el-table :data="finalEvaluationForm.scorePersonList" border style="width: 100%;">
+              <el-table-column label="检修员" align="center" prop="nickName"  style="width: 50%;">
+                <template #default="scope">
+                  <span>{{ scope.row.nickName }}<span v-if="scope.row.isLeader == 1"> (工作负责人)</span></span>
+                </template>
+              </el-table-column>
+              <el-table-column label="自评得分" align="center" prop="selfScore">
+                <template #default="scope">
+                  <span>{{ scope.row.selfScore !== null && scope.row.selfScore !== undefined ? parseFloat(scope.row.selfScore).toFixed(2) : '' }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="复评得分" align="center" prop="reviewScore">
+                <template #default="scope">
+                  <span>{{ scope.row.reviewScore !== null && scope.row.reviewScore !== undefined ? parseFloat(scope.row.reviewScore).toFixed(2) : '' }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="终评得分" align="center" prop="finalScore">
+                <template #default="scope">
+                  <el-input v-model="scope.row.finalScore"
+                            :value="calculateFinalScore(scope.row.reviewScore, finalEvaluationForm.finalCoefficient)"
+                            readonly
+                            style="width: 100%;"
+                  />
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-form-item>
+        </template>
+
+<!--        <el-form-item v-if="finalEvaluationForm.orderType === 1 && finalEvaluationForm.feedbackReason" label="反馈理由" prop="feedbackReason">
           <el-input
               v-model="finalEvaluationForm.feedbackReason"
               type="textarea"
               :rows="3"
               disabled
           />
-        </el-form-item>
-        <el-form-item label="得分明细">
-          <el-table :data="finalEvaluationForm.scorePersonList" border style="width: 100%;">
-            <el-table-column label="检修员" align="center" prop="nickName"  style="width: 50%;">
-              <template #default="scope">
-                <span>{{ scope.row.nickName }}<span v-if="scope.row.isLeader == 1"> (工作负责人)</span></span>
-              </template>
-            </el-table-column>
-            <el-table-column label="自评得分" align="center" prop="selfScore">
-              <template #default="scope">
-                <span>{{ scope.row.selfScore !== null && scope.row.selfScore !== undefined ? parseFloat(scope.row.selfScore).toFixed(2) : '' }}</span>
-              </template>
-            </el-table-column>
-            <el-table-column label="复评得分" align="center" prop="reviewScore">
-              <template #default="scope">
-                <span>{{ scope.row.reviewScore !== null && scope.row.reviewScore !== undefined ? parseFloat(scope.row.reviewScore).toFixed(2) : '' }}</span>
-              </template>
-            </el-table-column>
-            <el-table-column label="终评得分" align="center" prop="finalScore">
-              <template #default="scope">
-                <el-input v-model="scope.row.finalScore"
-                  :value="calculateFinalScore(scope.row.reviewScore, finalEvaluationForm.finalCoefficient)" 
-                  readonly
-                  style="width: 100%;"
-                />
-              </template>
-            </el-table-column>
-          </el-table>
-        </el-form-item>
+        </el-form-item>-->
+        <!-- 维修工单终评界面添加标签页 -->
+        <el-tabs v-if="finalEvaluationForm.orderType === 1" v-model="activeFinalEvalTab">
+          <el-tab-pane label="终评信息" name="evaluation">
+            <el-row :gutter="20">
+              <el-col :span="8">
+                <el-form-item label="工单编码">
+                  <el-input v-model="finalEvaluationForm.workOrderProjectNo" disabled />
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="风机编号">
+                  <el-input v-model="finalEvaluationForm.pcsDeviceName" disabled />
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="场站">
+                  <el-input v-model="finalEvaluationForm.pcsStationName" disabled />
+                </el-form-item>
+              </el-col>
+            </el-row>
+
+            <el-form-item :label="finalEvaluationForm.orderType === 1 ? '维修总结' : '维保总结'">
+              <el-input
+                  v-model="finalEvaluationForm.workSummary"
+                  type="textarea"
+                  disabled
+                  :rows="4"
+              />
+            </el-form-item>
+
+            <el-row :gutter="20">
+              <el-col :span="12" v-if="finalEvaluationForm.orderType === 1">
+                <el-form-item label="检修类型">
+                  <el-select v-model="finalEvaluationForm.maintenanceType" disabled style="width: 100%">
+                    <el-option
+                        v-for="item in maintenanceTypeOptions"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value">
+                    </el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12" v-if="finalEvaluationForm.orderType === 2">
+                <el-form-item label="维保类型">
+                  <el-select v-model="finalEvaluationForm.inspectionType" disabled style="width: 100%">
+                    <el-option
+                        v-for="item in inspectionTypeOptions"
+                        :key="item.inspectionTypeId"
+                        :label="getDictLabel(gxt_inspection_type, item.inspectionTypeId)"
+                        :value="item.inspectionTypeId.toString()">
+                    </el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="系数" prop="finalCoefficient">
+                  <el-input-number
+                      v-model="finalEvaluationForm.finalCoefficient"
+                      :min="finalEvaluationForm.orderType === 1 ? 0.5 : 0.8"
+                      :max="finalEvaluationForm.orderType === 1 ? 1.5 : 1.2"
+                      :step="0.01"
+                      style="width: 100%"
+                      controls-position="right"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-form-item label="得分明细">
+              <el-table :data="finalEvaluationForm.scorePersonList" border style="width: 100%;">
+                <el-table-column label="检修员" align="center" prop="nickName"  style="width: 50%;">
+                  <template #default="scope">
+                    <span>{{ scope.row.nickName }}<span v-if="scope.row.isLeader == 1"> (工作负责人)</span></span>
+                  </template>
+                </el-table-column>
+                <el-table-column label="自评得分" align="center" prop="selfScore">
+                  <template #default="scope">
+                    <span>{{ scope.row.selfScore !== null && scope.row.selfScore !== undefined ? parseFloat(scope.row.selfScore).toFixed(2) : '' }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column label="复评得分" align="center" prop="reviewScore">
+                  <template #default="scope">
+                    <span>{{ scope.row.reviewScore !== null && scope.row.reviewScore !== undefined ? parseFloat(scope.row.reviewScore).toFixed(2) : '' }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column label="终评得分" align="center" prop="finalScore">
+                  <template #default="scope">
+                    <el-input v-model="scope.row.finalScore"
+                      :value="calculateFinalScore(scope.row.reviewScore, finalEvaluationForm.finalCoefficient)" 
+                      readonly
+                      style="width: 100%;"
+                    />
+                  </template>
+                </el-table-column>
+              </el-table>
+            </el-form-item>
+          </el-tab-pane>
+          <el-tab-pane label="申诉信息" name="appeal">
+            <el-form-item label="申诉理由">
+              <el-input
+                v-model="finalEvaluationForm.appealReason"
+                type="textarea"
+                :rows="4"
+                disabled
+              />
+            </el-form-item>
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="申诉人">
+                  <el-input v-model="finalEvaluationForm.appealUserName" disabled />
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="申诉时间">
+                  <el-input v-model="finalEvaluationForm.appealTime" disabled />
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </el-tab-pane>
+        </el-tabs>
+
       </el-form>
       
       <template #footer>
@@ -832,6 +968,63 @@
         </div>
       </template>
     </el-dialog>
+    
+    <!-- 申诉对话框 -->
+    <el-dialog title="发起申诉" v-model="appealDialogVisible" width="800px" append-to-body>
+      <el-form ref="appealRef" :model="appealForm" :rules="appealRules" label-width="120px" label-position="top">
+        <el-alert type="info" :closable="false" style="margin-bottom: 20px;">
+          发起申诉操作,请输入申诉理由
+        </el-alert>
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="工单编码">
+              <el-input v-model="appealForm.workOrderProjectNo" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="风机编号">
+              <el-input v-model="appealForm.pcsDeviceName" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="场站">
+              <el-input v-model="appealForm.pcsStationName" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="发生时间">
+              <el-input v-model="appealForm.occurTime" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="原得分">
+              <el-input v-model="appealForm.originalScore" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <el-form-item label="申诉理由" prop="appealReason">
+          <el-input
+            v-model="appealForm.appealReason"
+            type="textarea"
+            placeholder="请输入申诉理由"
+            maxlength="500"
+            show-word-limit
+            :rows="6"
+          />
+        </el-form-item>
+      </el-form>
+      
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="closeAppealDialog">取 消</el-button>
+          <el-button type="primary" @click="submitAppeal">提交申诉</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
@@ -842,7 +1035,8 @@ import {
   selfEvaluation, 
   review, 
   confirm,
-  finalEvaluation 
+  finalEvaluation,
+  appeal
 } from "@/api/gxt/orderScore";
 import { listScoreproject } from "@/api/gxt/scoreproject";
 import { listMaintenanceCenters, listStationsByMaintenanceCenter } from "@/api/gxt/equipment"
@@ -872,6 +1066,7 @@ const selfEvaluationDialogVisible = ref(false);
 const reviewDialogVisible = ref(false);
 const confirmDialogVisible = ref(false);
 const finalEvaluationDialogVisible = ref(false);
+const appealDialogVisible = ref(false); // 申诉对话框
 
 // 表单相关
 const queryRef = ref(null);
@@ -879,6 +1074,10 @@ const selfEvaluationRef = ref(null);
 const reviewRef = ref(null);
 const confirmRef = ref(null);
 const finalEvaluationRef = ref(null);
+const appealRef = ref(null); // 申诉表单引用
+
+// 终评标签页控制
+const activeFinalEvalTab = ref('evaluation');
 
 // 各种表单数据
 const viewForm = ref({});
@@ -886,6 +1085,7 @@ const selfEvaluationForm = ref({});
 const reviewForm = ref({});
 const confirmForm = ref({});
 const finalEvaluationForm = ref({});
+const appealForm = ref({}); // 申诉表单
 
 // 人员列表
 const scorePersonList = ref([]);
@@ -974,6 +1174,13 @@ const confirmRules = ref({
   ]
 });
 
+// 申诉对话框表单验证规则
+const appealRules = ref({
+  appealReason: [
+    { required: true, message: "申诉理由不能为空", trigger: "blur" }
+  ]
+});
+
 // 维保中心和场站选项
 const maintenanceCenterOptions = ref([])
 const stationOptions = ref([])
@@ -996,6 +1203,21 @@ function getDictLabel(dictOptions, value) {
   return dict ? dict.label : '';
 }
 
+// 判断是否可以选择并发起申诉
+const canAppeal = computed(() => {
+  // 只有当选择了且仅选择了一个维修工单,并且该工单状态为"待归档"或"已归档"时才允许发起申诉
+  if (ids.value.length !== 1) return false;
+  
+  const selectedOrder = orderScoreList.value.find(item => item.id === ids.value[0]);
+  if (!selectedOrder) return false;
+  
+  // 只有维修工单(orderType=1)才能发起申诉
+  if (selectedOrder.orderType !== 1) return false;
+  
+  // 只有待归档(to_archive)或已归档(archived)状态才能发起申诉
+  return selectedOrder.scoringStatus === 'to_archive' || selectedOrder.scoringStatus === 'archived';
+});
+
 onMounted(() => {
   getList();
   getMaintenanceCenterAndStationList();
@@ -1650,6 +1872,10 @@ function handleFinalEvaluation(row) {
       scorePersonList: row.orderType === 1 ? (data.repairOrderPersonList || []) : (data.workOrderPersonList || []),
       feedbackReason: row.orderType === 1 ? data.feedbackReason : null,
       confirmStatus: data.confirmStatus,
+      // 申诉相关信息
+      appealReason: data.appealReason,
+      appealUserName: data.appealUserName,
+      appealTime: data.appealTime ? proxy.parseTime(data.appealTime, '{y}-{m}-{d} {h}:{i}') : null
     };
     
     // 如果是维保工单,根据风机型号获取维保类型选项
@@ -1662,6 +1888,9 @@ function handleFinalEvaluation(row) {
       });
     }
     
+    // 默认显示终评信息标签页
+    activeFinalEvalTab.value = 'evaluation';
+    
     finalEvaluationDialogVisible.value = true;
   });
 }
@@ -1697,6 +1926,169 @@ function submitFinalEvaluation() {
   });
 }
 
+/** 发起申诉操作 */
+function handleAppeal() {
+  // 获取选中的工单
+  const selectedOrder = orderScoreList.value.find(item => item.id === ids.value[0]);
+  if (!selectedOrder) {
+    proxy.$modal.msgError("未找到选中的工单");
+    return;
+  }
+  
+  // 检查是否为维修工单
+  if (selectedOrder.orderType !== 1) {
+    proxy.$modal.msgError("只有维修工单才能发起申诉");
+    return;
+  }
+  
+  // 检查工单状态是否为"待归档"或"已归档"
+  if (selectedOrder.scoringStatus !== 'to_archive' && selectedOrder.scoringStatus !== 'archived') {
+    proxy.$modal.msgError("只有状态为\"待归档\"或\"已归档\"的工单才能发起申诉");
+    return;
+  }
+  
+  // 检查申诉时效性(本月工单或上月工单延期5天)
+  const now = new Date();
+  //const orderEndDate = new Date(selectedOrder.realEndTime);
+  const orderEndDate = new Date(selectedOrder.occurTime);
+
+  // 当前月份和年份
+  const currentYear = now.getFullYear();
+  const currentMonth = now.getMonth();
+  const currentDay = now.getDate();
+  
+  // 工单完成月份和年份
+  const orderYear = orderEndDate.getFullYear();
+  const orderMonth = orderEndDate.getMonth();
+  
+  // 判断是否符合申诉时效
+  let isValidAppealPeriod = false;
+  if (currentYear === orderYear && currentMonth === orderMonth) {
+    // 本月工单
+    isValidAppealPeriod = true;
+  } else if (currentYear === orderYear && currentMonth === orderMonth + 1) {
+    // 上月工单,在本月5号之前可申诉
+    if (currentDay <= 5) {
+      isValidAppealPeriod = true;
+    }
+  } else if (currentYear === orderYear + 1 && currentMonth === 0 && orderMonth === 11) {
+    // 跨年情况:当前1月,工单完成于上年12月,在1月5号之前可申诉
+    if (currentDay <= 5) {
+      isValidAppealPeriod = true;
+    }
+  }
+  
+  if (!isValidAppealPeriod) {
+    proxy.$modal.msgError("超出申诉时效,不能发起申诉");
+    return;
+  }
+  
+  // 检查是否已经申诉过(通过confirmStatus字段判断)
+  if(selectedOrder.confirmStatus == 3){
+    proxy.$modal.msgError("该工单已申诉,不能发起申诉");
+    return;
+  }
+  
+  // 检查当前用户是否有权限发起申诉(工作负责人或检修人员)
+  const currentUserId = userStore.id;
+  let hasPermission = false;
+  hasPermission = isUserInScoreList(selectedOrder)
+  
+  // 检查是否为工作负责人
+  /*if (selectedOrder.teamLeaderId && selectedOrder.teamLeaderId === currentUserId) {
+    hasPermission = true;
+  }*/
+  
+  // 检查是否为检修人员(需要获取工单详细信息)
+  /*if (!hasPermission) {
+    getOrderScore(selectedOrder.orderType, selectedOrder.id).then(response => {
+      const data = response.data;
+      const persons = data.repairOrderPersonList || [];
+      
+      // 检查当前用户是否在检修人员列表中
+      for (const person of persons) {
+        if (person.userId && person.userId === currentUserId) {
+          hasPermission = true;
+          break;
+        }
+      }
+      
+      if (!hasPermission) {
+        proxy.$modal.msgError("您没有权限对此工单发起申诉");
+        return;
+      }
+      
+      // 初始化申诉表单
+      appealForm.value = {
+        orderType: selectedOrder.orderType,
+        id: selectedOrder.id,
+        workOrderProjectNo: selectedOrder.workOrderProjectNo,
+        pcsDeviceName: selectedOrder.pcsDeviceName,
+        pcsStationName: selectedOrder.pcsStationName,
+        occurTime: proxy.parseTime(selectedOrder.realEndTime, '{y}-{m}-{d} {h}:{i}'),
+        originalScore: getReviewerScore(data),
+        appealReason: ''
+      };
+      
+      // 显示申诉对话框
+      appealDialogVisible.value = true;
+    });
+    return;
+  }*/
+  if (!hasPermission) {
+    proxy.$modal.msgError("您没有权限对此工单发起申诉");
+    return;
+  }
+
+  // 获取工单详细信息
+  getOrderScore(selectedOrder.orderType, selectedOrder.id).then(response => {
+    const data = response.data;
+    
+    // 初始化申诉表单
+    appealForm.value = {
+      orderType: selectedOrder.orderType,
+      id: selectedOrder.id,
+      workOrderProjectNo: selectedOrder.workOrderProjectNo,
+      pcsDeviceName: selectedOrder.pcsDeviceName,
+      pcsStationName: selectedOrder.pcsStationName,
+      occurTime: proxy.parseTime(selectedOrder.realEndTime, '{y}-{m}-{d} {h}:{i}'),
+      originalScore: getReviewerScore(data),
+      appealReason: ''
+    };
+    
+    // 显示申诉对话框
+    appealDialogVisible.value = true;
+  });
+}
+
+/** 关闭申诉对话框 */
+function closeAppealDialog() {
+  appealDialogVisible.value = false;
+  proxy.resetForm("appealRef");
+}
+
+/** 提交申诉 */
+function submitAppeal() {
+  proxy.$refs["appealRef"].validate(valid => {
+    if (valid) {
+      // 将申诉理由作为feedbackReason传递给后端
+      const appealData = {
+        orderType: appealForm.value.orderType,
+        id: appealForm.value.id,
+        appealReason: appealForm.value.appealReason, // 使用appealReason字段存储申诉理由
+      };
+
+      appeal(appealData).then(response => {
+        proxy.$modal.msgSuccess("申诉提交成功");
+        appealDialogVisible.value = false;
+        getList();
+      }).catch(error => {
+        proxy.$modal.msgError(error.message || "申诉提交失败");
+      });
+    }
+  });
+}
+
 /** 判断用户是否在工单的评分人员列表中 */
 function isUserInScoreList(row) {
   // 获取工单的评分人员列表
@@ -1731,6 +2123,31 @@ function isUserConfirmed(row) {
   return false;
 }
 
+// 获取当前用户的复评分数
+function getReviewerScore(data) {
+  // 获取当前登录用户ID
+  const currentUserId = userStore.id;
+  
+  // 检查维修工单人员列表
+  if (data.repairOrderPersonList && Array.isArray(data.repairOrderPersonList)) {
+    const person = data.repairOrderPersonList.find(p => p.userId == currentUserId);
+    if (person && person.reviewScore !== null && person.reviewScore !== undefined) {
+      return parseFloat(person.reviewScore).toFixed(2);
+    }
+  }
+  
+  // 检查维保工单人员列表
+  if (data.workOrderPersonList && Array.isArray(data.workOrderPersonList)) {
+    const person = data.workOrderPersonList.find(p => p.userId == currentUserId);
+    if (person && person.reviewScore !== null && person.reviewScore !== undefined) {
+      return parseFloat(person.reviewScore).toFixed(2);
+    }
+  }
+  
+  // 如果没找到复评分数,则返回空字符串
+  return '';
+}
+
 function getMaintenanceCenterAndStationList() {
   listMaintenanceCenters().then(response => {
     maintenanceCenterOptions.value = response.data.map(item => {