package org.jeecg.modules.api.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.MinioUtil;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.api.model.CabinetStocks;
import org.jeecg.modules.api.model.HandleDeviceData;
import org.jeecg.modules.api.service.HandleDeviceDataConvertService;
import org.jeecg.modules.apply.entity.ApplyRecord;
import org.jeecg.modules.apply.service.IApplyRecordService;
import org.jeecg.modules.device.entity.BuDevice;
import org.jeecg.modules.device.entity.BuDeviceType;
import org.jeecg.modules.device.entity.DeviceBreakdownReport;
import org.jeecg.modules.device.entity.Part;
import org.jeecg.modules.device.model.DeviceRiskAnalysis;
import org.jeecg.modules.device.service.*;
import org.jeecg.modules.manual.entity.Manual;
import org.jeecg.modules.manual.service.IManualService;
import org.jeecg.modules.material.model.bo.BuMaterialStockBo;
import org.jeecg.modules.material.service.IBuMaterialStockService;
import org.jeecg.modules.oss.entity.OssFile;
import org.jeecg.modules.oss.service.IOssFileService;
import org.jeecg.modules.regular.entity.RegularInput;
import org.jeecg.modules.regular.service.IRegularInputService;
import org.jeecg.modules.regular.service.IRegularMaterialService;
import org.jeecg.modules.regular.service.IRegularToolsService;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysDictMapper;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.jeecg.modules.system.model.SysLoginModel;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.tool.entity.Tool;
import org.jeecg.modules.toolBorrowingRecord.entity.ToolBorrowingRecord;
import org.jeecg.modules.toolBorrowingRecord.service.IToolBorrowingRecordService;
import org.jeecg.modules.toolSheet.entity.ToolSheet;
import org.jeecg.modules.toolSheet.service.IToolSheetService;
import org.jeecg.modules.workOrder.entity.*;
import org.jeecg.modules.workOrder.model.WorkOrderDetailRecord;
import org.jeecg.modules.workOrder.model.WorkOrderDto;
import org.jeecg.modules.workOrder.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * 智能工具传数接口
 */
@Validated
@RequiredArgsConstructor
@RestController
@Api(tags="API-给手持机暴露的接口")
@RequestMapping("/mobile")
public class HandleDeviceApiController {

    private final IApplyRecordService applyRecordService;
    private final IRegularMaterialService regularMaterialService;
    private final IRegularToolsService regularToolsService;
    private final IRegularInputService regularInputService;
    private final IManualService manualService;
    private final IWorkOrderService workOrderService;
    private final IWorkPermitCompleteService workPermitCompleteService;
    private final IWorkRecordService workRecordService;
    private final IOperationRecordService operationRecordService;
    private final IBuDeviceService buDeviceService;
    private final IPartService partService;
    private final IBuDeviceTypeService buDeviceTypeService;
    private final IBuDeviceOnlineService buDeviceOnlineService;
    private final IDeviceBreakdownReportService deviceBreakdownReportService;
    private final IToolBorrowingRecordService toolBorrowingRecordService;
    private final IToolSheetService toolSheetService;
    private final IOssFileService ossFileService;
    private final HandleDeviceDataConvertService dataConvertService;
    private final IBuMaterialStockService buMaterialStockService;
    private final ISysUserService sysUserService;
    private final IWorkDivisionService workDivisionService;

    private final SysUserMapper sysUserMapper;
    private final SysDictMapper sysDictMapper;

    @ApiOperation(value="请销点记录-请点", notes="请销点记录-请点")
    @PostMapping(value = "/wpc/add")
    public Result<String> add(@RequestBody WorkPermitComplete workPermitComplete) {
        int result = workPermitCompleteService.addPermit(workPermitComplete);
        if (result == 1) {
            return Result.OK("请点成功！");
        } else if (result == 0) {
            return Result.error("物资申请未通过，请点失败！");
        }
        return Result.error("请点失败！");
    }

    @ApiOperation(value="请销点记录-编辑/销点", notes="请销点记录-编辑/销点")
    @RequestMapping(value = "/wpc/edit", method = {RequestMethod.PUT,RequestMethod.POST})
    public Result<String> edit(@RequestBody WorkPermitComplete workPermitComplete) {
        int result = workPermitCompleteService.updateComple(workPermitComplete);
        if (result == 1) {
            return Result.OK("销点成功！");
        } else if (result == 0) {
            return Result.error("请点站值班员不能为空！");
        } else if (result == 2) {
            return Result.error("编辑成功！");
        }
        return Result.error("失败！");
    }

    @ApiOperation(value="请销点记录-通过workOrder查询", notes="请销点记录-通过workOrder查询")
    @GetMapping(value = "/wpc/queryByWorkOrder")
    public Result<WorkPermitComplete> queryByWorkOrder(@RequestParam(name="workOrder",required=true) String workOrder) {
        WorkPermitComplete workPermitComplete = workPermitCompleteService.getOne(new LambdaQueryWrapper<WorkPermitComplete>().eq(WorkPermitComplete::getWorkOrder,workOrder));
        if(workPermitComplete==null) {
            return Result.error("未找到请销点记录");
        }
        return Result.OK(workPermitComplete);
    }

    @ApiOperation(value="任务工单-分页列表查询", notes="任务工单-分页列表查询")
    @GetMapping(value = "/workOrder/list")
    public Result<IPage<WorkOrder>> queryPageList(WorkOrder workOrder,
                                                  @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                  @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                                                  HttpServletRequest req) {
        LambdaQueryWrapper<WorkOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorkOrder::getCoordinator,workOrder.getCoordinator());
        queryWrapper.ne(WorkOrder::getStatus,4);
        queryWrapper.orderByDesc(WorkOrder::getCreateTime);
        Page<WorkOrder> page = new Page<WorkOrder>(pageNo, pageSize);
        IPage<WorkOrder> pageList = workOrderService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    @ApiOperation(value="任务工单-通过id查询工单详细内容", notes="任务工单-通过id查询工单详细内容")
    @GetMapping(value = "/workOrder/getDetailbyId")
    public Result<WorkOrderDto> getDetailbyId(@RequestParam(name="id",required=true) String id,@RequestParam(name="queryAll",required=false) Integer queryAll) {
        return Result.OK(workOrderService.getDetailbyId(id,queryAll!=0));
    }

    @ApiOperation(value = "实际派工表-列表查询", notes = "实际派工表-列表查询")
    @GetMapping(value = "/workDivision/allist/byOrder")
    public Result<List<WorkDivision>> queryList(WorkDivision workDivision) {
        LambdaQueryWrapper<WorkDivision> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorkDivision::getWorkOrder, workDivision.getWorkOrder());
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        queryWrapper.ne(WorkDivision::getExecutor, loginUser.getId());

        List<WorkDivision> ist = workDivisionService.list(queryWrapper);
        ist.forEach(pgl -> {
            SysUser user = sysUserMapper.selectById(pgl.getExecutor());
            pgl.setExecutorUser(user.getUsername());
            pgl.setExecutorName(user.getRealname());
            pgl.setExecPhone(user.getPhone());
        });
        return Result.OK(ist);
    }

    @ApiOperation(value="工单作业记录-编辑", notes="工单作业记录-编辑")
    @RequestMapping(value = "/operationRecord/edit", method = {RequestMethod.PUT,RequestMethod.POST})
    public Result<String> edit(@RequestBody OperationRecord operationRecord) {
        operationRecordService.updateById(operationRecord);
        return Result.OK("编辑成功!");
    }

    @ApiOperation(value="工单作业记录-自检完成作业（单/多项）", notes="工单作业记录-自检完成作业（单/多项）")
    @PostMapping(value = "/workOrder/detail/complete")
    public Result<?> completeRecord(@RequestBody Map<Object, Object> records){
        if(operationRecordService.completeRecords(records)){
            return Result.ok();
        }
        return Result.error("作业记录操作失败");
    }

    @ApiOperation(value="工单作业记录-互检完成作业（单/多项）", notes="工单作业记录-互检完成作业（单/多项）")
    @PostMapping(value = "/workOrder/detail/complete/mutual")
    public Result<?> completeMutualRecord(@RequestBody Map<Object, Object> records){
        if(operationRecordService.completeMutualRecord(records)){
            return Result.ok();
        }
        return Result.error("作业记录操作失败");
    }

    @ApiOperation(value="工单作业记录-专检完成作业（单/多项）", notes="工单作业记录-专检完成作业（单/多项）")
    @PostMapping(value = "/workOrder/detail/complete/special")
    public Result<?> completeSpecialRecord(@RequestBody Map<Object, Object> records){
        if(operationRecordService.completeSpecialRecord(records)){
            return Result.ok();
        }
        return Result.error("作业记录操作失败");
    }

    @ApiOperation(value="工单作业记录-自检完成作业（全部）", notes="工单作业记录-自检完成作业（全部）")
    @PostMapping(value = "/workOrder/detail/completeAll")
    public Result<?> completeAllRecord(@RequestParam(name="workOrder") String workOrder){
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if(operationRecordService.update(new LambdaUpdateWrapper<OperationRecord>().
                set(OperationRecord::getCheckResult,0).set(OperationRecord::getSelfInspection,user.getRealname()).eq(OperationRecord::getWorkOrder,workOrder))){
            return Result.ok();
        }
        return Result.error("作业记录操作失败");
    }

    @ApiOperation(value="任务工单-开工/完工", notes="任务工单-开工/完工")
    @RequestMapping(value = "/workOrder/edit", method = {RequestMethod.PUT,RequestMethod.POST})
    public Result<String> edit(@RequestBody WorkOrder workOrder) {
        if(workOrder.getStatus() != null){
            switch (workOrder.getStatus()){
                case 3:
                    //开工
                    workOrderService.updateById(workOrder);
                    return Result.OK("开工成功!");
                case 4:
                    //完工
//                    //todo 判断所有作业是否完成
//                    long count = operationRecordService.queryUncompleteCount(workOrder.getId());
//                    if(count > 0){
//                        return Result.error("请先完成所有作业！");
//                    }
                    //todo 判断所有工具是否归还
                    long toolCount = operationRecordService.queryUnreturnCount(workOrder.getId());
                    if(toolCount > 0){
                        return Result.error("请先归还所有工具！");
                    }
                    workOrderService.updateById(workOrder);
                    return Result.OK("完工成功!");
                case 1:
                    //派工
                    break;
                case 2:
                    //开工
                    break;
                case 0:
                    //撤销
                    return workOrderService.cancelWorkOrder(workOrder) ? Result.ok("撤销成功") : Result.error("撤销工单失败！");
            }
        }

        if(workOrder.getReviewType()!=null){
            LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            Map<Integer, Consumer<String>> reviewSetters = Map.of(
                    1, workOrder::setReview1,
                    2, workOrder::setReview2,
                    3, workOrder::setReview3,
                    4, workOrder::setReview4
            );

            Consumer<String> setter = reviewSetters.get(workOrder.getReviewType());
            if (setter != null) {
                setter.accept(user.getId());
            }
        }
        workOrderService.updateById(workOrder);
        return Result.OK("编辑成功!");
    }

    @ApiOperation(value="任务工单-创建工单的测量项记录", notes="任务工单-创建工单的测量项记录")
    @PostMapping(value = "/workOrder/record")
    public Result<List<WorkOrderDetailRecord>> createRecord(@RequestBody WorkRecord workRecord) {
        return Result.OK(workRecordService.initWorkRecord(workRecord));
    }

    @ApiOperation(value="任务工单-根据工单id获取测量项记录", notes="任务工单-根据工单id获取测量项记录")
    @GetMapping(value = "/workOrder/record/list")
    public Result<List<WorkOrderDetailRecord>> listWorkRecordByWorkOrder(@RequestParam(name="workOrder") String workOrder) {
        return Result.OK(workRecordService.listWorkRecordByWorkOrder(workOrder));
    }

    @ApiOperation(value="任务工单-根据记录id指定当前测量项", notes="任务工单-根据记录id指定当前测量项")
    @PutMapping(value = "/workOrder/record/now")
    public Result<?> nowRecord(@RequestParam(name="recordId") String recordId) {
        return Result.OK(workRecordService.nowWorkRecord(recordId));
    }

    @ApiOperation(value="任务工单-根据记录id进行再次测量", notes="任务工单-根据记录id进行再次测量")
    @PutMapping(value = "/workOrder/record/again")
    public Result<WorkRecord> againRecord(@RequestParam(name="recordId") String recordId) {
        return Result.OK(workRecordService.againWorkRecord(recordId));
    }

    @ApiOperation(value="任务工单-根据修程id获取测量项", notes="任务工单-根据修程id获取测量项")
    @GetMapping(value = "/workOrder/listInput")
    public Result<List<RegularInput>> listInputByRegular(@RequestParam(name="regularId") String regularId) {
        return Result.OK(regularInputService.listInputByRegular(regularId));
    }

    @ApiOperation(value="任务工单-手持机上传测量项记录", notes="任务工单-手持机上传测量项记录")
    @PostMapping(value = "/workOrder/record/upload")
    public Result<?> createRecord(@RequestBody List<HandleDeviceData> handleDeviceDatas) {
        try {
            return Result.OK(dataConvertService.handleDataMessage(handleDeviceDatas));
        }catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    @ApiOperation(value="任务工单-根据工单id获取物料", notes="任务工单-根据工单id获取物料")
    @GetMapping("/workOrder/material/{id}")
    public Result<?> queryMaterialsByWorkOrder(@PathVariable("id") String id){
        try{
            return Result.ok(regularMaterialService.queryByWorkOrder(id));
        }catch (Exception e){
            return Result.error(e.getMessage());
        }
    }

    @ApiOperation(value="任务工单-根据工单id获取工器具", notes="任务工单-根据工单id获取工器具")
    @GetMapping("/workOrder/tool/{id}")
    public Result<?> queryToolsByWorkOrder(@PathVariable("id") String id){
        try{
            return Result.ok(regularToolsService.queryByWorkOrder(id));
        }catch (Exception e){
            return Result.error(e.getMessage());
        }
    }

    @ApiOperation(value="物资申请记录-添加", notes="物资申请记录-添加")
    @PostMapping(value = "/apply/add")
    public Result<String> add(@RequestBody ApplyRecord applyRecord) {
        applyRecordService.save(applyRecord);
        return Result.OK("添加成功！");
    }

    @ApiOperation(value="物资申请记录-通过workOrder查询", notes="工器具/物资申请记录-通过workOrder查询")
    @GetMapping(value = "/apply/queryByWorkOrder")
    public Result<List<ApplyRecord>> getByWorkOrder(@RequestParam(name="workOrder",required=true) String workOrder) {
        List<ApplyRecord> applyRecords = applyRecordService.queryByWorkOrder(workOrder);
        if(applyRecords.isEmpty()) {
            return Result.error("未找到物资申请记录");
        }
        return Result.OK(applyRecords);
    }

    @ApiOperation(value="作业指导书-通过workOrder查询", notes="作业指导书-通过workOrder查询")
    @GetMapping(value = "/manual/queryByWorkOrder")
    public Result<List<Manual>> getManualByWorkOrder(@RequestParam(name="workOrder",required=true) String workOrder) {
        List<Manual> manuals = manualService.queryByWorkOrder(workOrder);
        if(manuals.isEmpty()) {
            return Result.error("未找到作业指导书");
        }
        return Result.OK(manuals);
    }

    @ApiOperation(value="设备信息表-通过id查询", notes="设备信息表-通过id查询")
    @GetMapping(value = "/device/queryById")
    public Result<?> queryById(@RequestParam(name="id",required=true) String id) {
        BuDevice buDevice = buDeviceService.getById(id);
        if(buDevice==null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(buDevice);
    }

    @ApiOperation(value="设备信息表-查询device列表", notes="设备信息表-查询device列表")
    @GetMapping(value = "/device/getDevices")
    public Result<?> getDevice() {
        List<DeviceRiskAnalysis> deviceByType = buDeviceOnlineService.getDevice();
        return Result.OK(deviceByType);
    }

    @ApiOperation(value="设备部件表-通过id查询", notes="设备部件表-通过id查询")
    @GetMapping(value = "part/queryById")
    public Result<Part> getPartById(@RequestParam(name="id",required=true) String id) {
        Part part = partService.getById(id);
        if(part==null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(part);
    }

    @ApiOperation(value="设备部件表-分页列表查询", notes="设备部件表-分页列表查询")
    @GetMapping(value = "part/list")
    public Result<IPage<Part>> queryPageList(Part part,
                                             @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                             @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                                             HttpServletRequest req) {
        QueryWrapper<Part> queryWrapper = QueryGenerator.initQueryWrapper(part, req.getParameterMap());
        if(com.aliyuncs.utils.StringUtils.isEmpty(part.getPid())){
            queryWrapper.isNull("pid");
            queryWrapper.eq("is_virtual", 1);
        }
        Page<Part> page = new Page<Part>(pageNo, pageSize);
        IPage<Part> pageList = partService.page(page, queryWrapper);
        page.getRecords().forEach(item -> {
            List<Part> parts = partService.list(new LambdaQueryWrapper<Part>()
                    .eq(Part::getPid, item.getId()));
            item.setChildren(parts);
        });
        return Result.OK(pageList);
    }

    @GetMapping(value = "/deviceType/list/all")
    @ApiOperation(value="设备类型-通过calss区分设备还是部件", notes="设备类型-通过calss区分设备还是部件(非必填)")
    public Result<List<BuDeviceType>> queryAllList(@RequestParam(name="calss",required = false) String calss) {
        List<BuDeviceType> pageList = buDeviceTypeService.list(new LambdaQueryWrapper<BuDeviceType>().eq(StringUtils.isNotBlank(calss), BuDeviceType::getCalss, calss));
        return Result.OK(buDeviceTypeService.buildTree(pageList));
    }

    @ApiOperation(value="设备故障报修-添加", notes="设备故障报修-添加")
    @PostMapping(value = "/breakReport/add")
    public Result<String> add(@RequestBody DeviceBreakdownReport deviceBreakdownReport) {
        deviceBreakdownReportService.save(deviceBreakdownReport);
        return Result.OK("添加成功！");
    }

    @ApiOperation(value="工器具借用记录-分页列表查询", notes="工器具借用记录-分页列表查询")
    @GetMapping(value = "/toolBorrow/list")
    public Result<IPage<ToolBorrowingRecord>> queryToolBorrowList(ToolBorrowingRecord toolBorrowingRecord,
                                                            @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                            @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                                                            HttpServletRequest req) {
        QueryWrapper<ToolBorrowingRecord> queryWrapper = QueryGenerator.initQueryWrapper(toolBorrowingRecord, req.getParameterMap());
        Page<ToolBorrowingRecord> page = new Page<ToolBorrowingRecord>(pageNo, pageSize);
        IPage<ToolBorrowingRecord> pageList = toolBorrowingRecordService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    @ApiOperation(value = "工器具台账-分页列表查询", notes = "工器具台账-分页列表查询")
    @GetMapping(value = "/toolSheet/list")
    public Result<IPage<ToolSheet>> queryPageList(ToolSheet toolSheet,
                                                  @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                  @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                  HttpServletRequest req) {
        QueryWrapper<ToolSheet> queryWrapper = QueryGenerator.initQueryWrapper(toolSheet, req.getParameterMap());
        Page<ToolSheet> page = new Page<ToolSheet>(pageNo, pageSize);
        IPage<ToolSheet> pageList = toolSheetService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    @ApiOperation(value="物料出入库", notes="物料出入库")
    @PostMapping(value = "/material/stock")
    public Result<Boolean> materialStock(@RequestBody List<BuMaterialStockBo> bos) {
        try {
            return Result.OK(buMaterialStockService.materialStock(bos));
        }catch (Exception e) {
            return Result.error("物料出入库失败："+e.getMessage());
        }
    }

    //使用手持机进行虚拟库工具出入库
    @ApiOperation(value="工具出入库接口", notes="工具出入库接口")
    @PostMapping("/toolBorrow/outputInfo")
    public Result<String> outputInfo(@RequestBody CabinetStocks dto) {
        if (toolBorrowingRecordService.inOutRecordSync(dto.getTools())) {
            return Result.OK("工具出入库成功");
        }else {
            return Result.error("工具出入库失败");
        }
    }

    @ApiOperation(value = "用户密码验证", notes = "用户密码验证")
    @GetMapping("/password/check")
    public Result<JSONObject> checkPassword(SysLoginModel sysLoginModel) {
        String username = sysLoginModel.getUsername();
        String password = sysLoginModel.getPassword();

        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername,username);
        SysUser sysUser = sysUserService.getOne(queryWrapper);

        Result<JSONObject> result = sysUserService.checkUserIsEffective(sysUser);
        if(!result.isSuccess()) {
            return result;
        }

        //2. 校验用户名或密码是否正确
        String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
        String syspassword = sysUser.getPassword();
        if (!syspassword.equals(userpassword)) {
            result.error500("用户名或密码错误");
            return result;
        }
        result.setMessage(sysUser.getRealname());
        return result;
    }

    @ApiOperation(value="给手持机的上传文件接口", notes="给手持机的上传文件接口")
    @PostMapping(value = "/uploadMinioNew")
    public Result<?> uploadMinioNew(@Parameter(description = "File to upload", required = true)
                                    @RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception {
        Result<?> result = new Result<>();
        String bizPath = file.getOriginalFilename();

        //LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
        boolean flag = oConvertUtils.isNotEmpty(bizPath) && (bizPath.contains("../") || bizPath.contains("..\\"));
        if (flag) {
            throw new JeecgBootException("上传目录bizPath，格式非法！");
        }

        if(oConvertUtils.isEmpty(bizPath)){
            bizPath = "";
        }
        // 获取文件名
        String orgName = file.getOriginalFilename();
        orgName = CommonUtils.getFileName(orgName);
        String fileUrl =  MinioUtil.upload(file,bizPath);
        String objectPath = extractObjectPath(fileUrl);
        //保存文件信息
        OssFile minioFile = new OssFile()
                .setFileName(orgName)
                .setUrl(fileUrl);
        ossFileService.save(minioFile);
        minioFile.setUrl(objectPath);
        return Result.ok(minioFile);
    }

    private String extractObjectPath(String fullUrl) {
        List<DictModel> dictModels = sysDictMapper.queryDictItemsByCode("minio_out_url");
        String outUrl = dictModels.get(0).getText();
        try {
            URI uri = new URI(fullUrl);
            // /cl27io/xxx.pdf → cl27io/xxx.pdf
            return outUrl+uri.getPath().replaceFirst("^/", "");
        } catch (Exception e) {
            // 兜底（极端情况）
            int idx = fullUrl.indexOf("/", fullUrl.indexOf("//") + 2);
            return idx > -1 ? outUrl+fullUrl.substring(idx + 1) : fullUrl;
        }
    }
}
