feiyu02
9 天以前 85ef942e7195abeb71466b7159c3ee30161e1e54
2026.4.7
已修改24个文件
已添加1个文件
544 ■■■■■ 文件已修改
src/main/kotlin/cn/flightfeather/supervision/business/import/SceneImport.kt 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/common/utils/FileUtil.kt 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/common/utils/StringUtil.kt 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/config/RestExceptionHandler.kt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/domain/ds1/entity/Subtask.kt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/DataProductService.kt 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/MediafileService.kt 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/ProblemlistService.kt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/SubtaskService.kt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/UserMapService.kt 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/DataProductServiceImpl.kt 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/MediafileServiceImpl.kt 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/ProblemlistServiceImpl.kt 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/SubtaskServiceImpl.kt 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/TaskServiceImpl.kt 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/UserMapServiceImpl.kt 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/ExcelConfigVo.kt 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/SubtaskVo.kt 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/dataprod/QueryOpt.kt 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/dataprod/QueryOptSingle.kt 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/web/DataProductController.kt 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/web/MediafileController.kt 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/lightshare/web/ProblemlistController.kt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-pro-https.yml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/kotlin/cn/flightfeather/supervision/CommonTest.kt 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/business/import/SceneImport.kt
@@ -7,6 +7,7 @@
import cn.flightfeather.supervision.domain.ds1.repository.RegionRep
import cn.flightfeather.supervision.lightshare.vo.SceneDetail
import com.google.gson.Gson
import org.apache.poi.ss.usermodel.Cell
import org.apache.poi.ss.usermodel.CellType
import org.springframework.stereotype.Component
import java.io.InputStream
@@ -111,23 +112,23 @@
                    when (scense?.typeid.toString()) {
                        Constant.SceneType.TYPE1.value -> {
                            subScene = SceneConstructionSite().apply {
                                csProjectType = it.getCell(12)?.stringCellValue?.trim()
                                csStatus = it.getCell(13)?.stringCellValue?.trim()
                                siExtension1 = it.getCell(14)?.stringCellValue?.trim()
                                csStartTime = it.getCell(15)?.stringCellValue?.trim()
                                csEndTime = it.getCell(16)?.stringCellValue?.trim()
                                csLeftTime = it.getCell(17)?.stringCellValue?.trim()
                                csFloorSpace = it.getCell(18)?.numericCellValue?.toString()
                                csConstructionArea = it.getCell(19)?.numericCellValue?.toString()
                                csConstructionAreaPerMonth = it.getCell(20)?.numericCellValue?.toString()
                                csEmployerUnit = it.getCell(21)?.stringCellValue?.trim()
                                csEmployerContacts = it.getCell(22)?.stringCellValue?.trim()
                                csEmployerContactsTel = it.getCell(23)?.stringCellValue?.trim()
                                csConstructionUnit = it.getCell(24)?.stringCellValue?.trim()
                                csConstructionContacts = it.getCell(25)?.stringCellValue?.trim()
                                csConstructionContactsTel = it.getCell(26)?.stringCellValue?.trim()
                                csSecurityOfficer = it.getCell(27)?.stringCellValue?.trim()
                                csSecurityOfficerTel = it.getCell(28)?.stringCellValue?.trim()
                                csProjectType = getCellValueToString(it.getCell(12))
                                csStatus = getCellValueToString(it.getCell(13))
                                siExtension1 = getCellValueToString(it.getCell(14))
                                csStartTime = getCellValueToString(it.getCell(15))
                                csEndTime = getCellValueToString(it.getCell(16))
                                csLeftTime = getCellValueToString(it.getCell(17))
                                csFloorSpace = getCellValueToString(it.getCell(18))
                                csConstructionArea = getCellValueToString(it.getCell(19))
                                csConstructionAreaPerMonth = getCellValueToString(it.getCell(20))
                                csEmployerUnit = getCellValueToString(it.getCell(21))
                                csEmployerContacts = getCellValueToString(it.getCell(22))
                                csEmployerContactsTel = getCellValueToString(it.getCell(23))
                                csConstructionUnit = getCellValueToString(it.getCell(24))
                                csConstructionContacts = getCellValueToString(it.getCell(25))
                                csConstructionContactsTel = getCellValueToString(it.getCell(26))
                                csSecurityOfficer = getCellValueToString(it.getCell(27))
                                csSecurityOfficerTel = getCellValueToString(it.getCell(28))
                            }
                        }
                        Constant.SceneType.TYPE2.value -> {
@@ -145,7 +146,7 @@
                result.add(data)
            }
        } catch (e: IllegalStateException) {
            throw BizException("excel文件内容错误,数据转换失败!", e)
            throw BizException(e.message, e)
        }
        return result
    }
@@ -153,4 +154,16 @@
    private fun errorStr(row: Int, col: Int, str: String): String {
        return "第${row}行,第${col}列单元格错误,${str}"
    }
    private fun getCellValueToString(cell: Cell?): String {
        cell ?: return ""
        return when (cell.cellType) {
            CellType.STRING -> cell.stringCellValue.trim()
            CellType.NUMERIC -> cell.numericCellValue.toString().trim()
            CellType.BLANK -> cell.stringCellValue.trim()
            CellType.BOOLEAN -> cell.booleanCellValue.toString().trim()
            CellType.ERROR -> cell.errorCellValue.toString().trim()
            else -> throw BizException(errorStr(cell.rowIndex + 1, cell.columnIndex + 1, "单元格格式不是常见格式,无法识别"))
        }
    }
}
src/main/kotlin/cn/flightfeather/supervision/common/utils/FileUtil.kt
@@ -122,6 +122,7 @@
                    fos.write(b, 0, a)
                    a = fis.read(b)
                }
            }
        }
@@ -145,30 +146,21 @@
    }
    /**
     * æŒ‰ç…§å›ºå®šå®½åº¦åŽ‹ç¼©å›¾ç‰‡è‡³base64形式
     * æŒ‰ç…§è·¯å¾„建立文件夹,并自动处理重复路径
     */
//    fun compressImage2(bytes: ByteArray): String {
//        val length = 1440//图片长边固定压缩为1440像素
//
//        val input = ByteArrayInputStream(bytes)
//        val srcImg = ImageIO.read(input)
//        var srcLong = 0
//        var srcShort = 0
//        if (srcImg.width <= srcImg.height) {
//            srcLong = srcImg.height
//            srcShort = srcImg.width
//
//        } else {
//
//        }
//        val scale = w.toFloat() / srcW
//        val h = (srcImg.height * scale).toInt()
//
//        val buffImg = BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB)
//        buffImg.graphics.drawImage(srcImg.getScaledInstance(w, h, Image.SCALE_SMOOTH), 0, 0, null)
//        val out = ByteArrayOutputStream()
//        ImageIO.write(buffImg, "PNG", out)
//
//        return SCHEME_PNG + Base64.getEncoder().encodeToString(out.toByteArray())
//    }
    fun mkDirs(basePath: String): File {
        var file = File(basePath)
        var i = 1
        while (file.exists() && i <= 100) {
            val path = "$basePath($i)"
            file = File(path)
            i++
        }
        if (file.exists()) {
            delAllFile(file.absolutePath)
        } else {
            file.mkdirs()
        }
        return file
    }
}
src/main/kotlin/cn/flightfeather/supervision/common/utils/StringUtil.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package cn.flightfeather.supervision.common.utils
/**
 *
 * @date 2026/1/20
 * @author feiyu02
 */
object StringUtil {
    /**
     * æ•´æ•°æ•°å­—按照显示位数格式化
     * @param num æ•°å­—
     * @param digit æ˜¾ç¤ºä½æ•°
     */
    fun numberFormat(num: Int?, digit: Int): String {
        var str = num.toString()
        while (str.length < digit) {
            str = "0$str"
        }
        return str
    }
}
src/main/kotlin/cn/flightfeather/supervision/config/RestExceptionHandler.kt
@@ -35,6 +35,7 @@
    @ExceptionHandler(BizException::class)
    @ResponseStatus(HttpStatus.OK)
    fun bizException(e: BizException): BaseResponse<String> {
        e.printStackTrace()
        return BaseResponse.fail("200", e)
    }
}
src/main/kotlin/cn/flightfeather/supervision/domain/ds1/entity/Subtask.kt
@@ -11,7 +11,7 @@
@JsonInclude(JsonInclude.Include.NON_NULL)
@Table(name = "tm_t_subtask")
@ApiModel(value = "Subtask")
public class Subtask {
open class Subtask {
    @Id
    @Column(name = "ST_GUID")
    @ApiModelProperty(value = "主键16位guid")
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/DataProductService.kt
@@ -1,6 +1,7 @@
package cn.flightfeather.supervision.lightshare.service
import cn.flightfeather.supervision.lightshare.vo.AreaVo
import cn.flightfeather.supervision.lightshare.vo.dataprod.QueryOpt
import cn.flightfeather.supervision.model.dataproduct.DataProdOption
import cn.flightfeather.supervision.model.dataproduct.PPListProbRecurrence
import cn.flightfeather.supervision.model.dataproduct.PPListProblemChange
@@ -27,4 +28,14 @@
     * é—®é¢˜å¤å‘情况
     */
    fun problemRecurrence(option: DataProdOption): List<PPListProbRecurrence>
    /**
     * æŸ¥è¯¢æ•°æ®äº§å“è®°å½•
     */
    fun findProduct(queryOpt: QueryOpt, page: Int, perPage: Int)
    /**
     * ç”Ÿæˆæ•°æ®äº§å“
     */
    fun generateProduct(queryOpt: QueryOpt)
}
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/MediafileService.kt
@@ -1,8 +1,10 @@
package cn.flightfeather.supervision.lightshare.service
import cn.flightfeather.supervision.domain.ds1.entity.Mediafile
import cn.flightfeather.supervision.lightshare.vo.ExcelConfigVo
import cn.flightfeather.supervision.lightshare.vo.MediaFileVo
import org.springframework.web.multipart.MultipartFile
import javax.servlet.http.HttpServletResponse
interface MediafileService {
@@ -32,4 +34,6 @@
    fun findBysubtaskbtid(id: String, btid: String): MutableList<Mediafile>?
    fun getRoutineRecord(iGuid: String?, stGuid: String?): List<Mediafile?>
    fun downloadPic(config: ExcelConfigVo, response: HttpServletResponse): HttpServletResponse
}
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/ProblemlistService.kt
@@ -45,7 +45,7 @@
    fun newProblem(problem: String, files: Array<MultipartFile>): String
    fun updateProblem(problem: ProblemListVo, deleteImg: List<String>, files: Array<MultipartFile>): String
    fun updateProblem(problem: ProblemListVo, deleteImg: List<String>?, files: Array<MultipartFile>): String
    fun changeProblem(problemId: String, files: Array<MultipartFile>): String
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/SubtaskService.kt
@@ -37,7 +37,7 @@
    fun findByDayTaskID(taskId: String): List<SubtaskVo>
    fun findByDayTaskID(dayTaskId: String, userId: String, userType: String): List<Subtask>
    fun findByDayTaskID(dayTaskId: String, userId: String, userType: String): List<SubtaskVo>
    fun getTaskProgress(areaVo: AreaVo, userGuid: String): TaskVo
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/UserMapService.kt
@@ -39,4 +39,9 @@
     * æœç´¢ç¬¬ä¸‰æ–¹è®¾å¤‡
     */
    fun searchThirdPartyDevice(areaVo: AreaVo, keyword: String, page: Int?, perPage: Int?): Pair<DataHead, List<DeviceSiteVo>>
    /**
     * åŒæ­¥ä¸¤ä¸ªç³»ç»Ÿåœºæ™¯çš„上下线状态
     */
    fun syncOnlineStatus()
}
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/DataProductServiceImpl.kt
@@ -12,6 +12,7 @@
import cn.flightfeather.supervision.lightshare.service.DataProductService
import cn.flightfeather.supervision.lightshare.vo.AreaVo
import cn.flightfeather.supervision.lightshare.vo.ExcelConfigVo
import cn.flightfeather.supervision.lightshare.vo.dataprod.QueryOpt
import cn.flightfeather.supervision.model.dataproduct.DataProdOption
import cn.flightfeather.supervision.model.dataproduct.PPListProbRecurrence
import cn.flightfeather.supervision.model.dataproduct.PPListProblemChange
@@ -112,4 +113,13 @@
        }
        return res
    }
    override fun findProduct(queryOpt: QueryOpt, page: Int, perPage: Int) {
        // æ ¹æ®äº§å“ç±»åž‹ç¼–号、区域、时段、场景类型、配置id查询
        TODO("Not yet implemented")
    }
    override fun generateProduct(queryOpt: QueryOpt) {
        TODO("Not yet implemented")
    }
}
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/MediafileServiceImpl.kt
@@ -1,17 +1,20 @@
package cn.flightfeather.supervision.lightshare.service.impl
import cn.flightfeather.supervision.business.autooutput.datasource.AopDbMapper
import cn.flightfeather.supervision.common.exception.BizException
import cn.flightfeather.supervision.common.utils.*
import cn.flightfeather.supervision.domain.ds1.entity.Mediafile
import cn.flightfeather.supervision.domain.ds1.mapper.MediafileMapper
import cn.flightfeather.supervision.common.utils.Constant
import cn.flightfeather.supervision.common.utils.FileUtil
import cn.flightfeather.supervision.domain.ds1.entity.Inspection
import cn.flightfeather.supervision.domain.ds1.entity.Subtask
import cn.flightfeather.supervision.domain.ds1.repository.InspectionRep
import cn.flightfeather.supervision.domain.ds1.repository.MediaFileRep
import cn.flightfeather.supervision.domain.ds1.repository.SceneRep
import cn.flightfeather.supervision.domain.ds1.repository.SubTaskRep
import cn.flightfeather.supervision.lightshare.service.DomainitemService
import cn.flightfeather.supervision.lightshare.service.MediafileService
import cn.flightfeather.supervision.lightshare.vo.AreaVo
import cn.flightfeather.supervision.lightshare.vo.ExcelConfigVo
import cn.flightfeather.supervision.lightshare.vo.MediaFileVo
import com.fasterxml.jackson.core.type.TypeReference
import org.springframework.beans.BeanUtils
@@ -21,7 +24,15 @@
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import tk.mybatis.mapper.entity.Example
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.nio.charset.StandardCharsets
import java.time.LocalDateTime
import java.time.ZoneId
import java.util.*
import javax.servlet.http.HttpServletResponse
@Service
@@ -32,6 +43,7 @@
    private val subTaskRep: SubTaskRep,
    private val sceneRep: SceneRep,
    private val domainItemService: DomainitemService,
    private val dbMapper: AopDbMapper,
    @Value("\${filePath}") var filePath: String,
    @Value("\${imgPath}") var imgPath: String,
) : MediafileService {
@@ -98,7 +110,9 @@
            mapper.readValue<List<MediaFileVo>>(mediafileVoList, object : TypeReference<List<MediaFileVo>>() {})
        if (mediaFileVos.isNotEmpty()) {
            mediaFileVos.forEach {
            mediaFileVos.forEachIndexed { i, it ->
                if (i >= files.size) return@forEachIndexed
                val mediafile = Mediafile()
                BeanUtils.copyProperties(it, mediafile)
@@ -108,17 +122,15 @@
                if (reme == null) {
                    mediafileMapper.insert(mediafile)
                }
            }
            //根据扩展字段1获取保存路径
            val path = mediaFileVos[0].extension1
            for (image in files) {
                val fileName = image.originalFilename
                //根据扩展字段1获取保存路径
                val path = it.extension1
                val fileName = it.guid + ".jpg"
                val image = files[i]
                val filePath = "${imgPath}/$path/"
                try {
                    //调用文件保存方法
                    FileUtil.uploadFile(image.bytes, filePath, fileName!!)
                    FileUtil.uploadFile(image.bytes, filePath, fileName)
                } catch (e: Exception) {
                    // TODO: handle exception
                }
@@ -198,4 +210,97 @@
        }
        return res
    }
    override fun downloadPic(config: ExcelConfigVo, response: HttpServletResponse): HttpServletResponse {
        val subSum = dbMapper.subtaskMapper.getSummaryByArea(AreaVo().apply {
            provincecode = config.provinceCode
            citycode = config.cityCode
            districtcode = config.districtCode
            starttime = LocalDateTime.ofInstant(config.startTime?.toInstant(), ZoneId.systemDefault())
            endtime = LocalDateTime.ofInstant(config.endTime?.toInstant(), ZoneId.systemDefault())
            scensetypeid = config.sceneType.toString()
        })
        if (subSum.isEmpty()) return response
        val mediaList = mediafileMapper.selectByExample(Example(Mediafile::class.java).apply {
            createCriteria().andIn("iguid", subSum.map { it.insGuid })
                .apply {
                    if (!config.fileType.isNullOrEmpty()) {
                        andIn("businesstypeid", config.fileType)
                    }
                }
        })
        //建立第一层目录,包含所有的任务
        val time = DateUtil.DateToString(Date(), "yyyy-MM-dd_HH-mm-ss")
        val basePath = imgPath + File.separator + "temp" + File.separator + time
        FileUtil.mkDirs(basePath)
        //循环建立第二层目录,按照日期分类
        subSum.groupBy { it.stPlanTime }.forEach { (date, sList) ->
            //建立一个日期文件夹
            val datePath = "${basePath}${File.separator}${DateUtil.DateToString(date, DateUtil.DateStyle.YYYY_MM_DD)}"
            FileUtil.mkDirs(datePath)
            //循环建立第三层目录,按照巡查任务分类
            sList.forEach {s ->
                //建立一个子任务文件夹
                val subTaskFilePath = "${datePath}${File.separator}${StringUtil.numberFormat(s.sceneIndex, 3)} ${s.sceneName}"
                FileUtil.mkDirs(subTaskFilePath)
                //循环建立第四层目录,按照图片类型分类
                mediaList.filter { m-> m.iguid == s.insGuid }.groupBy { m-> m.businesstype }.forEach { (type, mList) ->
                    val mediaTypeFilePath = "${subTaskFilePath}${File.separator}${type}"
                    FileUtil.mkDirs(mediaTypeFilePath)
                    // å†™å…¥å›¾ç‰‡
                    mList.forEachIndexed { i, m->
                        val fromPicName =  m.guid + ".jpg"
                        val picPath =
                            imgPath + File.separator + m.extension1 + fromPicName
                        val fromFile = File(picPath)
                        val picName = if (m.description != null) {
                            m.description!!.replace("/", "-")
                                .replace("\\", "-")
                                .replace("\n", "")
                                .replace(".", "(${i + 1}).")
                        } else {
                            fromPicName
                        }
//                        val picName = fromPicName
                        val toFile = File(mediaTypeFilePath + File.separator + picName)
                        if (fromFile.exists()) {
                            FileUtil.copy(fromFile, toFile)
                        }
                    }
                }
            }
        }
        response.apply {
            setHeader("Content-Disposition", "attachment;filename=$time.zip")
            contentType = "application/octet-stream"
            characterEncoding = StandardCharsets.UTF_8.name()
        }
        val zipFile = File("$basePath.zip")
        val fos1 = FileOutputStream(zipFile)
        ZipUtils.toZip(basePath, fos1, true)
        val out = response.outputStream
        val fis = FileInputStream(zipFile)
        val buf = ByteArray(2 * 1024)
        var len = fis.read(buf)
        while (len != -1) {
            out.write(buf, 0, len)
            len = fis.read(buf)
        }
        out.flush()
        out.close()
        fis.close()
        fos1.close()
        return response
    }
}
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/ProblemlistServiceImpl.kt
@@ -555,13 +555,13 @@
        return "success"
    }
    override fun updateProblem(problem: ProblemListVo, deleteImg: List<String>, files: Array<MultipartFile>): String {
    override fun updateProblem(problem: ProblemListVo, deleteImg: List<String>?, files: Array<MultipartFile>): String {
        problemRep.findOne(problem.guid) ?: throw BizException("该问题不存在")
        problemRep.update(problem)
        val inspection = inspectionMapper.selectByPrimaryKey(problem.iguid) ?: throw BizException("巡查记录不存在")
        val scene = scenseMapper.selectByPrimaryKey(inspection.sguid) ?: throw BizException("巡查记录对应场景不存在")
        mediafileService.saveMediaFile(files) { MediaFileVo.newProFile(inspection, problem, scene) }
        mediafileService.deleteList(deleteImg)
        deleteImg?.let { mediafileService.deleteList(it) }
        return "success"
    }
@@ -615,9 +615,10 @@
        val mediaFiles = mediafileMapper.selectByExample(Example(Mediafile::class.java).apply {
            createCriteria().andEqualTo("businessguid", problemId)
                .andEqualTo("businesstypeid", 1)
                .andEqualTo("ischanged", true)
//                .andEqualTo("ischanged", true)
        })
        if (mediaFiles.isEmpty()) throw BizException("问题还未整改,无法修改整改")
        if (mediaFiles.isEmpty()) throw BizException("缺少问题和整改图片,无法修改")
        if (p.ischanged != true) throw BizException("未整改问题无法修改")
        // ä¿å­˜æ–°çš„æ•´æ”¹å›¾ç‰‡
        val m = mediaFiles[0]
@@ -626,6 +627,7 @@
            m.apply {
                guid = UUIDGenerator.generate16ShortUUID()
                description = p.problemname + " " + p.location + " æ•´æ”¹ " + UUIDGenerator.generateUUID(4) + ".jpg"
                ischanged = true
            }
        }
        mediafileService.deleteList(deleteImg)
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/SubtaskServiceImpl.kt
@@ -1,7 +1,6 @@
package cn.flightfeather.supervision.lightshare.service.impl
import cn.flightfeather.supervision.business.autooutput.score.AopEvaluation
import cn.flightfeather.supervision.common.exception.BizException
import cn.flightfeather.supervision.domain.ds1.entity.*
import cn.flightfeather.supervision.domain.ds1.mapper.*
import cn.flightfeather.supervision.common.utils.Constant
@@ -104,7 +103,7 @@
        return subtaskVoList
    }
    override fun findByDayTaskID(dayTaskId: String, userId: String, userType: String): List<Subtask> {
    override fun findByDayTaskID(dayTaskId: String, userId: String, userType: String): List<SubtaskVo> {
        val example = Example(Subtask::class.java)
        val criteria = example.createCriteria()
        criteria.andEqualTo("tsguid", dayTaskId)
@@ -115,25 +114,31 @@
            )
        }
        example.orderBy("name")
        val result = subtaskMapper.selectByExample(example).apply {
            forEach breaking@{
                //已审核提示
                it.remark = Constant.PROBLEM_CHECK_PASS
                problemlistMapper.selectByExample(Example(Problemlist::class.java).apply {
                    createCriteria().andEqualTo("stguid", it.stguid)
                    and(
                        createCriteria().orIsNull("remark")
                            .orNotEqualTo("remark", Constant.PROBLEM_DELETED)
                    )
                }).forEach { problem ->
                    //子任务中有问题未审核时,设置未审核提示
                    if (problem.extension3 == Constant.PROBLEM_UNCHECKED) {
                        it.remark = Constant.PROBLEM_UNCHECKED
                        return@breaking
                    }
        val result = subtaskMapper.selectByExample(example).map {
            val vo = SubtaskVo()
            BeanUtils.copyProperties(it, vo)
            vo
        }.onEach {
            //已审核提示
            it.remark = Constant.PROBLEM_CHECK_PASS
            problemlistMapper.selectByExample(Example(Problemlist::class.java).apply {
                createCriteria().andEqualTo("stguid", it.stguid)
                and(
                    createCriteria().orIsNull("remark")
                        .orNotEqualTo("remark", Constant.PROBLEM_DELETED)
                )
            }).forEach { problem ->
                //子任务中有问题未审核时,设置未审核提示
                if (problem.extension3 == Constant.PROBLEM_UNCHECKED) {
                    it.remark = Constant.PROBLEM_UNCHECKED
                }
            }
            // åœºæ™¯ç±»åž‹
            scenseMapper.selectByPrimaryKey(it.scenseid)?.let { s->
                it.sceneTypeId = s.typeid
                it.sceneTypeName = s.type
            }
        }
        return result
    }
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/TaskServiceImpl.kt
@@ -337,11 +337,14 @@
        // èŽ·å–æ€»ä»»åŠ¡ä¸‹æ‰€æœ‰çš„å­ä»»åŠ¡
        val subTasks = subTaskRep.findAll(Subtask().apply { tguid = taskId })
        if (subTasks.isEmpty()) return emptyList()
        // èŽ·å–æ‰€æœ‰å­ä»»åŠ¡æ¶‰åŠçš„å·¡æŸ¥åœºæ™¯ä¿¡æ¯
        val sceneList = scenseMapper.selectByExample(Example(Scense::class.java).apply {
            createCriteria().andIn("guid", subTasks.map { it?.scenseid })
        })
        val sceneList = if (subTasks.isEmpty()) {
            emptyList()
        } else {
            scenseMapper.selectByExample(Example(Scense::class.java).apply {
                createCriteria().andIn("guid", subTasks.map { it?.scenseid })
            })
        }
        //根据sql条件查询
        dayTasks.forEach { t ->
@@ -377,7 +380,7 @@
            val userProgressMap = mutableMapOf<String, ProgressPerUserPerDay>()
            filterSubTasks.forEach fst@{ fst ->
                fst ?: return@fst
                // fixme 2025.11.30 ç”±äºŽç›‘管APP的bug,导致用户可以不选择执行人员直接创建任务,所以暂时将没有执行人员的任务定义为匿名用户
                // 2026.2.2 å°†æ²¡æœ‰æ‰§è¡Œäººå‘˜çš„任务定义为匿名用户
                if (fst.executorguids.isNullOrBlank()) {
                    fst.executorguids = "niming"
                    fst.executorusernames = "niming"
@@ -400,8 +403,8 @@
                        // å½“多个人一起执行同一任务时,平分巡查量
                        this.totalTaskNum += 1.0 / ids.size
                        if (fst.status == Constant.TaskProgress.RUNINGSTATUS3.text) {
                            this.completeTaskNum += 1.0 / ids.size
                        }
                        this.completeTaskNum += 1.0 / ids.size
                        // å•人整改率累计(评分)
                        this.totalProblemNum += proList.size.toDouble() / ids.size
@@ -741,7 +744,7 @@
    override fun create(task: Task): Task {
        val res = save(task)
        if (res < 1)
            throw BizException("任务创建失败")
            throw BizException("总任务或当日任务创建失败")
        else
            return task
    }
src/main/kotlin/cn/flightfeather/supervision/lightshare/service/impl/UserMapServiceImpl.kt
@@ -164,4 +164,8 @@
    ): Pair<DataHead, List<DeviceSiteVo>> {
        return aopDataDeviceMap.searchDevice(areaVo, keyword, page ?: 1, perPage ?: 30)
    }
    override fun syncOnlineStatus() {
        TODO("Not yet implemented")
    }
}
src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/ExcelConfigVo.kt
@@ -30,4 +30,7 @@
    // å†³å®šæ˜¯å¦ç»Ÿè®¡æ€»ä»»åŠ¡ä¸‹æ‰€æœ‰çš„åœºæ™¯æˆ–åªç»Ÿè®¡ç­›é€‰å‡ºçš„å­ä»»åŠ¡å¯¹åº”çš„åœºæ™¯
    var allScene: Boolean = true,
    // åª’体文件的类型
    var fileType: List<Int>? = null,
)
src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/SubtaskVo.kt
@@ -1,122 +1,16 @@
package cn.flightfeather.supervision.lightshare.vo
import cn.flightfeather.supervision.domain.ds1.entity.Subtask
import com.fasterxml.jackson.annotation.JsonInclude
import java.util.*
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SubtaskVo {
    var stguid: String? = null
class SubtaskVo : Subtask() {
    /**
     * æœˆä»»åŠ¡æˆ–å…¶ä»–é¡¶å±‚ä»»åŠ¡ï¼Œä¸ä¸ºç©º
     */
    var tguid: String? = null
    var sceneTypeId: Byte? = null
    /**
     * æ‰€å±žæ—¥çš„T_GUID,可为空
     */
    var tsguid: String? = null
    var name: String? = null
    var priority: Boolean? = null
    var typeno: Byte? = null
    var type: String? = null
    var provincecode: String? = null
    var provincename: String? = null
    var citycode: String? = null
    var cityname: String? = null
    var districtcode: String? = null
    var districtname: String? = null
    var towncode: String? = null
    var townname: String? = null
    var scensename: String? = null
    var scenseid: String? = null
    var scenseTypeId: String? = null
    var scenseaddress: String? = null
    var deadlinetype: String? = null
    var planstarttime: Date? = null
    var sceneTypeName: String? = null
    var planstarttimestr: String? = null
    var planendtime: Date? = null
    var planendtimestr: String? = null
    var deployerguid: String? = null
    var deployerusername: String? = null
    var deployerrealname: String? = null
    var deploytime: Date? = null
    var executionstarttime: Date? = null
    var executionendtime: Date? = null
    var executorguids: String? = null
    var executorusernames: String? = null
    /**
     * ä¸Žç”¨æˆ·è¡¨ç”¨æˆ·åå…³è”,用“&”连接多人,例如:张三&李四&王五
     */
    var executorrealtimes: String? = null
    /**
     * æœªæ‰§è¡Œã€æ­£åœ¨æ‰§è¡Œã€å·²ç»“束
     */
    var status: String? = null
    var notifedcount: Int? = null
    /**
     * ER_GUID的集合,多个时“,”分割,自动匹配场景,同类场景多个考核规范时,现场巡查时,可单选或多选。
     */
    var rulelist: String? = null
    var stAssessorguid: String? = null
    var assessorusername: String? = null
    var assessorrealname: String? = null
    var assesstime: Date? = null
    var assessresult: String? = null
    var thirdassessorguid: String? = null
    var thirdassessorusername: String? = null
    var thirdassessorrealname: String? = null
    var thirdassesstime: Date? = null
    var thirdassessresult: String? = null
    var extension1: String? = null
    var extension2: String? = null
    var extension3: String? = null
    var remark: String? = null
}
src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/dataprod/QueryOpt.kt
@@ -11,7 +11,13 @@
 * @author feiyu02
 */
@ApiModel("查询参数")
class QueryOpt {
open class QueryOpt {
    @ApiModelProperty("产品编号")
    var prodId: String? = null
    @ApiModelProperty("配置编号", notes = "0表示未使用配置的自定义时段产品")
    var configId: Int = 0
    @ApiModelProperty("总任务id")
    var topTaskId: String? = null
src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/dataprod/QueryOptSingle.kt
@@ -1,9 +1,7 @@
package cn.flightfeather.supervision.lightshare.vo.dataprod
import com.fasterxml.jackson.annotation.JsonFormat
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
import java.time.LocalDateTime
/**
 * å•个场景纵向数据统计产品查询条件
@@ -11,16 +9,8 @@
 * @author feiyu02
 */
@ApiModel("单个场景纵向数据统计产品查询条件")
class QueryOptSingle {
class QueryOptSingle : QueryOpt() {
    @ApiModelProperty("场景id")
    var sceneId: String? = null
    @ApiModelProperty("起始时间,格式 yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    var startTime: LocalDateTime? = null
    @ApiModelProperty("结束时间,格式 yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    var endTime: LocalDateTime? = null
}
src/main/kotlin/cn/flightfeather/supervision/lightshare/web/DataProductController.kt
@@ -3,6 +3,7 @@
import cn.flightfeather.supervision.lightshare.service.DataProductService
import cn.flightfeather.supervision.lightshare.vo.AreaVo
import cn.flightfeather.supervision.lightshare.vo.ExcelConfigVo
import cn.flightfeather.supervision.lightshare.vo.dataprod.QueryOpt
import cn.flightfeather.supervision.model.dataproduct.DataProdOption
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
@@ -42,4 +43,32 @@
    fun problemRecurrence(
        @ApiParam("查询条件") @RequestBody option: DataProdOption,
    ) = dataProductService.problemRecurrence(option)
    @ApiOperation(value = "查询数据产品项及对应的统计状态")
    @GetMapping("/type/query")
    fun findProductType(
        @ApiParam("产品类型", allowableValues = "base, middle, final", format = "base") @RequestParam types: String,
    ) {
    }
    @ApiOperation(value = "查询数据产品记录")
    @PostMapping("/record/query")
    fun findProduct(
        @ApiParam("查询条件") @RequestBody queryOpt: QueryOpt,
        @ApiParam("页码") @RequestParam(value = "page", required = false, defaultValue = "1") page: Int?,
        @ApiParam("单页数据量") @RequestParam(value = "perPage", required = false, defaultValue = "30") perPage: Int?,
    ) {
        // æ ¹æ®äº§å“ç±»åž‹ç¼–号、区域、时段、场景类型、配置id查询
        return dataProductService.findProduct(queryOpt, page ?: 1, perPage ?: 30)
    }
//    @ApiOperation(value = "生成数据产品")
//    @PostMapping("/generate")
//    fun generateProduct() = dataProductService.generateProduct()
}
src/main/kotlin/cn/flightfeather/supervision/lightshare/web/MediafileController.kt
@@ -3,11 +3,14 @@
import cn.flightfeather.supervision.config.IgnoreResponseAdvice
import cn.flightfeather.supervision.domain.ds1.entity.Mediafile
import cn.flightfeather.supervision.lightshare.service.MediafileService
import cn.flightfeather.supervision.lightshare.vo.ExcelConfigVo
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import io.swagger.annotations.ApiParam
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import springfox.documentation.annotations.ApiIgnore
import javax.servlet.http.HttpServletResponse
@Api(tags = ["MediafileController"], description = "多媒体文件API接口")
@RestController
@@ -56,4 +59,12 @@
        @ApiParam("巡查记录id", required = false) @RequestParam(required = false) iGuid: String?,
        @ApiParam("巡查任务id", required = false) @RequestParam(required = false) stGuid: String?,
    ) = mediafileService.getRoutineRecord(iGuid, stGuid)
    @IgnoreResponseAdvice
    @ApiOperation("下载图片")
    @PostMapping("/pic/download")
    fun downloadPic(
        @RequestBody config: ExcelConfigVo,
        @ApiIgnore response: HttpServletResponse
    ) = mediafileService.downloadPic(config, response)
}
src/main/kotlin/cn/flightfeather/supervision/lightshare/web/ProblemlistController.kt
@@ -127,7 +127,7 @@
    @PostMapping("/updateProblem")
    fun updateProblem(
        @ApiParam("问题信息json") @RequestParam("problem") problem: String,
        @ApiParam("删除的问题图片id") @RequestParam("deleteImg") deleteImg: List<String>,
        @ApiParam("删除的问题图片id") @RequestParam("deleteImg", required = false) deleteImg: List<String>?,
        @ApiParam("问题图片") @RequestPart("images") images: Array<MultipartFile>,
    ): String {
        val problemVo = ObjectMapper().readValue(problem, object : TypeReference<ProblemListVo>() {})
src/main/resources/application-pro-https.yml
@@ -15,6 +15,12 @@
  configuration:
    log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
springfox:
  documentation:
    swagger:
      v2:
        enabled: true
imgPath: D:/02product/04supervision/images/
filePath: D:/02product/04supervision/files/
mode: prohttps
src/test/kotlin/cn/flightfeather/supervision/CommonTest.kt
@@ -22,12 +22,8 @@
    @Test
    fun findStr() {
        val str = "http://114.233.144.555:9006/asdasd/asdasd"
        val url = str.split("://")[1].split("/")[0]
        val newStr = str.replace(url, "224.55.2.12:8085")
//        val i1 = str.indexOf("://")
//        val i2 = str.indexOf("/")
        println(str)
        println(newStr)
        val m = "cOm7.jpg"
        val m1 = m.replace("/", "-").replace(".", "(${0 + 1}).")
        println(m1)
    }
}