fuliqi
2024-08-22 6dd308df5a1a288f6de850a43c6479d41638083b
Merge remote-tracking branch 'origin/master'
13个文件已修改
203 ■■■■ 已修改文件
ycl-common/src/main/java/enumeration/general/ErrorTypeEnum.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-pojo/src/main/java/com/ycl/platform/domain/form/WorkOrderForm.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/mapper/YwPointMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/WorkOrderServiceImpl.java 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/YwPointServiceImpl.java 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/application-dev.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/application-prod.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/mapper/zgyw/CheckIndexCarMapper.xml 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/mapper/zgyw/CheckIndexFaceMapper.xml 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/mapper/zgyw/CheckIndexVideoMapper.xml 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/mapper/zgyw/WorkOrderMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/mapper/zgyw/YwPointMapper.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-common/src/main/java/enumeration/general/ErrorTypeEnum.java
@@ -36,4 +36,17 @@
        this.value = value;
    }
    public static String getEnumValue(String value) {
        String[] values = value.split(",");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < values.length; i++) {
            sb.append(ErrorTypeEnum.valueOf(values[i]).getValue());
            if (i != values.length - 1) {
                sb.append(",");
            }
        }
        return sb.toString();
    }
}
ycl-pojo/src/main/java/com/ycl/platform/domain/form/WorkOrderForm.java
@@ -4,7 +4,6 @@
import com.ycl.platform.domain.entity.WorkOrder;
import com.ycl.system.domain.group.Add;
import com.ycl.system.domain.group.Update;
import enumeration.general.ErrorTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import jakarta.validation.constraints.NotBlank;
@@ -47,7 +46,7 @@
    @NotEmpty(message = "故障类型不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("故障类型")
    private List<ErrorTypeEnum> errorType;
    private List<String> errorType;
    // @NotNull(message = "运维人员不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("运维人员")
ycl-server/src/main/java/com/ycl/platform/mapper/YwPointMapper.java
@@ -55,7 +55,7 @@
    /**
     * 更新点位信息
     *
     * @param point
     * @param pointList
     */
    int updatePoint(@Param("point") YwPoint point);
    int updatePoint(List<YwPoint> pointList);
}
ycl-server/src/main/java/com/ycl/platform/service/impl/WorkOrderServiceImpl.java
@@ -28,7 +28,10 @@
import com.ycl.platform.wvp.WVPResult;
import com.ycl.system.Result;
import com.ycl.system.domain.SysConfig;
import com.ycl.system.entity.SysDictData;
import com.ycl.system.mapper.SysConfigMapper;
import com.ycl.system.mapper.SysDictDataMapper;
import com.ycl.system.mapper.SysDictTypeMapper;
import com.ycl.system.model.LoginUser;
import com.ycl.system.page.PageUtil;
import com.ycl.utils.DateUtils;
@@ -84,6 +87,7 @@
    private final SysConfigMapper configMapper;
    private final ServerConfig serverConfig;
    private final ReportMapper reportMapper;
    private final SysDictDataMapper dictDataMapper;
    @Value("${rtsp.server:http://127.0.0.1:7788}")
    private String rtspServer;
@@ -118,16 +122,31 @@
        for (WorkOrder workOrder : workOrderList) {
            WorkOrder databaseWorkOrder = mapping.get(workOrder.getSerialNumber());
            if (Objects.nonNull(databaseWorkOrder)) {
                List<WorkOrderErrorType> workOrderErrorTypeList = new LambdaQueryChainWrapper<>(workOrderErrorTypeMapper)
                        .select(WorkOrderErrorType::getErrorName)
                        .eq(WorkOrderErrorType::getWorkOrderNo, workOrder.getWorkOrderNo())
                        .list();
                List<String> errorNameList = workOrderErrorTypeList.stream().map(WorkOrderErrorType::getErrorName).collect(Collectors.toList());
                String errorType = databaseWorkOrder.getErrorType();
                if (workOrder.getErrorType().equals(errorType)) {
                if (errorNameList.contains(errorType)) {
                    // 如果,国标码、故障类型都一样,则跳过不处理
                    continue;
                } else {
                    // 错误类型不一样,就更新错误类型,并且重置工单状态为待处理
                    errorType = errorType + "," + workOrder.getErrorType();
                    databaseWorkOrder.setErrorType(errorType);
                    databaseWorkOrder.setStatus(WorkOrderStatusEnum.DISTRIBUTED);
                    // 错误类型不一样,就新增一个错误类型,并且重置工单状态为待处理
                    List<SysDictData> errorTypeDictList = dictDataMapper.selectDictDataByType("error_type");
                    String finalErrorType = errorType;
                    List<SysDictData> targetErrorTypes = errorTypeDictList.stream().filter(item -> finalErrorType.equals(item.getDictValue())).collect(Collectors.toList());
                    if (! CollectionUtils.isEmpty(targetErrorTypes)) {
                        errorType = targetErrorTypes.get(0).getDictValue();
                    }
                    WorkOrderErrorType workOrderErrorType = new WorkOrderErrorType();
                    workOrderErrorType.setWorkOrderNo(databaseWorkOrder.getWorkOrderNo());
                    Date now = new Date();
                    workOrderErrorType.setCreateTime(now);
                    workOrderErrorType.setUpdateTime(now);
                    workOrderErrorTypeMapper.insert(workOrderErrorType);
                    databaseWorkOrder.setStatus(WorkOrderStatusEnum.DISTRIBUTED);
                    databaseWorkOrder.setUpdateTime(now);
                    baseMapper.updateById(databaseWorkOrder);
                    updateNum++;
@@ -142,11 +161,11 @@
            } else {
                workOrder.setCreateTime(new Date());
                workOrder.setUpdateTime(new Date());
                // 如果报备过,使用最新报备的错误类型
                Report report = reportMapper.checkPointReported(workOrder.getSerialNumber());
                if (Objects.nonNull(report)) {
                    workOrder.setErrorType(report.getErrorType());
                }
//                // 如果报备过,使用最新报备的错误类型
//                Report report = reportMapper.checkPointReported(workOrder.getSerialNumber());
//                if (Objects.nonNull(report)) {
//                    workOrder.setErrorType(report.getErrorType());
//                }
                waitAddList.add(workOrder);
            }
        }
@@ -215,8 +234,8 @@
        Date now = new Date();
        entity.setCreateTime(now);
        entity.setUpdateTime(now);
        entity.setErrorType(form.getErrorType().stream().map(ErrorTypeEnum::getValue).collect(Collectors.joining(",")));
        List<WorkOrderErrorType> workOrderErrorTypes = form.getErrorType().stream().map(errorType -> new WorkOrderErrorType(entity.getWorkOrderNo(), errorType.getValue())).toList();
        entity.setErrorType(String.join(",", form.getErrorType()));
        List<WorkOrderErrorType> workOrderErrorTypes = form.getErrorType().stream().map(errorType -> new WorkOrderErrorType(entity.getWorkOrderNo(), errorType)).toList();
        workOrderErrorTypeMapper.insertWorkOrderErrorTypeList(workOrderErrorTypes);
        if(baseMapper.insert(entity) > 0) {
            return Result.ok("添加成功");
@@ -402,6 +421,7 @@
    public Result page(WorkOrderQuery query) {
        IPage<WorkOrderVO> page = PageUtil.getPage(query, WorkOrderVO.class);
        baseMapper.page(page, query);
        page.getRecords().forEach(item -> item.setErrorType(ErrorTypeEnum.getEnumValue(item.getErrorType())));
        return Result.ok().data(page.getRecords()).total(page.getTotal());
    }
@@ -409,6 +429,7 @@
    public Result distributePage(DistributeWorkOrderQuery query) {
        IPage<WorkOrderVO> page = PageUtil.getPage(query, WorkOrderVO.class);
        baseMapper.distributePage(page, query);
        page.getRecords().forEach(item -> item.setErrorType(ErrorTypeEnum.getEnumValue(item.getErrorType())));
        return Result.ok().data(page).total(page.getTotal());
    }
ycl-server/src/main/java/com/ycl/platform/service/impl/YwPointServiceImpl.java
@@ -287,17 +287,6 @@
            return point;
        }).collect(Collectors.toList());
        this.waitAllFinishAndGetResult(pointList);
//        for (PointExport pointExport : dataList) {
//            YwPoint point = new YwPoint();
//            point.setImportantCommandImageTag("是".equals(pointExport.getImportantCommandImageTagString()));
//            point.setProvinceTag("是".equals(pointExport.getProvinceTagString()));
//            point.setUnitId(Long.valueOf(unitId));
//            point.setStartTime(startTime);
//            point.setEndTime(endTime);
//            point.setPointName(pointExport.getPointName());
//            point.setSerialNumber(pointExport.getSerialNumber());
//            this.baseMapper.updatePoint(point);
//        }
    }
    public void waitAllFinishAndGetResult(List<YwPoint> dataList) throws InterruptedException, ExecutionException {
@@ -306,34 +295,18 @@
        int start = 0;
        Date startTime = new Date();
        while (true) {
            if (dataList.size() < start + 50) {
            if (dataList.size() < start + 100) {
                List<YwPoint> list = dataList.subList(start, dataList.size() - 1);
                Callable<Boolean> callable = new PointImportCallable(list, this.baseMapper);
                FutureTask<Boolean> futureTask = new FutureTask(callable);
                Thread thread = new Thread(futureTask);
                thread.start();
                // 不能直接调用Future的get方法,否则就变成串行执行了,失去多线程意义
                resultList.add(futureTask);
                this.baseMapper.updatePoint(list);
                break;
            } else {
                List<YwPoint> list = dataList.subList(start, start + 50);
                Callable<Boolean> callable = new PointImportCallable(list, this.baseMapper);
                FutureTask<Boolean> futureTask = new FutureTask(callable);
                Thread thread = new Thread(futureTask);
                thread.start();
                // 不能直接调用Future的get方法,否则就变成串行执行了,失去多线程意义
                resultList.add(futureTask);
                start += 50;
                List<YwPoint> list = dataList.subList(start, start + 100);
                this.baseMapper.updatePoint(list);
                start += 100;
            }
        }
        for (FutureTask<Boolean> futureTask : resultList) {
            data.add(futureTask.get());
        }
        Date endTime = new Date();
        log.error("总共耗时:" + (endTime.getTime() - startTime.getTime()) / 1000);
        if (data.stream().allMatch(item -> item == Boolean.TRUE)) {
            System.out.println("执行成功");
        }
        log.error("总共耗时:" + (endTime.getTime() - startTime.getTime()));
    }
}
ycl-server/src/main/resources/application-dev.yml
@@ -36,7 +36,7 @@
spring:
  # 数据源配置
  datasource:
    url: jdbc:mysql://101.35.247.188/zgyw?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
    url: jdbc:mysql://101.35.247.188/zgyw?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowMultiQueries=true
    username: root
    password: ycl@202466
    type: com.alibaba.druid.pool.DruidDataSource
ycl-server/src/main/resources/application-prod.yml
@@ -36,7 +36,7 @@
spring:
  # 数据源配置
  datasource:
    url: jdbc:mysql://51.92.65.72:3306/zgyw?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
    url: jdbc:mysql://51.92.65.72:3306/zgyw?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowMultiQueries=true
    username: root
    password: zgyw@202488
    type: com.alibaba.druid.pool.DruidDataSource
ycl-server/src/main/resources/application.yml
@@ -68,7 +68,7 @@
logging:
  level:
    org.springframework: warn
    com.ycl : debug
    com.ycl : error
# security配置
security:
ycl-server/src/main/resources/mapper/zgyw/CheckIndexCarMapper.xml
@@ -127,16 +127,16 @@
    <select id="dashboard" resultType="com.ycl.platform.domain.entity.CheckIndexCar">
        SELECT
            IFNULL(ROUND(AVG(view_connect_stability * 100), 2), 0) AS view_connect_stability,
            IFNULL(ROUND(AVG(site_online * 100), 2), 0) AS site_online,
            IFNULL(ROUND(AVG(device_directory_consistent * 100), 2), 0) AS device_directory_consistent,
            IFNULL(ROUND(AVG(vehicle_information_collection_accuracy * 100), 2), 0) AS vehicle_information_collection_accuracy,
            IFNULL(ROUND(AVG(vehicle_capture_integrity * 100), 2), 0) AS vehicle_capture_integrity,
            IFNULL(ROUND(AVG(vehicle_capture_accuracy * 100), 2), 0) AS vehicle_capture_accuracy,
            IFNULL(ROUND(AVG(vehicle_timing_accuracy * 100), 2), 0) AS vehicle_timing_accuracy,
            IFNULL(ROUND(AVG(vehicle_upload_timeliness * 100), 2), 0) AS vehicle_upload_timeliness,
            IFNULL(ROUND(AVG(vehicle_url_availability * 100), 2), 0) AS vehicle_url_availability,
            IFNULL(ROUND(AVG(vehicle_picture_availability * 100), 2), 0) AS vehicle_picture_availability
            IFNULL(ROUND(AVG(view_connect_stability * 100), 0), 0) AS view_connect_stability,
            IFNULL(ROUND(AVG(site_online * 100), 0), 0) AS site_online,
            IFNULL(ROUND(AVG(device_directory_consistent * 100), 0), 0) AS device_directory_consistent,
            IFNULL(ROUND(AVG(vehicle_information_collection_accuracy * 100), 0), 0) AS vehicle_information_collection_accuracy,
            IFNULL(ROUND(AVG(vehicle_capture_integrity * 100), 0), 0) AS vehicle_capture_integrity,
            IFNULL(ROUND(AVG(vehicle_capture_accuracy * 100), 0), 0) AS vehicle_capture_accuracy,
            IFNULL(ROUND(AVG(vehicle_timing_accuracy * 100), 0), 0) AS vehicle_timing_accuracy,
            IFNULL(ROUND(AVG(vehicle_upload_timeliness * 100), 0), 0) AS vehicle_upload_timeliness,
            IFNULL(ROUND(AVG(vehicle_url_availability * 100), 0), 0) AS vehicle_url_availability,
            IFNULL(ROUND(AVG(vehicle_picture_availability * 100), 0), 0) AS vehicle_picture_availability
        FROM
            t_check_index_car
        <where>
ycl-server/src/main/resources/mapper/zgyw/CheckIndexFaceMapper.xml
@@ -117,14 +117,14 @@
    <select id="dashboard" resultType="com.ycl.platform.domain.entity.CheckIndexFace">
        SELECT
        IFNULL(ROUND(AVG(view_connect_stability * 100), 2), 0) AS view_connect_stability,
        IFNULL(ROUND(AVG(site_online * 100), 2), 0) AS site_online,
        IFNULL(ROUND(AVG(device_directory_consistent * 100), 2), 0) AS device_directory_consistent,
        IFNULL(ROUND(AVG(face_information_collection_accuracy * 100), 2), 0) AS face_information_collection_accuracy,
        IFNULL(ROUND(AVG(face_picture_qualification * 100), 2), 0) AS face_picture_qualification,
        IFNULL(ROUND(AVG(face_timing_accuracy * 100), 2), 0) AS face_timing_accuracy,
        IFNULL(ROUND(AVG(face_upload_timeliness * 100), 2), 0) AS face_upload_timeliness,
        IFNULL(ROUND(AVG(face_picture_availability * 100), 2), 0) AS face_picture_availability
        IFNULL(ROUND(AVG(view_connect_stability * 100), 0), 0) AS view_connect_stability,
        IFNULL(ROUND(AVG(site_online * 100), 0), 0) AS site_online,
        IFNULL(ROUND(AVG(device_directory_consistent * 100), 0), 0) AS device_directory_consistent,
        IFNULL(ROUND(AVG(face_information_collection_accuracy * 100), 0), 0) AS face_information_collection_accuracy,
        IFNULL(ROUND(AVG(face_picture_qualification * 100), 0), 0) AS face_picture_qualification,
        IFNULL(ROUND(AVG(face_timing_accuracy * 100), 0), 0) AS face_timing_accuracy,
        IFNULL(ROUND(AVG(face_upload_timeliness * 100), 0), 0) AS face_upload_timeliness,
        IFNULL(ROUND(AVG(face_picture_availability * 100), 0), 0) AS face_picture_availability
        FROM
        t_check_index_face
        <where>
ycl-server/src/main/resources/mapper/zgyw/CheckIndexVideoMapper.xml
@@ -178,27 +178,27 @@
    <select id="dashboard" resultType="com.ycl.platform.domain.entity.CheckIndexVideo">
        SELECT
        IFNULL(ROUND(AVG(platform_online * 100), 2), 0) AS platform_online,
        IFNULL(ROUND(AVG(monitor_qualification * 100), 2), 0) AS monitor_qualification,
        IFNULL(ROUND(AVG(monitor_registration * 100), 2), 0) AS monitor_registration,
        IFNULL(ROUND(AVG(archives_rate * 100), 2), 0) AS archives_rate,
        IFNULL(ROUND(AVG(site_online * 100), 2), 0) AS site_online,
        IFNULL(ROUND(AVG(video_available * 100), 2), 0) AS video_available,
        IFNULL(ROUND(AVG(annotation_accuracy * 100), 2), 0) AS annotation_accuracy,
        IFNULL(ROUND(AVG(timing_accuracy * 100), 2), 0) AS timing_accuracy,
        IFNULL(ROUND(AVG(key_site_online * 100), 2), 0) AS key_site_online,
        IFNULL(ROUND(AVG(key_video_available * 100), 2), 0) AS key_video_available,
        IFNULL(ROUND(AVG(key_annotation_accuracy * 100), 2), 0) AS key_annotation_accuracy,
        IFNULL(ROUND(AVG(key_timing_accuracy * 100), 2), 0) AS key_timing_accuracy,
        IFNULL(ROUND(AVG(key_command_image_inspection * 100), 2), 0) AS key_command_image_inspection,
        IFNULL(ROUND(AVG(key_command_image_directory_tree * 100), 2), 0) AS key_command_image_directory_tree,
        IFNULL(ROUND(AVG(online_inspection_platform * 100), 2), 0) AS online_inspection_platform,
        IFNULL(ROUND(AVG(video_transmission_assets_accuracy * 100), 2), 0) AS video_transmission_assets_accuracy,
        IFNULL(ROUND(AVG(video_transmission_assets_weak_password_score * 100), 2), 0) AS video_transmission_assets_weak_password_score,
        IFNULL(ROUND(AVG(video_transmission_dangerous_assets_score * 100), 2), 0) AS video_transmission_dangerous_assets_score,
        IFNULL(ROUND(AVG(video_transmission_boundary_integrity_detection * 100), 2), 0) AS video_transmission_boundary_integrity_detection,
        IFNULL(ROUND(AVG(operating_rate * 100), 2), 0) AS operating_rate,
        IFNULL(ROUND(AVG(key_command_image_online * 100), 2), 0) AS key_command_image_online
        IFNULL(ROUND(AVG(platform_online * 100), 0), 0) AS platform_online,
        IFNULL(ROUND(AVG(monitor_qualification * 100), 0), 0) AS monitor_qualification,
        IFNULL(ROUND(AVG(monitor_registration * 100), 0), 0) AS monitor_registration,
        IFNULL(ROUND(AVG(archives_rate * 100), 0), 0) AS archives_rate,
        IFNULL(ROUND(AVG(site_online * 100), 0), 0) AS site_online,
        IFNULL(ROUND(AVG(video_available * 100), 0), 0) AS video_available,
        IFNULL(ROUND(AVG(annotation_accuracy * 100), 0), 0) AS annotation_accuracy,
        IFNULL(ROUND(AVG(timing_accuracy * 100), 0), 0) AS timing_accuracy,
        IFNULL(ROUND(AVG(key_site_online * 100), 0), 0) AS key_site_online,
        IFNULL(ROUND(AVG(key_video_available * 100), 0), 0) AS key_video_available,
        IFNULL(ROUND(AVG(key_annotation_accuracy * 100), 0), 0) AS key_annotation_accuracy,
        IFNULL(ROUND(AVG(key_timing_accuracy * 100), 0), 0) AS key_timing_accuracy,
        IFNULL(ROUND(AVG(key_command_image_inspection * 100), 0), 0) AS key_command_image_inspection,
        IFNULL(ROUND(AVG(key_command_image_directory_tree * 100), 0), 0) AS key_command_image_directory_tree,
        IFNULL(ROUND(AVG(online_inspection_platform * 100), 0), 0) AS online_inspection_platform,
        IFNULL(ROUND(AVG(video_transmission_assets_accuracy * 100), 0), 0) AS video_transmission_assets_accuracy,
        IFNULL(ROUND(AVG(video_transmission_assets_weak_password_score * 100), 0), 0) AS video_transmission_assets_weak_password_score,
        IFNULL(ROUND(AVG(video_transmission_dangerous_assets_score * 100), 0), 0) AS video_transmission_dangerous_assets_score,
        IFNULL(ROUND(AVG(video_transmission_boundary_integrity_detection * 100), 0), 0) AS video_transmission_boundary_integrity_detection,
        IFNULL(ROUND(AVG(operating_rate * 100), 0), 0) AS operating_rate,
        IFNULL(ROUND(AVG(key_command_image_online * 100), 0), 0) AS key_command_image_online
        FROM
        t_check_index_video
        <where>
ycl-server/src/main/resources/mapper/zgyw/WorkOrderMapper.xml
@@ -167,7 +167,7 @@
        LEFT JOIN t_work_order w ON w.serial_number = p.serial_number AND w.deleted = 0
        WHERE d.del_flag = 0 AND d.area IS NOT NULL
        <if test="dataScope == 1"> AND p.province_tag = 'province' </if>
        <if test="deptId != null"> /*AND p.dept_id = #{deptId}*/ </if>
        <!-- <if test="deptId != null"> AND p.dept_id = #{deptId} </if> -->
        GROUP BY d.area, d.dept_id
        ORDER BY d.dept_id
    </select>
ycl-server/src/main/resources/mapper/zgyw/YwPointMapper.xml
@@ -109,15 +109,18 @@
    </delete>
    <update id="updatePoint">
        update t_yw_point
        <set>
            <if test="point.pointName != null and point.pointName != ''">point_name = #{point.pointName},</if>
        <foreach collection="pointList" separator=";" item="point">
            UPDATE t_yw_point
            SET
            <if test="point.pointName != null and point.pointName != ''">
                point_name = #{point.pointName},
            </if>
            unit_id = #{point.unitId},
            start_time = #{point.startTime},
            end_time = #{point.endTime},
            province_tag = #{point.provinceTag},
            important_command_image_tag = #{point.importantCommandImageTag},
        </set>
            important_command_image_tag = #{point.importantCommandImageTag}
            WHERE serial_number = #{point.serialNumber}
        </foreach>
    </update>
</mapper>