service

service.impl

CardioTrainServiceImpl

这段代码定义了一个名为 `CardioTrainServiceImpl` 的 Service 实现类,用于对心血管训练实体 `CardioTrain` 的数据进行操作。接下来我将详细解释代码中每个部分的含义:

1. 导入了必要的类,包括了 Spring 的 `Service` 注解、MyBatis Plus 的 `ServiceImpl` 类、实体类 `CardioTrain`、Service 接口 `CardioTrainService` 以及对应的 Mapper 接口 `CardioTrainMapper`。

2. 注释部分:提供了该 Service 实现类的作者、描述、创建日期。

3. `@Service` 注解:标注该类为 Spring 的 Service 组件,用于在应用程序中进行组件扫描和依赖注入。

4. `public class CardioTrainServiceImpl extends ServiceImpl<CardioTrainMapper, CardioTrain> implements CardioTrainService`:定义了一个 Service 实现类 `CardioTrainServiceImpl`,继承了 MyBatis Plus 提供的 `ServiceImpl` 类,并指定了泛型参数为 `CardioTrainMapper` 和 `CardioTrain`,表示该 Service 操作的实体类和对应的 Mapper 接口。

5. `@Autowired private CardioTrainMapper cardioTrainMapper;`:使用 Spring 的依赖注入功能,将 `CardioTrainMapper` 接口的实例注入到 `cardioTrainMapper` 字段中,方便在类内部使用 Mapper 接口进行数据库操作。

6. `public List<CardioTrain> getAll() {...}`:定义了一个名为 `getAll` 的方法,用于获取所有心血管训练信息。在方法内部,调用了 `cardioTrainMapper` 的 `selectList` 方法查询数据库中的心血管训练信息,并返回查询结果。

通过这个 Service 实现类,可以方便地对心血管训练实体的数据进行操作,包括获取所有心血管训练信息等功能。整体设计简洁明了,符合 Spring 的规范,适合用于在应用程序中处理业务逻辑和数据操作。
package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.entity.CardioTrain;
import com.cqupt.software_1.service.CardioTrainService;
import com.cqupt.software_1.mapper.CardioTrainMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
* @author hp
* @description 针对表【cardio_train】的数据库操作Service实现
* @createDate 2023-05-16 16:16:01
*/
@Service
public class CardioTrainServiceImpl extends ServiceImpl<CardioTrainMapper, CardioTrain>
    implements CardioTrainService{


    @Autowired
    private CardioTrainMapper cardioTrainMapper;

    @Override
    public List<CardioTrain> getAll() {


        List<CardioTrain> cardioTrains = cardioTrainMapper.selectList(null);

        return cardioTrains;
    }
}

Category2ServiceImpl

这段代码中定义了一个名为 `Category2ServiceImpl` 的 Service 实现类,用于对 Category2Entity 类型的数据进行操作,并实现了 `Category2Service` 接口中定义的方法。下面我将逐个介绍代码中每个部分的功能:

1. 导入了必要的类,包括了 Spring 的 `Service` 注解、MyBatis Plus 的 `ServiceImpl` 类、实体类 `Category2Entity`、Service 接口 `Category2Service` 以及对应的 Mapper 接口 `Category2Mapper`。

2. 注释部分:使用 `TODO` 标记表示待办事项,可能是希望未来对该模块进行扩展或补充。

3. `@Service` 注解:标注该类为 Spring 的 Service 组件,用于在应用程序中进行组件扫描和依赖注入。

4. `public class Category2ServiceImpl extends ServiceImpl<Category2Mapper, Category2Entity> implements Category2Service`:定义了一个 Service 实现类 `Category2ServiceImpl`,继承了 MyBatis Plus 提供的 `ServiceImpl` 类,并指定了泛型参数为 `Category2Mapper` 和 `Category2Entity`,表示该 Service 操作的实体类和对应的 Mapper 接口。

5. `@Autowired private Category2Mapper dataManagerMapper;` 和 `@Autowired private Category2Mapper category2Mapper;`:使用 Spring 的依赖注入功能,将 `Category2Mapper` 接口的实例注入到 `dataManagerMapper` 和 `category2Mapper` 字段中,以便在类内部进行数据库操作。

6. `public List<Category2Entity> getCategory() {...}`:定义了一个名为 `getCategory` 的方法,用于获取目录行程的树形结构数据,并在内部对数据进行处理,返回处理后的结果。

7. `public List<Category2Entity> getCategory2() {...}`:定义了一个名为 `getCategory2` 的方法,类似于 `getCategory`,但在处理后将顶层以下所有元素设置为叶子节点。

8. `private List<Category2Entity> getSecondLevelChildren(String parentId) {...}`:定义了一个名为 `getSecondLevelChildren` 的私有方法,用于获取指定父节点下的第二层目录数据。

9. `@Override public void removeNode(String id) {...}`:实现了 `Category2Service` 接口中定义的移除节点操作,调用 `category2Mapper` 的 `removeNode` 方法来删除指定 id 的节点。

10. `private List<Category2Entity> getCatChildren(Category2Entity level1Cat, List<Category2Entity> categoryEntities) {...}`:定义了一个名为 `getCatChildren` 的私有方法,用于递归获取指定一级目录下的所有子结构数据,并返回处理后的子结构数据列表。

通过这个 Service 实现类,可以方便地处理目录行程数据的结构化处理和数据操作,适用于构建具有树形结构展示和操作需求的场景。整体设计较为复杂,但提供了丰富的数据处理和操作方法,能够满足较为复杂的业务逻辑需求。
package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.entity.Category2Entity;
import com.cqupt.software_1.mapper.Category2Mapper;
import com.cqupt.software_1.service.Category2Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

// TODO 公共模块新增类

@Service
public class Category2ServiceImpl extends ServiceImpl<Category2Mapper, Category2Entity>
        implements Category2Service {

    @Autowired
    Category2Mapper dataManagerMapper;


    @Autowired
    Category2Mapper category2Mapper;

    @Override
    public List<Category2Entity> getCategory() {

        // 获取所有目录行程树形结构
        List<Category2Entity> categoryEntities = dataManagerMapper.selectList(null);
        // 获取所有级结构
        List<Category2Entity> treeData = categoryEntities.stream().filter((Category2Entity) -> {
            return Category2Entity.getParentId().equals("0") && Category2Entity.getIsDelete()==0;
        }).map((level1Cat) -> {
            level1Cat.setChildren(getCatChildren(level1Cat, categoryEntities));;
            return level1Cat;
        }).collect(Collectors.toList());

        return treeData;
    }





    @Override
    public List<Category2Entity> getCategory2() {

        // 获取所有目录行程树形结构
        List<Category2Entity> categoryEntities = dataManagerMapper.selectList(null);
        // 获取所有级结构
        List<Category2Entity> treeData = categoryEntities.stream().filter((Category2Entity) -> {
            return Category2Entity.getParentId().equals("0") && Category2Entity.getIsDelete()==0;
        }).map((level1Cat) -> {
            level1Cat.setChildren(getSecondLevelChildren(level1Cat.getId()));;
            return level1Cat;
        }).collect(Collectors.toList());

        // 顶层以下都变为叶子结点
        for (Category2Entity treeDatum : treeData) {
            for (Category2Entity child : treeDatum.getChildren()) {
                child.setIsLeafs(1);
            }

        }
        return treeData;
    }


    // 获取第二层目录
    private List<Category2Entity> getSecondLevelChildren(String parentId) {
        // 获取所有第二层目录
        List<Category2Entity> secondLevelCategories = dataManagerMapper.selectList(null).stream()
                .filter(Category2Entity -> Category2Entity.getParentId().equals(parentId) && Category2Entity.getIsDelete() == 0)
                .map(level2Cat -> {
                    level2Cat.setChildren(new ArrayList<>()); // 第二层目录没有子目录
                    return level2Cat;
                })
                .collect(Collectors.toList());

        return secondLevelCategories;
    }


    @Override
    public void removeNode(String id) {
        category2Mapper.removeNode(id);
    }

    // 获取1级目录下的所有子结构
    private List<Category2Entity> getCatChildren(Category2Entity level1Cat, List<Category2Entity> categoryEntities) {
        List<Category2Entity> children = categoryEntities.stream().filter((CategoryEntity) -> {
            return CategoryEntity.getParentId().equals(level1Cat.getId()) && CategoryEntity.getIsDelete()==0; // 获取当前分类的所有子分类
        }).map((child) -> {
            // 递归设置子分类的所有子分类
            child.setChildren(getCatChildren(child, categoryEntities));
            return child;
        }).collect(Collectors.toList());
        return children;
    }
}

Category2ServiceImpl

这段代码是一个服务实现类 `Category2ServiceImpl`,通过实现 `Category2Service` 接口来提供分类目录的相关功能。

1. `Category2ServiceImpl` 类继承了 `ServiceImpl<Category2Mapper, Category2Entity>`,表明它是一个基于 MyBatis-Plus 的 service 实现类。

2. `getCategory()` 方法用于获取所有的分类目录并构建成树形结构。首先从数据库中查询所有的目录信息,然后根据父目录为 "0"(即顶层目录)并且未被删除的条件过滤出一级目录,在此基础上通过递归方式构建子目录的树形结构,最后返回完整的树形数据。

3. `getCategory2()` 方法与 `getCategory()` 类似,不同之处在于获取第二层目录结构时调用了 `getSecondLevelChildren()` 方法,并且在最后将所有非顶层目录设置为叶子结点。

4. `getSecondLevelChildren()` 方法用于获取指定父目录下的所有第二层子目录,根据指定的 parentId 进行过滤,同时确保子目录未被删除,并将每个子目录设置为叶子结点。

5. `removeNode(String id)` 方法用于删除指定 id 的节点,实际调用了 `category2Mapper` 的 `removeNode()` 方法进行删除操作。

6. `getCatChildren()` 方法用于获取指定一级目录下的所有子目录结构,通过递归方式构建完整的子目录树形结构。首先根据指定一级目录的 id 进行过滤,然后递归获取每个子目录的子目录,最终返回完整的子目录结构。

package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.entity.Category2Entity;
import com.cqupt.software_1.mapper.Category2Mapper;
import com.cqupt.software_1.service.Category2Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

// TODO 公共模块新增类

@Service
public class Category2ServiceImpl extends ServiceImpl<Category2Mapper, Category2Entity>
        implements Category2Service {

    @Autowired
    Category2Mapper dataManagerMapper;


    @Autowired
    Category2Mapper category2Mapper;

    @Override
    public List<Category2Entity> getCategory() {

        // 获取所有目录行程树形结构
        List<Category2Entity> categoryEntities = dataManagerMapper.selectList(null);
        // 获取所有级结构
        List<Category2Entity> treeData = categoryEntities.stream().filter((Category2Entity) -> {
            return Category2Entity.getParentId().equals("0") && Category2Entity.getIsDelete()==0;
        }).map((level1Cat) -> {
            level1Cat.setChildren(getCatChildren(level1Cat, categoryEntities));;
            return level1Cat;
        }).collect(Collectors.toList());

        return treeData;
    }





    @Override
    public List<Category2Entity> getCategory2() {

        // 获取所有目录行程树形结构
        List<Category2Entity> categoryEntities = dataManagerMapper.selectList(null);
        // 获取所有级结构
        List<Category2Entity> treeData = categoryEntities.stream().filter((Category2Entity) -> {
            return Category2Entity.getParentId().equals("0") && Category2Entity.getIsDelete()==0;
        }).map((level1Cat) -> {
            level1Cat.setChildren(getSecondLevelChildren(level1Cat.getId()));;
            return level1Cat;
        }).collect(Collectors.toList());

        // 顶层以下都变为叶子结点
        for (Category2Entity treeDatum : treeData) {
            for (Category2Entity child : treeDatum.getChildren()) {
                child.setIsLeafs(1);
            }

        }
        return treeData;
    }


    // 获取第二层目录
    private List<Category2Entity> getSecondLevelChildren(String parentId) {
        // 获取所有第二层目录
        List<Category2Entity> secondLevelCategories = dataManagerMapper.selectList(null).stream()
                .filter(Category2Entity -> Category2Entity.getParentId().equals(parentId) && Category2Entity.getIsDelete() == 0)
                .map(level2Cat -> {
                    level2Cat.setChildren(new ArrayList<>()); // 第二层目录没有子目录
                    return level2Cat;
                })
                .collect(Collectors.toList());

        return secondLevelCategories;
    }


    @Override
    public void removeNode(String id) {
        category2Mapper.removeNode(id);
    }

    // 获取1级目录下的所有子结构
    private List<Category2Entity> getCatChildren(Category2Entity level1Cat, List<Category2Entity> categoryEntities) {
        List<Category2Entity> children = categoryEntities.stream().filter((CategoryEntity) -> {
            return CategoryEntity.getParentId().equals(level1Cat.getId()) && CategoryEntity.getIsDelete()==0; // 获取当前分类的所有子分类
        }).map((child) -> {
            // 递归设置子分类的所有子分类
            child.setChildren(getCatChildren(child, categoryEntities));
            return child;
        }).collect(Collectors.toList());
        return children;
    }
}

CategoryServiceImpl


1. **CategoryServiceImpl类**:这是一个服务实现类,实现了CategoryService接口,用于处理分类相关的业务逻辑。

2. **getCategory()方法**:这个方法用于获取所有的分类信息,包括树形结构。首先从数据库中获取所有的分类实体列表,然后根据父子关系构建树形结构。同时,这个方法还过滤掉已删除的分类信息,并将"公共数据集"放在树形结构的最后。

3. **removeNode(String id)方法**:这个方法用于删除指定id的节点(即分类)。在执行删除操作之前,它记录了用户的操作日志,包括操作时间、用户名和操作类型。然后调用categoryMapper的removeNode方法执行删除操作。

4. **addParentDisease(String diseaseName)方法**:这个方法用于添加一个父病种分类。首先创建一个新的CategoryEntity实体对象,然后记录用户的操作日志,包括操作时间、用户名和操作类型。最后调用categoryMapper的insert方法将新的分类信息插入数据库。

5. **getCatChildren(CategoryEntity level1Cat, List<CategoryEntity> categoryEntities)方法**:这个方法用于获取指定一级分类下的所有子分类。它接收一个一级分类实体对象和所有分类实体的列表作为参数,然后根据父子关系过滤出当前一级分类的所有子分类,并递归地设置子分类的子分类,最终返回子分类列表。

整个类的目的是提供对分类信息的增删查改操作,并在需要时记录用户的操作日志。
package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.common.UserThreadLocal;
import com.cqupt.software_1.entity.CategoryEntity;
import com.cqupt.software_1.entity.UserLog;
import com.cqupt.software_1.mapper.CategoryMapper;
import com.cqupt.software_1.service.CategoryService;
import com.cqupt.software_1.service.UserLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

// TODO 公共模块新增类

@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, CategoryEntity>
        implements CategoryService {

    @Autowired
    CategoryMapper dataManagerMapper;
    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    UserLogService userLogService;
    @Override
    public List<CategoryEntity> getCategory() {

        // 获取所有目录行程树形结构
        List<CategoryEntity> categoryEntities = dataManagerMapper.selectList(null);
        // 获取所有级结构
        List<CategoryEntity> treeData = categoryEntities.stream().filter((categoryEntity) -> {
            return categoryEntity.getParentId().equals("0") && categoryEntity.getIsDelete()==0;
        }).map((level1Cat) -> {
            level1Cat.setChildren(getCatChildren(level1Cat, categoryEntities));;
            return level1Cat;
        }).collect(Collectors.toList());
        List<CategoryEntity> publicData = treeData.stream().filter(categoryEntity -> {
            return categoryEntity.getLabel().equals("公共数据集");
        }).collect(Collectors.toList());
        if(publicData!=null && publicData.size()>0){
            treeData.remove(publicData.get(0));
            treeData.add(publicData.get(0));
        }
        return treeData;
    }

    @Override
    public void removeNode(String id) {
        UserLog userLog = new UserLog();
        userLog.setOpTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        userLog.setUsername(UserThreadLocal.get().getUsername());
        userLog.setUid(UserThreadLocal.get().getUid());
        userLog.setOpType("删除病种数据信息");
        userLogService.save(userLog);
        categoryMapper.removeNode(id);
    }

    @Override
    public void addParentDisease(String diseaseName) {
        CategoryEntity categoryEntity = new CategoryEntity(null, 1, diseaseName, "0", 0, 0, "" + diseaseName, 0, 0, null);
        UserLog userLog = new UserLog();
        userLog.setOpTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        userLog.setUsername(UserThreadLocal.get().getUsername());
        userLog.setUid(UserThreadLocal.get().getUid());
        userLog.setOpType("添加新病种");
        userLogService.save(userLog);
        categoryMapper.insert(categoryEntity);
    }

    // 获取1级目录下的所有子结构
    private List<CategoryEntity> getCatChildren(CategoryEntity level1Cat, List<CategoryEntity> categoryEntities) {
        List<CategoryEntity> children = categoryEntities.stream().filter((categoryEntity) -> {
            return categoryEntity.getParentId().equals(level1Cat.getId()) && categoryEntity.getIsDelete()==0; // 获取当前分类的所有子分类
        }).map((child) -> {
            // 递归设置子分类的所有子分类
            child.setChildren(getCatChildren(child, categoryEntities));
            return child;
        }).collect(Collectors.toList());
        return children;
    }
}

DataServiceImpl

这段代码是一个Java类,位于`com.cqupt.software_1.service.impl`包中,名为`DataServiceImpl`。该类实现了一个接口`DataService`。在这个类中,有一个注入`DataMapper`的实例,用于数据访问。这个类中包含了两个方法:

1. `selectListById(Set<Integer> satisfiedSamples, String tableName)`方法:这个方法接收一个`Set<Integer>`类型的参数`satisfiedSamples`和一个`String`类型的参数`tableName`。它调用`dataMapper`的`selectListById`方法来查询满足条件的样本列表,并返回一个包含Map对象的列表。这些Map对象代表数据库中对应于满足条件的样本的记录。

2. `getBarCoordinates(String tableName, String field)`方法:这个方法接收两个`String`类型的参数`tableName`和`field`。它调用`dataMapper`的`getBarCoordinates`方法来获取指定表和字段的柱状坐标数据。返回一个包含`BarCoordinate`对象的`ArrayList`,其中`BarCoordinate`对象表示柱状图中的坐标点。
package com.cqupt.software_1.service.impl;

import com.cqupt.software_1.entity.BarCoordinate;
import com.cqupt.software_1.mapper.DataMapper;
import com.cqupt.software_1.service.DataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;


@Service
public class DataServiceImpl implements DataService {

    @Autowired
    private DataMapper dataMapper;

    @Override
    public List<Map<String, Object>> selectListById(Set<Integer> satisfiedSamples, String tableName) {
        return dataMapper.selectListById(satisfiedSamples,tableName);
    }

    @Override
    public ArrayList<BarCoordinate> getBarCoordinates(String tableName, String field) {
        ArrayList<BarCoordinate> coordinates = dataMapper.getBarCoordinates(tableName,field);
        return coordinates;
    }
}

DataTableManagerServiceImpl

这段代码是一个Java服务实现类,实现了`DataTableManagerService`接口。首先导入了所需的包,并标注了`@Service`注解,表示这是一个Spring的服务类。

1. `upalldata()`函数:从数据库中获取所有数据表的信息并返回。

2. `deletename(String tablename)`函数:根据传入的表名删除数据库中对应的表。

3. `upname()`函数:从数据库中获取所有表名并返回。

4. `getTableData(String tableId, String tableName)`函数:根据传入的表名,从数据库中获取该表的数据并返回。

5. `updateDataTable(String table_name,String disease)`函数:根据传入的表名和疾病信息,计算样本数和特征数,并将相关信息插入数据库中的`data_table`表。

6. `calculateFeatureNumber(String tableName)`函数:根据表名,计算该表的特征数。

7. `calculateSampleSize(String tableName)`函数:根据表名,计算该表的样本数。

这些函数主要用于数据库操作,包括获取数据、删除表、获取表名、获取表数据以及更新表信息等。同时,代码中使用了JDBC连接数据库,并在每个函数中实现了异常处理逻辑。
package com.cqupt.software_1.service.impl;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.common.DataTable;
import com.cqupt.software_1.mapper.DataTableManagerMapper;
import com.cqupt.software_1.service.DataTableManagerService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@Service
public class DataTableManagerServiceImpl extends ServiceImpl<DataTableManagerMapper,DataTable> implements DataTableManagerService {


    String  dbUrl = "jdbc:mysql://10.16.48.219:3306/medical?characterEncoding=utf-8";
    String dbUsername = "root";
    String dbPassword = "111111";

    @Resource
    private DataTableManagerMapper dataTableManagerMapper;


    @Override
    public List<DataTable> upalldata() {
        return dataTableManagerMapper.upalldata();
    }


    @Override
    public void deletename(String tablename) {
        dataTableManagerMapper.deletetablename(tablename);
    }

    @Override
    public List<String> upname() {
        return dataTableManagerMapper.upname();
    }

    @Override
    public List<Map<String, Object>> getTableData(String tableId, String tableName) {
        List<Map<String, Object>> tableData = dataTableManagerMapper.getTableData(tableName);
        return tableData;
    }

    @Override
    public void updateDataTable(String table_name,String disease) {
        // 在这里实现计算样本数和特征数的逻辑
        int featurenumber = calculateFeatureNumber(table_name);
        int samplesize = calculateSampleSize(table_name);

        // 创建一个新的数据对象
        DataTable dataTableEntity = new DataTable();
        dataTableEntity.setTable_name(table_name);
        dataTableEntity.setFeaturenumber(featurenumber);
        dataTableEntity.setSamplesize(samplesize);
//        dataTableEntity.setTableType("Your Table Type"); // 替换为表类型信息
        dataTableEntity.setDisease(disease); // 替换为疾病信息
        dataTableEntity.setCreator("杨星"); // 替换为创建者信息

        // 插入新样本数据到data_table表中
        dataTableManagerMapper.insertDataTable(dataTableEntity);
    }

    private int calculateFeatureNumber(String tableName) {
        try {
            // 建立数据库连接


            Connection connection = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
            Statement statement = connection.createStatement();

            // 查询表头
            String query = "SELECT * FROM " +"`"+tableName+"`" + " LIMIT 1";
            ResultSet resultSet = statement.executeQuery(query);
            int featureNumber = resultSet.getMetaData().getColumnCount();

            // 关闭连接
            resultSet.close();
            statement.close();
            connection.close();

            return featureNumber;
        } catch (Exception e) {
            // 处理异常情况
            e.printStackTrace();
            return 0; // 或者抛出异常
        }
    }

    // 计算样本数的方法
    private int calculateSampleSize(String tableName) {
        try {
            // 建立数据库连接

            Connection connection = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
            Statement statement = connection.createStatement();

            // 查询数据行数
            String query = "SELECT COUNT(*) AS rowCount FROM " + "`"+tableName+"`";
            ResultSet resultSet = statement.executeQuery(query);
            int rowCount = 0;
            if (resultSet.next()) {
                rowCount = resultSet.getInt("rowCount");
            }

            // 关闭连接
            resultSet.close();
            statement.close();
            connection.close();

            // 减去表头行数(假设第一行是表头)
            return rowCount - 1;
        } catch (Exception e) {
            // 处理异常情况
            e.printStackTrace();
            return 0; // 或者抛出异常
        }
    }

//    @Override
//    public boolean save(DataTable dataTable) {
//        return false;
//    }
//
//    @Override
//    public boolean saveBatch(Collection<DataTable> collection, int i) {
//        return false;
//    }
//
//    @Override
//    public boolean saveOrUpdateBatch(Collection<DataTable> collection) {
//        return false;
//    }
//
//    @Override
//    public boolean saveOrUpdateBatch(Collection<DataTable> collection, int i) {
//        return false;
//    }
//
//    @Override
//    public boolean removeById(Serializable serializable) {
//        return false;
//    }
//
//    @Override
//    public boolean removeByMap(Map<String, Object> map) {
//        return false;
//    }
//
//    @Override
//    public boolean remove(Wrapper<DataTable> wrapper) {
//        return false;
//    }
//
//    @Override
//    public boolean removeByIds(Collection<? extends Serializable> collection) {
//        return false;
//    }
//
//    @Override
//    public boolean updateById(DataTable dataTable) {
//        return false;
//    }
//
//    @Override
//    public boolean update(DataTable dataTable, Wrapper<DataTable> wrapper) {
//        return false;
//    }
//
//    @Override
//    public boolean updateBatchById(Collection<DataTable> collection, int i) {
//        return false;
//    }
//
//    @Override
//    public boolean saveOrUpdate(DataTable dataTable) {
//        return false;
//    }
//
//    @Override
//    public DataTable getById(Serializable serializable) {
//        return null;
//    }
//
//    @Override
//    public Collection<DataTable> listByIds(Collection<? extends Serializable> collection) {
//        return null;
//    }
//
//    @Override
//    public Collection<DataTable> listByMap(Map<String, Object> map) {
//        return null;
//    }
//
//    @Override
//    public DataTable getOne(Wrapper<DataTable> wrapper, boolean b) {
//        return null;
//    }
//
//    @Override
//    public Map<String, Object> getMap(Wrapper<DataTable> wrapper) {
//        return null;
//    }
//
//    @Override
//    public Object getObj(Wrapper<DataTable> wrapper) {
//        return null;
//    }
//
//    @Override
//    public long count(Wrapper<DataTable> wrapper) {
//        return 0;
//    }
//
//    @Override
//    public List<DataTable> list(Wrapper<DataTable> wrapper) {
//        return null;
//    }
//
//    @Override
//    public IPage<DataTable> page(IPage<DataTable> iPage, Wrapper<DataTable> wrapper) {
//        return null;
//    }
//
//    @Override
//    public List<Map<String, Object>> listMaps(Wrapper<DataTable> wrapper) {
//        return null;
//    }
//
//    @Override
//    public List<Object> listObjs(Wrapper<DataTable> wrapper) {
//        return null;
//    }
//
//    @Override
//    public IPage<Map<String, Object>> pageMaps(IPage<DataTable> iPage, Wrapper<DataTable> wrapper) {
//        return null;
//    }
}

FeatureManageServiceImpl

这段代码是一个Java类,用于实现特征管理服务。让我逐个函数和接口详细介绍一下:

1. `FeatureManageServiceImpl` 类:
   - 这是特征管理服务的实现类。
   - 通过 `ServiceImpl` 类来实现 MyBatis-Plus 提供的通用服务。
   - 该类标注了 `@Service` 注解,表明它是一个服务类,会被Spring框架管理。

2. `getFeatureList` 方法:
   - 该方法用于获取特征列表。
   - 参数 `belongType` 表示特征所属类型。
   - 首先通过 `featureManageMapper` 查询数据库中的特征信息。
   - 然后将查询结果封装成 `FeatureVo` 对象列表,并返回。

3. `insertFeatures` 方法:
   - 该方法用于插入特征信息。
   - 参数 `featureListVo` 是包含特征信息的对象。
   - 首先从 `featureListVo` 中获取特征信息,并封装成 `FeatureEntity` 对象列表。
   - 该方法目前被标注为作废方法,不需要实现。

这段代码中还有一些 `TODO` 注释,表示需要进一步完善的部分,比如特征的中文解释、类型等信息。
package com.cqupt.software_1.service.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cqupt.software_1.entity.FeatureEntity;
import com.cqupt.software_1.mapper.FeatureManageMapper;
import com.cqupt.software_1.service.FeatureManageService;
import com.cqupt.software_1.vo.FeatureClassVo;
import com.cqupt.software_1.vo.FeatureListVo;
import com.cqupt.software_1.vo.FeatureVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

// TODO 公共模块新增类

@Service
public class FeatureManageServiceImpl extends ServiceImpl<FeatureManageMapper, FeatureEntity> implements FeatureManageService {
    @Autowired
    FeatureManageMapper featureManageMapper;
    @Override
    public List<FeatureVo> getFeatureList(String belongType) {
        List<FeatureEntity> featureEntities = featureManageMapper.selectFeatures(belongType);
        //封装vo
        ArrayList<FeatureVo> featureVos = new ArrayList<>();
        for (FeatureEntity featureEntity : featureEntities) {
            FeatureVo featurevVo = new FeatureVo();
            featurevVo.setCharacterId(featureEntity.getCharacterId());
            featurevVo.setChName(featureEntity.getChName());
            featurevVo.setFeatureName(featureEntity.getFeatureName());
            featurevVo.setUnit(featureEntity.getUnit());
            //TODO 封装字段是否离散 离散就是discrete  连续就是continuous

            //TODO 如果离散就封装取值 连续就是封装范围
            featureVos.add(featurevVo);
        }
        return featureVos;
    }

    @Override
    public void insertFeatures(FeatureListVo featureListVo) {
        // 封装对象信息
        List<FeatureClassVo> tableHeaders = featureListVo.getTableHeaders();
        ArrayList<FeatureEntity> featureEntities = new ArrayList<>();
        for (FeatureClassVo tableHeader : tableHeaders) {
            FeatureEntity featureEntity = new FeatureEntity();
            featureEntity.setChName(null);// TODO 特征中文解释
            featureEntity.setFeatureName(tableHeader.getFieldName());
            featureEntity.setUnit("character varying"); // TODO  特征类型
            featureEntity.setDiseaseStandard(false);
            if(tableHeader.getIsDiagnosis()=="1") featureEntity.setDiagnosis(true);
            if(tableHeader.getIsPathology()=="1") featureEntity.setPathology(true);
            if(tableHeader.getIsExamine()=="1") featureEntity.setExamine(true);
            if(tableHeader.getIsLabel()=="1") featureEntity.setLabel(true);
            if(tableHeader.getIsVitalSigns()=="1") featureEntity.setVitalSigns(true);
            featureEntities.add(featureEntity);
        }
        // TODO 作废方法,不需要完成
    }
}

FieldManagementServiceImpl

这段代码是另一个 Java 类,用于实现字段管理服务。让我逐个函数和接口详细介绍一下:

1. `FieldManagementServiceImpl` 类:
   - 这是字段管理服务的实现类。
   - 通过 `ServiceImpl` 类来实现 MyBatis-Plus 提供的通用服务。
   - 该类标注了 `@Service` 注解,表明它是一个服务类,会被 Spring 框架管理。

2. `getFieldsByType` 方法:
   - 该方法用于根据字段类型获取字段列表。
   - 参数 `indexEnNames` 是一个包含字段英文名的列表。
   - 调用 `fieldManagementMapper` 的 `getFieldsByType` 方法来查询指定类型的字段信息,并返回结果。

3. `getFiledByDiseaseName` 方法:
   - 该方法用于根据疾病名称获取字段列表。
   - 参数 `diseaseName` 表示疾病名称。
   - 调用 `fieldManagementMapper` 的 `getFiledByDiseaseName` 方法来查询与指定疾病相关的字段信息,并返回结果。

4. `updateFieldsByDiseaseName` 方法:
   - 该方法用于更新特定疾病名称相关的字段。
   - 参数 `diseaseName` 表示疾病名称,`fields` 是一个包含要更新的字段名的列表。
   - 调用 `fieldManagementMapper` 的 `updateFieldsByDiseaseName` 方法来更新指定疾病名称相关的字段信息。

这段代码中同样存在 `TODO` 注释,表示需要进一步完善的部分,比如新增类的信息。
package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.entity.FieldManagementEntity;
import com.cqupt.software_1.mapper.FieldManagementMapper;
import com.cqupt.software_1.service.FieldManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

// TODO 公共模块新增类

@Service
public class FieldManagementServiceImpl extends ServiceImpl<FieldManagementMapper, FieldManagementEntity> implements FieldManagementService {
    @Autowired
    FieldManagementMapper fieldManagementMapper;
    @Override
    public List<FieldManagementEntity> getFieldsByType(List<String> indexEnNames) {
        return fieldManagementMapper.getFieldsByType(indexEnNames);
    }

    @Override
    public List<FieldManagementEntity> getFiledByDiseaseName(String diseaseName) {

        List<FieldManagementEntity> res = fieldManagementMapper.getFiledByDiseaseName(diseaseName);

        return res;
    }

    @Override
    public void updateFieldsByDiseaseName(String diseaseName, List<String> fields) {

        fieldManagementMapper.updateFieldsByDiseaseName(diseaseName, fields);
    }
}

FileServiceImpl

这段代码是一个基于Spring框架的文件上传服务实现。让我逐步解释:

1. `FileServiceImpl` 类实现了 `FileService` 接口,该接口定义了文件上传的方法。

2. `fileUpload` 方法用于处理文件上传。它接受一个 `MultipartFile` 对象,表示上传的文件,以及一个新的表名 `newName` 和一个疾病名 `disease`。

3. 在 `fileUpload` 方法中,首先检查上传的文件是否是 CSV 格式,如果不是则抛出异常。

4. 接着从上传的 CSV 文件中读取数据,处理表头,去除空格,并保存处理后的数据行。

5. 然后,通过 JDBC 连接数据库,创建新表并插入数据。表名由参数 `newName` 决定,表结构和数据由上传的 CSV 文件确定。

6. 插入数据时,采用批处理方式,每 1000 条数据执行一次批处理,以提高效率。

7. 最后,调用 `dataTableManagerService` 的方法更新数据表,传入新创建的表名和疾病名。

8. 返回一个 `UploadResult` 对象,其中包含上传结果的相关信息,如表名、表头等。

整个过程实现了从上传文件到数据库插入数据的流程,同时保证了代码的健壮性和效率。

这段代码是用Java编写的,主要功能是生成SQL插入语句和创建数据库表。让我来逐个介绍每个函数和接口的作用:

1. `generateInsertQuery` 函数:
   - 输入参数:表名 `tableName` 和列名数组 `columnNames`。
   - 返回值:生成的SQL插入语句。
   - 作用:根据传入的表名和列名数组,动态生成带有占位符 `?` 的SQL插入语句,用于向数据库表中插入数据。

2. `createTable` 函数:
   - 输入参数:数据库连接 `connection`、表名 `tableName`、表头列表 `tableHeaders`、行数据列表 `rows`。
   - 作用:根据传入的表名、表头列表和行数据列表,动态生成创建表的SQL语句,并通过数据库连接执行该语句创建表。

3. `determineColumnType` 函数:
   - 输入参数:列名 `columnName`、行数据列表 `rows`、表头列表 `tableHeaders`。
   - 返回值:根据数据类型判断的数据库列类型。
   - 作用:根据传入的列名、行数据列表和表头列表,判断该列的数据类型(整数、浮点数、日期等),并返回相应的数据库列类型(INT、DOUBLE、DATE、VARCHAR)。

在这些函数中,使用了 `StringBuilder` 来拼接SQL语句,避免了字符串连接操作的性能消耗。另外,还用到了异常处理机制来处理数据类型转换可能出现的异常,确保程序的稳定性和可靠性。
package com.cqupt.software_1.service.impl;

import com.cqupt.software_1.common.UploadResult;
import com.cqupt.software_1.service.DataTableManagerService;
import com.cqupt.software_1.service.FileService;
import com.opencsv.CSVReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;


@Service
public class FileServiceImpl implements FileService {


    @Resource
    private DataTableManagerService dataTableManagerService;

    @Value("${spring.datasource.url}")
    private String dbUrl;
    @Value("${spring.datasource.username}")
    private String dbUsername;
    @Value("${spring.datasource.password}")
    private String dbPassword;



    @Override
    @Transactional
    public UploadResult fileUpload(MultipartFile file, String newName, String disease) throws IOException {

        System.out.println(dbUrl);
        System.out.println(dbUsername);
        System.out.println(dbPassword);

        System.out.println("文件名字" + file.getOriginalFilename());
        if (!file.getOriginalFilename().endsWith(".csv")) {
            throw new IllegalArgumentException("Only CSV files are supported.");
        }


        String tableName = newName;

        List<String> tableHeaders;
        List<String[]> rows = new ArrayList<>(); // 存储处理后的数据行

        try (CSVReader csvReader = new CSVReader(new InputStreamReader(file.getInputStream()))) {
            String[] columnNames = csvReader.readNext();
            //去空格
            tableHeaders = new ArrayList<>();
            for (int i = 0; i < columnNames.length; i++) {
                String columnName = columnNames[i].trim();
                if (!columnName.isEmpty()) {
                    tableHeaders.add(columnName);
                }
            }
            String[] tableHeadersArray = tableHeaders.toArray(new String[0]);
            System.out.println("表头:" + tableHeaders);
            // 读取数据行并删除空表头对应的整列数据
            String[] row;
            while ((row = csvReader.readNext()) != null) {

                String[] newRow = new String[tableHeaders.size()];
                int newIndex = 0;
                for (int i = 0; i < row.length; i++) {
                    if (!columnNames[i].trim().isEmpty()) {
                        newRow[newIndex++] = row[i];
                    }
                }
                rows.add(newRow);
            }


            System.out.println("rows: "+rows);
            try (Connection connection = DriverManager.getConnection(dbUrl, dbUsername, dbPassword)) {
                createTable(connection, tableName, tableHeaders, rows);

                String insertQuery = generateInsertQuery(tableName, tableHeadersArray);
                System.out.println(insertQuery);

                int batchCount = 0;

                for (String[] data : rows) {
                    batchCount++;
                    try (PreparedStatement statement = connection.prepareStatement(insertQuery)) {

                        for (int i = 0; i < data.length; i++) {
                            // 去除列名中的空格
                            String columnName = tableHeaders.get(i).trim();
                            statement.setString(i + 1, data[i]);
                        }
                        statement.addBatch();
                        if (batchCount % 1000 == 0) {
                            statement.executeBatch();
                        }
                        statement.executeUpdate();

                    } catch (SQLException e) {
                        throw new RuntimeException("Failed to insert data into the database.", e);
                    }
                }

            } catch (SQLException e) {
                throw new RuntimeException("Failed to create table or establish connection to the database.", e);
            }
        } catch (IOException e) {
            throw new RuntimeException("Failed to read CSV file.", e);
        }
        dataTableManagerService.updateDataTable(tableName,disease);

//        return tableName;
        // 创建并返回UploadResult对象
        UploadResult result = new UploadResult();
        result.setTableName(tableName);
        result.setTableHeaders(tableHeaders);
        result.setCode(200);

        return result;
    }

    private String generateInsertQuery(String tableName, String[] columnNames) {

        StringBuilder sb = new StringBuilder();
        sb.append("INSERT INTO ");
        sb.append("`"); // 添加反引号(`)开始包围列名
        sb.append(tableName);
        sb.append("`"); // 添加反引号(`)结束包围列名
        sb.append(" (");

        for (int i = 0; i < columnNames.length; i++) {
            sb.append("`"); // 添加反引号(`)开始包围列名
            sb.append(columnNames[i]);
            sb.append("`"); // 添加反引号(`)结束包围列名

            if (i < columnNames.length - 1) {
                sb.append(", ");
            }
        }

        sb.append(") VALUES (");

        for (int i = 0; i < columnNames.length; i++) {
            sb.append("?");

            if (i < columnNames.length - 1) {
                sb.append(", ");
            }
        }

        sb.append(")");
        return sb.toString();
    }

    private void createTable(Connection connection, String tableName, List<String> tableHeaders, List<String[]> rows) {
        StringBuilder createTableQuery = new StringBuilder();
        createTableQuery.append("CREATE TABLE ");
        createTableQuery.append("`"); // 添加反引号(`)开始包围列名
        createTableQuery.append(tableName);
        createTableQuery.append("`"); // 添加反引号(`)结束包围列名
        createTableQuery.append(" (");
        for (int i = 0; i < tableHeaders.size(); i++) {
            String columnName = tableHeaders.get(i);
            String columnType = determineColumnType(columnName, rows,tableHeaders);
            // 使用反引号包裹列名
            createTableQuery.append("`").append(columnName).append("`").append(" ").append(columnType);
            if (i < tableHeaders.size() - 1) {
                createTableQuery.append(", ");
            }
        }
        createTableQuery.append(")");

        try (PreparedStatement statement = connection.prepareStatement(createTableQuery.toString())) {
            statement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("Failed to create table.", e);
        }
    }

    private String determineColumnType(String columnName, List<String[]> rows, List<String> tableHeaders) {

        // 判断数据是否为整数
        boolean isInt = true;
        // 判断数据是否为浮点数
        boolean isDouble = true;
        // 判断数据是否为日期,这里假设日期格式为"yyyy-MM-dd",你可以根据实际情况修改格式
        boolean isDate = true;

        for (String[] row : rows) {
            String data = row[tableHeaders.indexOf(columnName)];
            // 判断是否为整数
            try {
                Integer.parseInt(data);
            } catch (NumberFormatException e) {
                isInt = false;
            }

            // 判断是否为浮点数
            try {
                Double.parseDouble(data);
            } catch (NumberFormatException e) {
                isDouble = false;
            }

            // 判断是否为日期
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            try {
                LocalDate.parse(data, dateFormatter);
            } catch (DateTimeParseException e) {
                isDate = false;
            }

            // 如果有一行不符合整数、浮点数、或日期的格式,则退出循环
            if (!isInt && !isDouble && !isDate) {
                break;
            }
        }

        // 根据判断结果返回对应的列类型
        if (isInt) {
            return "INT";
        } else if (isDouble) {
            return "DOUBLE";
        } else if (isDate) {
            return "DATE";
        } else {
            // 如果以上条件都不满足,则返回默认的VARCHAR类型,长度为255
            return "VARCHAR(255)";
        }

    }
}

IndicatorManagementServiceImpl

这段代码是一个Java Spring Boot服务的实现部分,主要用于管理指标(Indicator)相关的操作。以下是每个函数和接口的详细介绍:

1. `IndicatorManagementServiceImpl` 类

   - `getIndicators(List<String> types, String tableName)` 方法:
     - 输入参数:类型列表 `types` 和表名 `tableName`
     - 输出:返回一个包含 `IndicatorManageEntity` 对象的列表
     - 功能:根据检查类型获取字段以及表中每一个字段的缺失率,首先根据中文名称获取值指标类型英文名,然后获取字段管理实体列表,并根据字段的特征进行处理,设置特征名称、标签、数据类型、缺失填充方法等信息,最后计算每个字段的缺失率并返回结果。

   - `getIndicatorsInfo(List<IndicatorManageEntity> checkedFeats, String tableName)` 方法:
     - 输入参数:已选特征列表 `checkedFeats` 和表名 `tableName`
     - 输出:返回一个包含 `IndicatorsMissDataVo` 对象的列表
     - 功能:根据特征名称和表名查询有效值、缺失值个数,并返回结果,用于显示指标的详细信息。

2. 内部依赖注入的组件和接口:

   - `IndicatorManagementMapper`:用于操作指标管理的数据访问层接口。
   - `TableDataMapper`:用于操作表数据的数据访问层接口。
   - `IndicatorService`:指标服务接口,提供获取值指标类型英文名的方法。
   - `FieldManagementService`:字段管理服务接口,提供获取字段信息的方法。
   - `CategoryMapper`:类别映射器,用于操作类别相关数据的接口。
   - `TaskMapper`:任务映射器,用于操作任务相关数据的接口。

3. `IndicatorManageEntity` 类:指标管理实体类,用于描述指标的属性和信息,如特征名称、标签、数据类型、缺失率等。

4. `IndicatorsMissDataVo` 类:指标缺失数据信息视图对象类,用于描述指标的缺失数据信息,如有效值、缺失值个数、缺失填充方法等。



1. `IndicatorManagementServiceImpl` 类

   - `getIndicators(List<String> types, String tableName)` 方法:
     - 输入参数:类型列表 `types` 和表名 `tableName`
     - 输出:返回一个包含 `IndicatorManageEntity` 对象的列表
     - 功能:根据检查类型获取字段以及表中每一个字段的缺失率,首先根据中文名称获取值指标类型英文名,然后获取字段管理实体列表,并根据字段的特征进行处理,设置特征名称、标签、数据类型、缺失填充方法等信息,最后计算每个字段的缺失率并返回结果。

   - `getIndicatorsInfo(List<IndicatorManageEntity> checkedFeats, String tableName)` 方法:
     - 输入参数:已选特征列表 `checkedFeats` 和表名 `tableName`
     - 输出:返回一个包含 `IndicatorsMissDataVo` 对象的列表
     - 功能:根据特征名称和表名查询有效值、缺失值个数,并返回结果,用于显示指标的详细信息。

2. 内部依赖注入的组件和接口:

   - `IndicatorManagementMapper`:用于操作指标管理的数据访问层接口。
   - `TableDataMapper`:用于操作表数据的数据访问层接口。
   - `IndicatorService`:指标服务接口,提供获取值指标类型英文名的方法。
   - `FieldManagementService`:字段管理服务接口,提供获取字段信息的方法。
   - `CategoryMapper`:类别映射器,用于操作类别相关数据的接口。
   - `TaskMapper`:任务映射器,用于操作任务相关数据的接口。

3. `IndicatorManageEntity` 类:指标管理实体类,用于描述指标的属性和信息,如特征名称、标签、数据类型、缺失率等。

4. `IndicatorsMissDataVo` 类:指标缺失数据信息视图对象类,用于描述指标的缺失数据信息,如有效值、缺失值个数、缺失填充方法等。

总体来说,这段代码实现了根据不同检查类型获取相应字段的缺失率信息,并能够查看指标的详细缺失数据信息,用于数据管理和分析。
package com.cqupt.software_1.service.impl;

import com.alibaba.fastjson.JSON;
import com.cqupt.software_1.common.MissDataCompleteMethods;
import com.cqupt.software_1.common.RunPyEntity;
import com.cqupt.software_1.common.UserThreadLocal;
import com.cqupt.software_1.entity.FieldManagementEntity;
import com.cqupt.software_1.entity.IndicatorCategory;
import com.cqupt.software_1.entity.IndicatorManageEntity;
import com.cqupt.software_1.entity.Task;
import com.cqupt.software_1.mapper.CategoryMapper;
import com.cqupt.software_1.mapper.IndicatorManagementMapper;
import com.cqupt.software_1.mapper.TableDataMapper;
import com.cqupt.software_1.mapper.TaskMapper;
import com.cqupt.software_1.service.FieldManagementService;
import com.cqupt.software_1.service.IndicatorManagementService;
import com.cqupt.software_1.service.IndicatorService;
import com.cqupt.software_1.utils.HTTPUtils;
import com.cqupt.software_1.vo.DataFillMethodVo;
import com.cqupt.software_1.vo.IndicatorsMissDataVo;
import com.cqupt.software_1.vo.IsFillVo;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class IndicatorManagementServiceImpl implements IndicatorManagementService {

    @Autowired
    IndicatorManagementMapper indicatorManagementMapper;
    @Autowired
    TableDataMapper tableDataMapper;
    @Autowired
    IndicatorService indicatorService;
    @Autowired
    FieldManagementService fieldManagementService;
    @Autowired
    CategoryMapper categoryMapper;
    @Autowired
    private TaskMapper taskMapper;

    // TODO 根据检查类型获取字段以及表中每一个字段的缺失率
    @Override
    public List<IndicatorManageEntity> getIndicators(List<String> types,String tableName) {
        // 跟据中文名称获取值指标类型英文名
        List<IndicatorCategory> categories = indicatorService.getEnName(types);
        List<IndicatorManageEntity> list = new ArrayList<>();
        List<String> indexEnNames = categories.stream().map(indicatorCategory -> {
            return indicatorCategory.getIndicator();
        }).collect(Collectors.toList());
        List<FieldManagementEntity> fieldManagementEntities = fieldManagementService.getFieldsByType(indexEnNames);
        for (FieldManagementEntity fieldManagementEntity : fieldManagementEntities) {
            IndicatorManageEntity indicatorManageEntity = new IndicatorManageEntity();
            indicatorManageEntity.setFeatureName(fieldManagementEntity.getFeatureName());
            indicatorManageEntity.setLabel(fieldManagementEntity.getChName());
            indicatorManageEntity.setDiscrete(fieldManagementEntity.getDiscrete());
            if(fieldManagementEntity.getUnit()!=null && !fieldManagementEntity.getUnit().equals("character varying")) {
                if(fieldManagementEntity.getDiscrete()!=null && fieldManagementEntity.getDiscrete()) {
                    indicatorManageEntity.setFeatureDataType(2); // 数字离散
                    indicatorManageEntity.setMissCompleteMethod("前向填充");
                }
                else {
                    indicatorManageEntity.setFeatureDataType(1); // 数字连续
                    indicatorManageEntity.setMissCompleteMethod("均数替换");
                }
            }else {
                if(indicatorManageEntity.getDiscrete()!=null && indicatorManageEntity.getDiscrete()){
                    indicatorManageEntity.setFeatureDataType(3); // 文本数据离散
                    indicatorManageEntity.setMissCompleteMethod("前向填充");
                }else continue; // 文本非离散 无法分析
            }
            if(fieldManagementEntity.getIsDemography()) {
                indicatorManageEntity.setType("diagnosis");
                indicatorManageEntity.setTypeCh("人口学指标");
            }else if(fieldManagementEntity.getIsPhysiological()){
                indicatorManageEntity.setType("vital_sign");
                indicatorManageEntity.setTypeCh("生理学指标");
            }else if(fieldManagementEntity.getIsSociology()){
                indicatorManageEntity.setType("pathology");
                indicatorManageEntity.setTypeCh("社会学指标");
            }else{
                indicatorManageEntity.setType("other_index");
                indicatorManageEntity.setTypeCh("其他类型指标");
            }
            float missRate = indicatorManagementMapper.getMissRate(indicatorManageEntity.getFeatureName(),tableName); // 缺失率
            indicatorManageEntity.setMissRate(missRate);

            list.add(indicatorManageEntity);
        }
        return list;
    }
    @Override
    public List<IndicatorsMissDataVo> getIndicatorsInfo(List<IndicatorManageEntity> checkedFeats, String tableName) {
        System.out.println("------------------------");
        System.out.println("tableName:"+tableName+" cheackedFeacts:"+JSON.toJSONString(checkedFeats));
        // 跟据特征名称和表名查询有效值,缺失值个数
        List<IndicatorsMissDataVo> indicatorsMissDataVos = new ArrayList<>();
        for (IndicatorManageEntity checkedFeat : checkedFeats) {
            IndicatorsMissDataVo vo  = indicatorManagementMapper.getMissDataInfo(checkedFeat,tableName);
            vo.setIndex(checkedFeat.getFeatureName());
            vo.setMissCompleteMethod(checkedFeat.getMissCompleteMethod());
            indicatorsMissDataVos.add(vo);
        }
        return indicatorsMissDataVos;
    }

    @Override
    public List<Map<String,IsFillVo>> fillData(DataFillMethodVo dataFillMethodVo) {
        List<IndicatorsMissDataVo> missCompleteMethod = dataFillMethodVo.getMissCompleteMethod();
        List<Map<String,IsFillVo>> res = new ArrayList<>();
        List<List<IsFillVo>> tempRes = new ArrayList<>();
        // 调用远程算法进行缺失值补齐  传递表名称 字段名称
        try
        {
            for (IndicatorsMissDataVo vo : missCompleteMethod) {
                System.out.println("算法为:"+vo.getMissCompleteMethod());
                MissDataCompleteMethods missDataCompleteMethods = new MissDataCompleteMethods();
                String path = missDataCompleteMethods.methodMap.get(vo.getMissCompleteMethod());
                System.out.println("路径为:"+path);
                 if(path==null || path.equals("")) continue;
                List<String> cols = new ArrayList<>();
                cols.add(vo.getIndex());
                RunPyEntity runPyEntity = new RunPyEntity(dataFillMethodVo.getTableName(),path,cols, 1); // 每一列都是不同的填充算法
                JsonNode jsonNode = HTTPUtils.postRequest(runPyEntity, path);
                List<String> oldData = getJsonNodeData(jsonNode,"old_data"); // 不论该列是和类型都将起数据封装成String类型
                List<String> new_data = getJsonNodeData(jsonNode, "new_data");
                // 封装该列数据的每一行值是否是被填充的
                List<IsFillVo> isFillVos = new ArrayList<>();
                for (int i=0; i<new_data.size(); i++) { // 这是某一列的插补处理
                    IsFillVo isFillVo = new IsFillVo();
                    isFillVo.setColName(vo.getIndex()); // 列名
                    isFillVo.setValue(new_data.get(i));
                    if(oldData.get(i)==null|| oldData.get(i).equals("null") || oldData.get(i).equals("NaN"))  isFillVo.setFlag(true);
                    else isFillVo.setFlag(false);
                    isFillVos.add(isFillVo);

                }
                tempRes.add(isFillVos);
            }
            // 将tempRes封装到res
            System.out.println("tempRes = "+JSON.toJSONString(tempRes));
            int colLength = tempRes.size();
            int rowlength = tempRes.get(0).size();
            for(int j=0; j<rowlength; j++){ // 行
                // 封装一行的数据
                LinkedHashMap<String, IsFillVo> map = new LinkedHashMap<>();
                for(int i=0; i<colLength; i++){ // 列
                    map.put(tempRes.get(i).get(j).getColName(),tempRes.get(i).get(j));
                }
                res.add(map);
            }
            // 创建任务模型
            Task task = new Task();
            // 获取当前时间的 LocalDateTime 对象
            LocalDateTime now = LocalDateTime.now();
            Timestamp timestamp = Timestamp.valueOf(now);
            task.setCreatetime(timestamp);
            task.setDataset(dataFillMethodVo.getTableName());

            List<String> featureNames = dataFillMethodVo.getMissCompleteMethod().stream().map(indicatorsMissDataVo -> {
                return indicatorsMissDataVo.getIndex();
            }).collect(Collectors.toList());
            String str = featureNames.stream().collect(Collectors.joining(","));

            task.setFeature(str); //有哪些列
            task.setTargetcolumn(str);

            task.setLeader(UserThreadLocal.get().getUsername());

            String models = dataFillMethodVo.getMissCompleteMethod().stream().map(indicatorsMissDataVo -> {
                return indicatorsMissDataVo.getMissCompleteMethod();
            }).collect(Collectors.joining(","));
            task.setModel(models); // 每列的插补算法

            task.setTaskname("缺失值补齐");
            // 跟据表名获取父节点的名称 select label from category where "id"=(select parent_id from category where label='copd')
            String label = categoryMapper.setParentLabelByLabel(dataFillMethodVo.getTableName());
            task.setDisease(label);
            task.setUserid(UserThreadLocal.get().getUid());
            task.setLeader(UserThreadLocal.get().getUsername());
            taskMapper.insert(task);

        }catch (Exception e){
            e.printStackTrace();
        }



        return res;
    }
    private List<String> getJsonNodeData(JsonNode jsonNode,String key){
        JsonNode old_data = jsonNode.get(key);
        List<String> dataList = new ArrayList<>();
        if (old_data.isArray()) {
            for (JsonNode row : old_data) {
                if (row.isArray()){
                    dataList.add(row.get(0).asText());
                }else{
                    dataList.add(row.asText());
                }
            }
        }else{
            System.out.println("不是list");
        }
        return dataList;
    }
}

IndicatorServiceImpl

这段代码是一个基于Spring框架的服务实现类,用于管理指标类别。让我逐个解释:

1. **包声明和导入语句:**
   这里声明了包名和导入了所需的类,包括FastJSON用于JSON序列化,MyBatis-Plus的`ServiceImpl`类,以及相关实体类和接口。

2. **IndicatorServiceImpl类:**
   这是服务接口`IndicatorService`的实现类,使用了Spring的@Service注解来标识它是一个服务类。

3. **@Autowired注解:**
   用于依赖注入,自动装配`IndicatorMapper`。

4. **getIndicatorCattegory()方法:**
   这个方法用于获取指标类别的树形结构数据。首先从数据库中获取所有的指标类别数据,然后通过过滤和映射操作构建出树形结构的数据,并返回。

5. **getEnName()方法:**
   这个方法用于根据传入的指标类型列表获取对应的英文名称列表。

6. **getCatChildren()方法:**
   这是一个私有方法,用于递归获取指定一级目录下的所有子目录。它接收一个一级目录对象和所有类别数据列表作为参数,然后通过过滤和映射操作找到该一级目录的所有子目录,并递归调用自身以获取子目录的子目录,最后返回子目录列表。

整体来说,这个类主要提供了获取指标类别数据和相关操作的功能,其中getIndicatorCattegory()方法是最主要的,它构建了指标类别的树形结构数据。
package com.cqupt.software_1.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.entity.CategoryEntity;
import com.cqupt.software_1.entity.IndicatorCategory;
import com.cqupt.software_1.mapper.IndicatorMapper;
import com.cqupt.software_1.service.IndicatorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class IndicatorServiceImpl extends ServiceImpl<IndicatorMapper,IndicatorCategory> implements IndicatorService {
    @Autowired
    IndicatorMapper indicatorMapper;
    @Override
    public List<IndicatorCategory> getIndicatorCattegory() {
        List<IndicatorCategory> indicatorCategories = indicatorMapper.selectList(null);
        System.out.println("service========================");
        System.out.println(JSON.toJSONString(indicatorCategories));
        List<IndicatorCategory> treeData = indicatorCategories.stream().filter((categoryEntity) -> {
            return categoryEntity.getParentId()==0;
        }).map((level1Cat) -> {
            level1Cat.setChildren(getCatChildren(level1Cat, indicatorCategories));;
            return level1Cat;
        }).collect(Collectors.toList());
        return treeData;
    }

    @Override
    public List<IndicatorCategory> getEnName(List<String> types) {
        List<IndicatorCategory> enNames = indicatorMapper.getEnNames(types);
        return enNames;
    }

    // 获取1级目录下的所有子结构
    private List<IndicatorCategory> getCatChildren(IndicatorCategory level1Cat, List<IndicatorCategory> categoryEntities) {
        List<IndicatorCategory> children = categoryEntities.stream().filter((categoryEntity) -> {
            return categoryEntity.getParentId()==level1Cat.getId(); // 获取当前分类的所有子分类
        }).map((child) -> {
            // 递归设置子分类的所有子分类
            child.setChildren(getCatChildren(child, categoryEntities));
            return child;
        }).collect(Collectors.toList());
        return children;
    }
}

LogServiceImpl

这段代码是另一个基于Spring框架的服务实现类,用于管理系统日志。让我逐个解释:

1. **LogServiceImpl类:**
   这是服务接口`LogService`的实现类,同样使用了Spring的@Service注解标识。

2. **@Autowired注解:**
   依赖注入,自动装配`LogMapper`、`UserLogMapper`和`UserMapper`。

3. **getAllLogs()方法:**
   这个方法用于获取所有系统日志数据,直接调用了`logMapper`的`getAllLogs()`方法。

4. **insertLog()方法:**
   这个方法用于插入系统日志。根据传入的用户ID、角色和操作,构建一个`UserLog`对象,并设置相应属性。然后通过`DateTimeFormatter`将当前时间格式化为指定格式,设置为操作时间。最后将日志对象插入到数据库中。

整体来说,这个类提供了系统日志的获取和插入功能,其中insertLog()方法用于插入新的系统日志,将用户的操作记录到数据库中。
package com.cqupt.software_1.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cqupt.software_1.entity.LogEntity;
import com.cqupt.software_1.entity.User;
import com.cqupt.software_1.entity.UserLog;
import com.cqupt.software_1.mapper.LogMapper;
import com.cqupt.software_1.mapper.UserLogMapper;
import com.cqupt.software_1.mapper.UserMapper;
import com.cqupt.software_1.service.LogService;
import com.jcraft.jsch.JSch;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

// TODO 公共模块新增类

@Service
public class LogServiceImpl extends ServiceImpl<LogMapper, LogEntity>
        implements LogService {

    @Autowired
    LogMapper logMapper;
    @Autowired
    UserLogMapper userLogMapper;
    @Autowired
    UserMapper userMapper;

    @Override
    public List<LogEntity> getAllLogs() {
        return logMapper.getAllLogs();
    }

    public void insertLog(String uid, Integer role, String operation) {
        User user = userMapper.selectByUid(Integer.parseInt(uid));

        UserLog logEntity = new UserLog();
        logEntity.setUid(Integer.parseInt(uid));
        logEntity.setUsername(user.getUsername());
        logEntity.setOpType(operation);
        // 创建 DateTimeFormatter 对象,定义日期时间的格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 创建 LocalDateTime 对象,存储当前日期和时间
        LocalDateTime now = LocalDateTime.now();
        // 使用 formatter 格式化 LocalDateTime 对象
        String formattedDate = now.format(formatter);
        logEntity.setOpTime(formattedDate);

        System.out.println("要插入的日志数据为:"+JSON.toJSONString(logEntity));

        userLogMapper.insert(logEntity);
    }
}

NodesServiceImpl

这段代码是另一个基于Spring框架的服务实现类,用于管理系统中的节点和关系数据。让我逐个解释:

1. **NodesServiceImpl类:**
   这是服务接口`NodesService`的实现类,同样使用了Spring的@Service注解标识。

2. **@Autowired注解:**
   依赖注入,自动装配了`NodesMapper`。

3. **getAllNodes()方法:**
   这个方法用于获取所有节点数据,直接调用了`nodesMapper`的`getAllNodes()`方法。

4. **getRelationships()方法:**
   这个方法用于获取所有节点之间的关系数据,直接调用了`nodesMapper`的`getRelationships()`方法。

整体来说,这个类提供了对系统中节点和节点之间关系的管理功能,其中getAllNodes()方法用于获取所有节点数据,getRelationships()方法用于获取节点之间的关系数据。
package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.entity.Nodes;
import com.cqupt.software_1.entity.Relationships;
import com.cqupt.software_1.mapper.NodesMapper;
import com.cqupt.software_1.service.NodesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes>
        implements NodesService {
    @Autowired
    NodesMapper nodesMapper;


    @Override
    public List<Nodes> getAllNodes() {
        return nodesMapper.getAllNodes();
    }

    @Override
    public List<Relationships> getRelationships() {
        return nodesMapper.getRelationships();
    }
}

NoticeServiceImpl

这段代码是另一个基于Spring框架的服务实现类,用于管理系统中的通知数据。让我逐个解释:

1. **NoticeServiceImpl类:**
   这是服务接口`NoticeService`的实现类,同样使用了Spring的@Service注解标识。

2. **@Autowired注解:**
   依赖注入,自动装配了`NoticeMapper`。

3. **allNotices()方法:**
   这个方法用于获取所有通知数据,并进行分页处理。通过`PageHelper.startPage()`设置分页参数,然后调用`noticeMapper`的`selectAllNotices()`方法查询数据,最后将结果封装到PageInfo对象中返回。

4. **saveNotification()方法:**
   这个方法用于保存通知数据,接收一个包含通知信息的InsertNoticeVo对象,然后调用`noticeMapper`的`saveNotification()`方法保存通知。

5. **queryNotices()方法:**
   这个方法用于查询通知数据,首先创建一个QueryWrapper对象,设置按照时间字段createTime进行降序排序,然后调用`noticeMapper`的`selectList()`方法查询符合条件的通知数据。

整体来说,这个类提供了对系统中通知数据的管理功能,包括获取所有通知并进行分页处理、保存通知、以及按照条件查询通知数据。
package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.entity.Notification;
import com.cqupt.software_1.entity.User;
import com.cqupt.software_1.mapper.NoticeMapper;
import com.cqupt.software_1.mapper.UserMapper;
import com.cqupt.software_1.service.NoticeService;
import com.cqupt.software_1.service.UserService;
import com.cqupt.software_1.vo.InsertNoticeVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


@Service
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notification>
        implements NoticeService {

    @Autowired
    private NoticeMapper noticeMapper;


    @Override
    public PageInfo<Notification> allNotices(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        // 返回查询结果列表
        List<Notification> notifications =  noticeMapper.selectAllNotices();
        // 使用 PageInfo 包装查询结果,并返回
        return new PageInfo<>(notifications);
    }

    @Override
    public void saveNotification(InsertNoticeVo notification) {
        noticeMapper.saveNotification(notification);
    }

    @Override
    public List<Notification> queryNotices() {


        // 创建QueryWrapper对象
        QueryWrapper queryWrapper = new QueryWrapper<>();

        // 设置按照时间字段createTime进行降序排序
        queryWrapper.orderByDesc("update_time");

        List<Notification> notifications = noticeMapper.selectList(queryWrapper);
        return notifications;
    }
}

PageServiceImpl

这段代码是一个用于处理通用数据库表操作的服务实现类。让我逐个解释:

1. **PageServiceImpl类:**
   这是服务接口`PageService`的实现类,使用了Spring的@Service注解标识。

2. **@Autowired注解:**
   依赖注入,自动装配了`PageMapper`。

3. **getInfoByTableName()方法:**
   这个方法根据传入的表名参数查询数据库中该表的所有信息,并返回一个包含查询结果的List<Map<String,Object>>对象。

4. **getInfoBySelectedFiled()方法:**
   这个方法根据传入的表名和字段参数查询数据库中指定字段的信息,返回一个包含查询结果的List<Map<String,Object>>对象。

整体来说,这个类提供了对系统中通用数据库表操作的功能,包括根据表名获取所有信息以及根据字段查询信息。
package com.cqupt.software_1.service.impl;

import com.cqupt.software_1.mapper.PageMapper;
import com.cqupt.software_1.service.PageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
public class PageServiceImpl  implements PageService  {

    @Autowired
    private PageMapper pageMapper;

    @Override
    public List<Map<String, Object>> getInfoByTableName(String tableName) {

        List<Map<String,Object>> res = pageMapper.getInfoByTableName(tableName);

        return res;
    }

    @Override
    public List<Map<String, Object>> getInfoBySelectedFiled(String tableName, String[] params) {

        List<Map<String,Object>> res = pageMapper.getInfoBySelectedFiled(tableName,params);

        return res;
    }
}

StatisticaldDataImpl

这段代码是用于统计数据的服务实现类。让我逐个解释:

1. **StatisticaldDataImpl类:**
   这是服务接口`StatisticaldService`的实现类,同样使用了Spring的@Service注解标识。

2. **@Autowired注解:**
   依赖注入,自动装配了`StatisticalDataMapper`。

3. **getStatisticaldData()方法:**
   这个方法用于获取统计数据。首先从缓存中获取数据,如果缓存中有数据,则直接返回;否则,从数据库中查询统计数据。如果数据库中有数据,则将数据存入缓存,并返回查询结果,否则返回空Map。

4. **showTableTrend()方法:**
   这个方法用于展示表的趋势。根据输入的日期,查询该日期之前的所有表数量,并返回结果。

5. **calculatorMissRate4Table()方法:**
   这个方法用于计算每个表的缺失总数。首先获取表的总记录数,然后获取表的所有字段名,遍历所有字段,统计为null的缺失总数,并返回结果。

整体来说,这个类提供了统计数据和展示表趋势的功能,以及计算每个表的缺失总数。
package com.cqupt.software_1.service.impl;

import com.cqupt.software_1.entity.StaticData;
import com.cqupt.software_1.mapper.StatisticalDataMapper;
import com.cqupt.software_1.service.StatisticaldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.datatransfer.FlavorEvent;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class StatisticaldDataImpl implements StatisticaldService {


    @Autowired
    private StatisticalDataMapper statisticaldDataMapper;

    @Override
    public Map<String,Object> getStatisticaldData() {
        // 从缓存中获取数据
        List<StaticData> staticData = statisticaldDataMapper.getStaticData();
        if(staticData!=null && staticData.size()>0){
            HashMap<String, Object> resMap = new HashMap<>();
            resMap.put("数据总量" , staticData.get(0).getAllCount());
            resMap.put("指标总量" , staticData.get(0).getAllIndex());
            resMap.put("总体缺失率", staticData.get(0).getAllMissRate());
            resMap.put("总体有效率", staticData.get(0).getAllValidRate());
            return resMap;
        }
        // 查询到数据库的所有的表名
        List<String> tableNames = statisticaldDataMapper.getAllTableNameOfDataBase();

        Map<String ,Object> resMap = new HashMap<>();

        // 总的行数
        Long rowCount = 0L;
        // 总的列数
        Long columnCount = 0L;
        // 总体缺失总数
        int missCount = 0;

        for (String tableName : tableNames) {

            Long row = statisticaldDataMapper.getCount(tableName); // 表有多少行

            Long column = statisticaldDataMapper.getColumn(tableName); // 表有多少列
            // 计算每个表的缺失总数
            int missNum = calculatorMissRate4Table(tableName); // 表的缺失数

            missCount += missNum;
            rowCount += row;
            columnCount +=  column;
        }
        // 总体缺失 / 总体数据
        double missRateTotal = (double) missCount/(rowCount*columnCount)*100;
        // 格式化两位小数
        DecimalFormat decimalFormat = new DecimalFormat("0.00");

        System.out.println(decimalFormat.format(missRateTotal));
        resMap.put("数据总量" , rowCount);
        resMap.put("指标总量" , columnCount);
        resMap.put("总体缺失率", decimalFormat.format(missRateTotal));
        resMap.put("总体有效率", decimalFormat.format(1 - missRateTotal));
        // 保存到缓存
        StaticData cacheData = new StaticData(rowCount,columnCount,Float.parseFloat(decimalFormat.format(missRateTotal)),Float.parseFloat(decimalFormat.format(1 - missRateTotal)));

        // 将数据保存到缓存中
        statisticaldDataMapper.saveCache(cacheData);
        return resMap;
    }

    @Override
    public int showTableTrend(LocalDate minusDays) {

        // 根据当前日期查询在今天和以前的所有表数量

        int num = statisticaldDataMapper.countTableBeforeDate(minusDays.toString());

        return num;
    }

    /**
     *
     *  根据表名计算每个表的 缺失总数
     * @param tableName
     * @return
     */
    private int calculatorMissRate4Table(String tableName) {

        // 1. 获取表的总记录数


        Long row = statisticaldDataMapper.getCount(tableName);

        // 2. 根据表名获取所有的字段名字

        List<String> filedNames = statisticaldDataMapper.getColumnsByTableName(tableName);

        // 3. 遍历所有的字段,统计为null 的缺失总数
        int missCount = 0;
        for (String filedName : filedNames) {
            Long missNum = statisticaldDataMapper.getColumnMissCount(tableName, filedName);
            missCount += missNum;
        }


        return missCount;

    }
}

TableDataServiceImpl

这段代码是一个Java类,实现了一个服务接口`TableDataService`,包含了一些数据表操作的方法。让我逐个解释:

1. **TableDataServiceImpl类声明**:声明了一个类`TableDataServiceImpl`,实现了`TableDataService`接口。

2. **私有变量**:
   - `private volatile boolean hasError = false;`:一个私有的`boolean`类型变量,用于标记是否有错误。

3. **依赖注入**:
   - `@Autowired IndicatorManagementMapper indicatorManagementMapper;`:指标管理的Mapper对象。
   - `@Autowired ThreadPoolTaskExecutor taskExecutor;`:线程池的TaskExecutor对象。
   - `@Autowired DataSourceTransactionManager transactionManager;`:数据源事务管理器对象。
   - `@Autowired TableDataMapper tableDataMapper;`:表数据的Mapper对象。
   - `@Autowired TableDescribeMapper tableDescribeMapper;`:表描述的Mapper对象。
   - `@Autowired CategoryMapper categoryMapper;`:分类的Mapper对象。
   - `@Autowired UserLogService userLogService;`:用户日志的服务对象。
   - `@Autowired TaskService taskService;`:任务的服务对象。
   - `@Autowired FieldManagementService fieldManagementService;`:字段管理的服务对象。
   - `@Autowired StatisticalDataMapper statisticalDataMapper;`:统计数据的Mapper对象。
   - `@Autowired IndicatorManagementService indicatorManagementService;`:指标管理的服务对象。
   - `@Autowired FilterDataColMapper filterDataColMapper;`:过滤数据列的Mapper对象。
   - `@Autowired FilterDataInfoMapper filterDataInfoMapper;`:过滤数据信息的Mapper对象。

4. **getTableData方法**:获取表数据的方法。
   - 参数:`TableId`表ID,`tableName`表名称。
   - 返回值:`List<LinkedHashMap<String, Object>>`,包含表中数据的列表。

5. **uploadFile方法**:上传文件的方法。
   - 参数:`file`上传的文件,`tableName`表名称,`type`类型,`user`用户,`userId`用户ID,`parentId`父ID,`parentType`父类型,`status`状态。
   - 返回值:`List<String>`,包含特征列表。

在`uploadFile`方法中,代码执行了以下操作:
- 创建`TableDescribeEntity`对象,设置相关属性。
- 创建`CategoryEntity`对象,设置相关属性。
- 插入`CategoryEntity`到数据库。
- 设置`TableDescribeEntity`的表ID并插入到数据库。
- 调用`storeTableData`方法,存储表数据。
- 保存用户日志。
- 删除统计数据的缓存。


这段代码是一个Java方法,名为`createTable`,它是一个数据库事务,用于创建表格并插入数据。让我们逐步分析它:
1. **`createTable`方法**:这是主要的方法,用于创建表和插入数据。它接受表名(`tableName`),字段列表(`characterList`),创建用户(`createUser`)和目录实体(`nodeData`)作为参数。
2. **`@Transactional(propagation = Propagation.REQUIRED)`**:这是一个注解,表明这个方法应该在一个事务中执行。如果没有现有的事务,它会创建一个新的事务。`Propagation.REQUIRED`意味着如果当前没有活动的事务,则新的事务将被开启。
3. **`getFilterDataByConditions`方法**:这个方法根据条件过滤数据,并返回一个包含筛选后数据的列表。
4. **`getBelongType`方法**:这个方法根据目录实体(`nodeData`)找到它所属的类型。
5. **`tableDataMapper.getAllTableData`方法**:这个方法根据给定的表名获取所有表数据。
6. **创建表头信息**:根据字段管理表创建新表,存储筛选后的数据。字段管理表是一个存储字段信息的表。
7. **`tableDataMapper.createTableByField`方法**:根据字段信息创建新表。
8. **数据保存**:批量将数据插入新表中。如果数据量过大,则进行分批插入以防止SQL参数溢出。
9. **保存目录信息**:创建新的目录节点信息,并将其保存到数据库中。
10. **保存表描述信息**:创建新表的描述信息,并将其保存到数据库中。
11. **保存筛选数据信息**:保存筛选数据的相关信息,包括用户ID、用户名、筛选时间等。
12. **`statisticalDataMapper.deleteCache`方法**:清除数据统计的缓存,可能是为了确保最新的数据统计信息。
这段代码的主要功能是在数据库中创建新表,并将筛选后的数据插入其中,同时记录相关的元数据和操作日志。

这段代码是一个Java类,可能是一个服务类或控制器类。让我来解释每个函数和接口的作用:
1. `getFilterDataByConditions`: 这是一个方法,根据给定的条件筛选数据。它首先从数据库中获取所有目录信息,然后找到所有符合条件的宽表节点,接着根据传入的条件列表筛选数据,并最终返回筛选结果。该方法使用了事务管理。
2. `storeTableData`: 这是另一个方法,用于将CSV文件数据存储到数据库表中。它首先解析CSV文件,获取表头信息和数据行,然后根据数据行解析字段类型,并创建表信息。最后,将数据批量插入到数据库表中。
3. `getFeatureDataType`: 这是一个私有方法,用于根据CSV文件数据获取字段类型。它遍历CSV数据的每一行和每一列,尝试将数据转换成数字类型,如果转换成功,则将字段类型设置为float8,否则设置为VARCHAR(255)。
4. `@Transactional`: 这是一个注解,用于指示该方法应该在事务中运行。
5. `@Override`: 这也是一个注解,表明该方法是对父类或接口的方法进行重写。
6. `MultipartFile`: 这是Spring框架中的一个接口,用于处理上传的文件数据。
7. `CategoryEntity`: 这可能是一个实体类,用于表示某个类别或节点的信息。
8. `UserLog`: 这可能是另一个实体类,用于记录用户操作日志。
总体而言,这段代码涉及到数据筛选、CSV文件处理和数据库操作,主要用于处理数据并记录用户操作。


这段代码是一个Java方法,其主要功能是从数据库中导出数据并填充到CSV格式的列表中。整个过程涉及获取数据、填充缺失值、生成CSV格式的数据列表,并记录用户操作日志。下面是对每个步骤和接口的详细介绍:
1. **方法定义和参数解释**:
   - `exportFile` 是方法的名称,属于某个类的重写方法(由 `@Override` 标注)。
   - 接受一个 `ExportFilledDataTableVo` 类型的参数 `dataFillMethodVo`,这个参数封装了导出数据时需要的各种设置和方法。
2. **获取填充数据**:
   - `List<Map<String, IsFillVo>> fillData`:这行代码调用 `indicatorManagementService.fillData` 方法,传入 `dataFillMethodVo.getDataFillMethodVo()`。此方法从指标管理服务获取填充数据,每个Map代表一行数据,只包含已填充的列。
3. **获取表的所有数据**:
   - `List<LinkedHashMap<String, Object>> tableData`:通过 `tableDataMapper.getAllTableData` 方法获取特定表的所有数据,传入表名 `dataFillMethodVo.getDataFillMethodVo().getTableName()`。使用 `LinkedHashMap` 保证数据的插入顺序与字段的定义顺序一致。
4. **获取表头信息**:
   - `List<FieldManagementEntity> fields`:通过 `fieldManagementService.list()` 获取当前数据库表的字段管理信息,这通常包括字段名等元数据。
5. **数据整合**:
   - 使用两层循环对表数据进行遍历和填充。外层循环遍历每行数据,内层循环遍历每个需要填充的字段。
   - 检查每行数据中是否存在需要填充的字段,如果不存在,则从填充数据 `fillData` 中获取相应的填充值。
6. **补全每行数据**:
   - 对每行数据的 `LinkedHashMap` 进行遍历,确保所有字段都存在。如果某个字段在行数据中不存在,则将其值设为空字符串。
7. **生成CSV格式的数据列表**:
   - 首先构建表头,将所有字段名称用逗号分隔。
   - 接着,遍历每行数据,将数据按字段顺序转换为CSV格式的字符串。
8. **记录用户操作日志**:
   - 创建 `UserLog` 对象并通过 `userLogService.save(userLog)` 方法保存。这里记录了操作用户的UID、用户名、操作时间和描述。
9. **返回数据**:
   - 将包含表头和所有行数据的CSV格式列表 `fileData` 返回。
此方法的设计考虑到了数据的完整性和用户操作的可追踪性,同时通过适当的数据结构保证了数据的有序性和完整性。整个过程中涉及了多个服务和组件的交互,反映了典型的企业级应用架构。

这段代码是一个Java方法,名为`featureDescAnalyze`,用于执行对特征进行描述性分析的操作。首先,它接受三个参数:`featureName`表示特征名称,`tableName`表示表名,`taskInfo`表示任务信息。
1. 首先判断特征是否在字段管理表中,如果不在,则从数据库中查询特征的数据分布情况。
2. 如果特征是离散的,它会获取该特征的不同取值,并计算每个取值的频率和占比。
3. 如果特征是非离散的,它会获取总条数、中位数、众数、均值、最小值、最大值等统计信息,并根据最大最小值划分数据段,计算每个数据段的数据量。
4. 无论特征是离散还是非离散,最后都会记录用户的操作日志。
这段代码中的函数和接口包括:
- `featureDescAnalyze(String featureName, String tableName, CreateTaskEntity taskInfo)`:主函数,接收特征名称、表名和任务信息,执行描述性分析操作。
- `getOne(QueryWrapper<FieldManagementEntity> queryWrapper)`:从字段管理表中获取特征信息。
- `indicatorManagementMapper.getFiledCount(featureName, tableName)`:从数据库中获取特征的统计信息。
- `tableDataMapper.getAllCount(tableName)`:从数据库中获取表的总记录数。
- `tableDataMapper.getDistinctValue(tableName, featureName)`:从数据库中获取特征的不同取值。
- `tableDataMapper.getCount(featureValue, tableName, featureName)`:从数据库中获取特定取值的记录数。
- `userLogService.save(userLog)`:保存用户操作日志。
这段代码是一个任务管理系统中的创建任务的功能实现代码。首先,通过调用`taskService.list(null)`获取任务列表,然后通过流式处理筛选出是否存在相同的任务。如果不存在相同的任务,则创建新任务。
在创建任务之前,设置了任务的各种属性,比如创建时间、数据集名称、特征名称等。其中,如果任务负责人为空,则从`UserThreadLocal`中获取当前用户的用户名作为任务负责人。如果任务名称为空,则将其设置为当前用户的用户名加上当前日期。
接下来,根据表名获取关联疾病的父节点名称,并将其设置为任务的疾病属性。然后将任务的结果、备注等信息设置好,最后调用`taskService.save(task)`保存任务信息。
整体而言,该代码段通过查询数据库和执行统计计算来对特征进行描述性分析,并记录用户操作日志。
整体来说,这段代码实现了根据一定条件判断任务是否存在,如果不存在则创建新任务,并设置任务的各种属性信息。


这段代码是一个Java方法,名为`featureDescAnalyze`,用于执行对某个特征进行描述性分析的操作。首先,根据输入的特征名称和表名,以及任务信息,进行一系列判断和处理。
1. `FeatureDescAnaVo featureDescAnalyze(String featureName, String tableName, CreateTaskEntity taskInfo)`方法是一个重写的方法,它接受特征名称、表名和任务信息作为参数,并返回一个特征描述分析的结果对象`FeatureDescAnaVo`。
2. 在方法内部,首先判断特征是否被字段管理表所管理,若不被管理,则通过数据库查询判断特征是离散还是非离散。
3. 如果特征是非离散的,就获取总条数、中位数、众数、均值、最小值和最大值等描述性统计信息,并调用远程方法进行处理。处理结果包括数据分段柱状图数据。
4. 如果特征是离散的,就获取不同取值的频率,并计算每个取值的数据总条数以及占比等信息。
5. 最后,记录用户操作日志,并返回特征描述分析的结果对象。
整个方法逻辑比较清晰,通过一系列判断和处理,分别处理离散和非离散的特征,并最终返回相应的描述性分析结果。

这段代码是一个Java类中的两个方法:`singleFactorAnalyze` 和 `consistencyAnalyze`。这些方法似乎是用于处理数据分析任务的。
`singleFactorAnalyze` 方法接收三个参数:tableName 表示数据表的名称,colNames 是一个包含列名的列表,taskInfo 则是一个包含任务相关信息的实体对象。该方法的主要功能是执行单因素分析任务,并返回结果。
首先,它创建一个 `RunPyEntity` 对象,并使用 `HTTPUtils.postRequest` 方法发送 POST 请求执行单因素分析任务。然后,它从返回的 JSON 结果中提取数据并将其转换为 `SingleAnalyzeVo` 对象。
接着,它检查是否存在重复的任务。如果不存在重复任务,则创建一个新的任务对象,并将相关信息设置到任务对象中,包括数据表名称、特征列名、任务负责人、备注等。最后,它将任务对象保存到数据库中,并返回单因素分析结果。
`consistencyAnalyze` 方法与 `singleFactorAnalyze` 类似,也接收三个参数,执行一致性验证任务,并返回结果。
首先,它创建一个 `RunPyEntity` 对象,并使用 `HTTPUtils.postRequest` 方法发送 POST 请求执行一致性验证任务。然后,它从返回的 JSON 结果中提取数据并将其转换为 `ConsistencyAnalyzeVo` 对象。
接着,它检查是否存在重复的任务。如果不存在重复任务,则创建一个新的任务对象,并将相关信息设置到任务对象中,包括数据表名称、特征列名、任务负责人、备注等。最后,它将任务对象保存到数据库中,并返回一致性验证结果。
这两个方法都包含了一些重复的代码,例如任务创建和重复性检查。可能考虑将这些共用的部分提取出来,以提高代码的可维护性和可读性。


这段代码是一个Java方法,名为`getTableDataByFields`,它接收两个参数:`tableName`和`featureList`。`tableName`是一个字符串,代表要查询的数据表的名称,`featureList`是一个字符串列表,包含要查询的字段名。
在方法内部,它调用了`tableDataMapper`对象的`getTableDataByFields`方法,传入表名和字段列表作为参数。这个`tableDataMapper`对象可能是一个数据访问对象(Data Access Object),用来执行数据库操作。
最后,方法返回一个`List<Map<String, Object>>`类型的对象,其中每个元素是一个Map,代表查询结果的一行数据,Map的键是字段名,值是对应字段的值。




这段代码包含了几个方法,它们用于处理数据和生成分析结果。下面是每个方法的详细介绍:
1. `getDataCount` 方法:
   - 这个方法接收一个`CategoryEntity`列表作为参数。
   - 它使用`tableDataMapper`对象的`getCountByName`方法来获取每个`CategoryEntity`中的标签对应的记录数。
   - 然后,它将这些记录数累加起来,并返回总记录数。
2. `getConsistencyAnalyzeFromJsonNode` 方法:
   - 这个方法接收一个`JsonNode`对象作为参数,该对象包含了ICC分析的结果。
   - 它从`JsonNode`中提取`ICC1`和`ICC2`部分,并创建相应的`ICCVo`对象来存储这些数据。
   - 最后,它将两个`ICCVo`对象添加到一个`ArrayList`中,并打印出来。
3. `getSingleAnalyzeDataFromJsonNode` 方法:
   - 这个方法同样接收一个`JsonNode`对象作为参数,该对象包含了单样本分析的结果。
   - 它创建一个`SingleAnalyzeVo`对象,并从`JsonNode`中提取各种统计数据,如Wilcoxon W统计量、t统计量等,并将它们设置为`SingleAnalyzeVo`对象的属性。
   - 它还从`JsonNode`中提取类别的统计信息,并创建`DiscreteVo`对象来存储这些信息。
   - 最后,它创建两个`ArrayList`来存储两组数据,并使用`getBinData`方法来生成非离散数据分布的区间。
4. `getBinData` 方法:
   - 这个方法接收一个`List<Double>`和一个`int`作为参数,用于指定数据和分箱的数量。
   - 它首先对数据进行排序,然后找到最大值和最小值,并计算分箱的间隔。
   - 然后,它遍历每个分箱,计算每个分箱中的数据点数量,并将结果存储在一个`LinkedHashMap<String, Integer>`中,其中键是分箱的描述,值是数据点数量。
1. `private boolean writeDataToCSV(List<String> data, String filePath)`: 这个方法用于将数据写入 CSV 文件。它接收一个包含字符串数据的列表和一个文件路径作为参数。在方法中,它首先创建一个 CSVWriter 对象来写入数据到文件。然后,它遍历传入的数据列表,将每行数据按逗号分割并写入文件。如果写入成功,则返回 true;如果发生 IOException,则输出错误消息并返回 false。
2. `private NotDiscrete getDataFromPy(JsonNode jsonNode)`: 这个方法从给定的 JsonNode 中获取数据并返回一个 NotDiscrete 对象。它首先从 JSON 中提取平均值、最大值、最小值、众数和中位数等数据,并将它们转换为浮点数并保留两位小数。然后,将这些数据设置到 NotDiscrete 对象中并返回。
3. `private LinkedHashMap<String,Integer> getBinData(Float max, Float min, String tableName, String featureName)`: 这个方法用于计算给定最大值和最小值之间的数据的分布情况。它将数据按照一定的区间划分,并计算每个区间内的数据量。具体地,它将数据分成六个区间,计算每个区间的起始值和结束值,并获取每个区间的数据量。最后,将起始值和结束值作为键,数据量作为值,存储在一个 LinkedHashMap 中,并返回该映射。
4. `private void getLeafNode(CategoryEntity nodeData,List<CategoryEntity> leafNodes)`: 这个方法用于获取给定节点的所有叶子节点。如果给定节点有子节点,它将递归地遍历所有子节点,直到找到叶子节点为止,并将这些叶子节点添加到传入的列表中。
5. `private CategoryEntity getBelongType(CategoryEntity nodeData, ArrayList<CategoryEntity> leafNodes)`: 这个方法用于确定给定节点所属的类型。它首先调用 `getLeafNode` 方法获取给定节点的所有叶子节点。然后,它遍历这些叶子节点,找到包含属性 `isWideTable` 值为 1 的节点,表示该节点属于宽表类型,然后返回该节点。
这些方法共同构成了一个处理和分析数据的工具集,它们可能用于生成统计报告或进行数据分析。


这段代码是一个 Java 类的部分实现,包含了一些关于表格数据管理的功能。让我来逐一解释每个函数和接口的作用:
1. `getCountByTableName(String tableName)`:这个方法用于获取指定表名的数据行数。
2. `getTableFields(String tableName)`:该方法用于获取指定表名的字段列表。
3. `getDataLikeMatch(String tableName, List<String> tableFields, String value)`:这个方法用于根据指定的表名、字段列表和值来获取类似匹配的数据。
4. `createFilterBtnTable(String tableName, List<CreateTableFeatureVo> characterList, String createUser, String status, String uid, String username, String IsFilter, String IsUpload, String uid_list,String nodeid)`:这个方法用于创建筛选按钮表格。它接收表名、特征列表、创建用户、状态、用户ID、用户名、是否筛选、是否上传、用户ID列表和节点ID作为参数。在函数内部,根据传入的参数,执行了以下步骤:
   - 查询节点数据。
   - 根据疾病特征列表、用户ID和节点ID获取筛选后的数据。
   - 获取字段管理信息。
   - 根据字段管理信息创建表头。
   - 将筛选后的数据插入到新创建的表中。
   - 保存目录信息。
   - 保存表描述信息。
在这个函数中,注释提供了更详细的步骤说明,包括筛选数据、创建表头信息、保存创建表的数据信息、保存目录信息等。整体来说,这个函数实现了根据特定条件创建筛选后的数据表,并将相关信息保存到数据库中。


这段代码是一个 Java 类中的两个方法的实现。第一个方法是 `getFilterDataByConditionsByDieaseId`,第二个方法是 `getInfoByTableName`。我来逐一介绍它们:
### `getFilterDataByConditionsByDieaseId` 方法:
这个方法是一个公共方法,返回一个 `List`,其中包含了满足条件的数据。它接受四个参数:一个 `List<CreateTableFeatureVo>` 类型的对象列表、一个 `String` 类型的用户 ID (`uid`)、一个 `String` 类型的用户名 (`username`)、一个 `String` 类型的节点 ID (`nodeid`)。
在方法的开始处,会输出一些调试信息到控制台,然后通过调用 `categoryMapper.selectList(null)` 查询数据库中所有的目录信息,并通过 `categoryMapper.selectById(nodeid)` 查询指定节点的信息。接着,它会找到所有的宽表节点并保存在 `allWideTableNodes` 列表中。
然后,通过遍历给定的 `characterList`,将其中的数字形式的逻辑操作符(0 表示 AND,1 表示 OR,2 表示 AND NOT)转换为字符串形式。接着,处理 `characterList` 中的 `varchar` 类型的数据,给值添加单引号。
然后,创建一个 `otherWideTableData` 的列表,保存调用 `tableDataMapper.getFilterData("merge",characterList)` 方法的结果。然后,将其中的数据合并到 `res` 列表中。
接下来,会创建一个 `FilterDataInfo` 对象,并将其插入数据库中。然后,遍历 `characterList`,为每个特征创建一个 `FilterDataCol` 对象,并将其插入数据库中。
最后,返回 `res` 列表,其中包含了满足条件的数据。
### `getInfoByTableName` 方法:
这个方法是另一个公共方法,返回一个 `List`,其中包含了指定表的信息。它接受一个 `String` 类型的表名参数。
该方法调用了 `tableDataMapper.getInfoByTableName(tableName)` 方法,并返回其结果,该方法用于从数据库中获取指定表的信息。
这两个方法都涉及到数据库操作,主要是查询和插入操作,并且涉及到对传入参数的处理和转换。
package com.cqupt.software_1.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cqupt.software_1.common.RunPyEntity;
import com.cqupt.software_1.common.UserThreadLocal;
import com.cqupt.software_1.entity.*;
import com.cqupt.software_1.mapper.*;
import com.cqupt.software_1.service.*;
import com.cqupt.software_1.utils.HTTPUtils;
import com.cqupt.software_1.vo.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URISyntaxException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

// TODO 公共模块

@Service
public class TableDataServiceImpl implements TableDataService {
    private volatile boolean hasError = false;
    @Autowired
    IndicatorManagementMapper indicatorManagementMapper;

    @Autowired
    ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    DataSourceTransactionManager transactionManager;

    @Autowired
    TableDataMapper tableDataMapper;

    @Autowired
    TableDescribeMapper tableDescribeMapper;
    @Autowired
    CategoryMapper categoryMapper;
    @Autowired
    UserLogService userLogService;

    @Autowired
    TaskService taskService;

    @Autowired
    FieldManagementService fieldManagementService;

    @Autowired
    StatisticalDataMapper statisticalDataMapper;

    @Autowired
    IndicatorManagementService indicatorManagementService;

    @Autowired
    FilterDataColMapper filterDataColMapper;
    @Autowired
    FilterDataInfoMapper filterDataInfoMapper;
    @Override
    public List<LinkedHashMap<String, Object>> getTableData(String TableId, String tableName) {
        List<LinkedHashMap<String, Object>> tableData = tableDataMapper.getTableData(tableName);
        return tableData;
    }

    @Transactional(propagation = Propagation.REQUIRED) // 事务控制
    @Override
    public List<String> uploadFile(MultipartFile file, String tableName, String type, String user, int userId, String parentId, String parentType, String status) throws IOException, ParseException {
        // 封住表描述信息
        TableDescribeEntity tableDescribeEntity = new TableDescribeEntity();
        tableDescribeEntity.setClassPath(parentType+"/"+type);
        // 解析系统当前时间
        tableDescribeEntity.setCreateTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        tableDescribeEntity.setCreateUser(user);
        tableDescribeEntity.setTableName(tableName);
        // 封装目录信息
        CategoryEntity categoryEntity = new CategoryEntity();
        categoryEntity.setLabel(tableName);
        CategoryEntity parentCate = categoryMapper.selectById(parentId);
        categoryEntity.setStatus(status);
        categoryEntity.setCatLevel(parentCate.getCatLevel()+1);
        categoryEntity.setIsCommon(parentCate.getIsCommon());
        categoryEntity.setIsLeafs(1);
        categoryEntity.setUid(UserThreadLocal.get().getUid().toString());
        categoryEntity.setPath(parentCate.getPath()+"/"+tableName);
        categoryEntity.setParentId(parentId);
        categoryEntity.setIsDelete(0);


        // 保存数据库
        categoryMapper.insert(categoryEntity);
        tableDescribeEntity.setTableId(categoryEntity.getId());
        tableDescribeMapper.insert(tableDescribeEntity);

        List<String> featureList = storeTableData(file, tableName);

        UserLog userLog = new UserLog(null, UserThreadLocal.get().getUid(),UserThreadLocal.get().getUsername(),new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),"数据文件上传");
        userLogService.save(userLog);

        statisticalDataMapper.deleteCache(); // 清除缓存

        return featureList;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void createTable(String tableName, List<CreateTableFeatureVo> characterList, String createUser, CategoryEntity nodeData) {
        /**
         *          筛选数据
         *              查询当前目录下的宽表所有数据
         *                  1、查询nodeData的所有子节点,找到是宽表的节点信息(表名)
         *              筛选 其他病种符合条件的所有数据
         *                  2、遍历所有目录信息 找到所有的宽表节点,排除上一步找到的宽表节点,使用剩下的宽表节点筛选数据
         *              合并所有数据
         *          创建表头信息
         *              3、根据宽表的字段管理表创建一个新表,存储筛选后的数据
         *          保存创建表的数据信息信息
         *              4、将1、2步骤的数据插入到3创建的表中
         *          保存目录信息
         *              5、创建目录节点信息,并保存数据库
         *
         */
        List<LinkedHashMap<String, Object>> res = getFilterDataByConditions(characterList, nodeData);
        CategoryEntity mustContainNode = getBelongType(nodeData, new ArrayList<CategoryEntity>());
        // 查询考虑疾病的宽表数据
        List<LinkedHashMap<String,Object>> diseaseData;
         if(mustContainNode!=null) {
             diseaseData = tableDataMapper.getAllTableData(mustContainNode.getLabel()); // 传递表名参数
         }else{
             diseaseData = new ArrayList<>();
        }
        // 合并考虑疾病和非考虑疾病的所有数据
        for (LinkedHashMap<String, Object> re : res) {
            diseaseData.add(re);
        }
        // 创建表头信息 获取宽表字段管理信息
        List<FieldManagementEntity> fields = fieldManagementService.list(null);
        HashMap<String, String> fieldMap = new HashMap<>();
        for (FieldManagementEntity field : fields) {
            fieldMap.put(field.getFeatureName(),field.getType());
        }
        // TODO 创建表头信息
        tableDataMapper.createTableByField(tableName,fieldMap);
        // TODO 数据保存 批量插入
        // TODO 保证value值数量与字段个数一致
        for (Map<String, Object> diseaseDatum : diseaseData) {
            for (FieldManagementEntity field : fields) {
                if(diseaseDatum.get(field.getFeatureName())==null)
                {
                    diseaseDatum.put(field.getFeatureName(),null);
                }
            }
        }
        // TODO 分批插入 防止sql参数传入过多导致溢出
        if(diseaseData.size()>200){
            int batch = diseaseData.size()/200;
            for(int i=0; i<batch; i++){
                int start = i*200, end = (i+1)*200;
                tableDataMapper.bachInsertData(diseaseData.subList(start,end),tableName); // diseaseData.subList(start,end) 前闭后开
            }
            tableDataMapper.bachInsertData(diseaseData.subList(batch*200,diseaseData.size()),tableName);
        }else{
            tableDataMapper.bachInsertData(diseaseData,tableName);
        }
        // 目录信息
//        System.out.println("节点参数信息:"+JSON.toJSONString(nodeData));
        CategoryEntity cat = categoryMapper.selectById(nodeData.getId());
        CategoryEntity node = new CategoryEntity();
        node.setIsDelete(0);
        node.setParentId(nodeData.getId());
        node.setPath(cat.getPath()+"/"+tableName);
        node.setIsLeafs(1);
        node.setIsCommon(nodeData.getIsCommon());
        node.setCatLevel(nodeData.getCatLevel()+1);
        node.setIsWideTable(0);
        node.setLabel(tableName);
        node.setStatus(nodeData.getStatus());
        node.setUid(UserThreadLocal.get().getUid().toString());
        node.setUsername(UserThreadLocal.get().getUsername());
        node.setStatus("0");
        node.setIsCommon(0);
        node.setIs_filter("1");
        categoryMapper.insert(node); // 保存目录信息
        // 表描述信息
        TableDescribeEntity tableDescribeEntity = new TableDescribeEntity();
        tableDescribeEntity.setTableName(tableName);
        tableDescribeEntity.setCreateUser(createUser);
        tableDescribeEntity.setCreateTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        tableDescribeEntity.setClassPath(cat.getPath()+"/"+tableName);
        tableDescribeEntity.setTableId(node.getId());
        tableDescribeEntity.setUid(UserThreadLocal.get().getUid());
        tableDescribeEntity.setTableStatus("0"); // 筛选后默认私有

        // 保存表描述信息
        tableDescribeMapper.insert(tableDescribeEntity);
        UserLog userLog = new UserLog(null, UserThreadLocal.get().getUid(),UserThreadLocal.get().getUsername(),new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),"筛选数据建表");
        userLogService.save(userLog);


        // 插入 filter_data_info 表信息
        FilterDataInfo filterDataInfo = new FilterDataInfo();
        filterDataInfo.setUid(UserThreadLocal.get().getUid());
        filterDataInfo.setCreateUser(UserThreadLocal.get().getUsername());
        filterDataInfo.setUsername(UserThreadLocal.get().getUsername());
        filterDataInfo.setCateId(nodeData.getId());
        filterDataInfo.setParentId(nodeData.getParentId());
        filterDataInfo.setFilterTime(new Timestamp(System.currentTimeMillis())); // 时间
        filterDataInfoMapper.insert(filterDataInfo);


        for (CreateTableFeatureVo createTableFeatureVo : characterList) {
            FilterDataCol filterDataCol = new FilterDataCol();
            BeanUtils.copyProperties(createTableFeatureVo,filterDataCol);
            filterDataCol.setFilterDataInfoId(filterDataInfo.getId());
            FieldManagementEntity fieldManagementEntity = fieldManagementService.getOne(new QueryWrapper<FieldManagementEntity>().eq("feature_name", createTableFeatureVo.getFeatureName()));
            filterDataCol.setRange(fieldManagementEntity.getRange());
            filterDataColMapper.insert(filterDataCol);
        }

        statisticalDataMapper.deleteCache(); // 清除数据统计的缓存

    }

    // 根据条件筛选数据
    @Transactional
    @Override
    public List<LinkedHashMap<String, Object>> getFilterDataByConditions(List<CreateTableFeatureVo> characterList,CategoryEntity nodeData) {
        List<CategoryEntity> categoryEntities = categoryMapper.selectList(null); // 查询所有的目录信息
        // 找到所有的宽表节点
        List<CategoryEntity> allWideTableNodes = categoryEntities.stream().filter(categoryEntity -> {
            return categoryEntity.getIsDelete()==0 && categoryEntity.getIsLeafs()==1 && categoryEntity.getIsWideTable()!=null && categoryEntity.getIsWideTable() == 1;
        }).collect(Collectors.toList());
        // 遍历当前节点的所有叶子节点,找到这个宽表节点
        ArrayList<CategoryEntity> leafNodes = new ArrayList<>();
        getLeafNode(nodeData, leafNodes);
        /** 找到所有的非考虑疾病的宽表节点 **/
        List<CategoryEntity> otherWideTable = null;
        if(leafNodes!=null && leafNodes.size()>0){
            for (CategoryEntity leafNode : leafNodes) {
                if(leafNode.getIsWideTable()!=null && leafNode.getIsWideTable()==1) {
                    otherWideTable = allWideTableNodes.stream().filter(categoryEntity -> { // 所有的非考虑疾病的宽表节点
                        return !categoryEntity.getLabel().equals(leafNode.getLabel());
                    }).collect(Collectors.toList());
                }
            }
        }else{
            otherWideTable = allWideTableNodes;
        }
        if(otherWideTable==null) otherWideTable = allWideTableNodes;
        // 筛选所有非考虑疾病的宽表数据
        /** select * from ${tableName} where ${feature} ${computeOpt} ${value} ${connector} ... **/
        // 前端传过来的 AND OR NOT 是数字形式0,1,2,需要变成字符串拼接sql
        for (CreateTableFeatureVo createTableFeatureVo : characterList) {
            if(createTableFeatureVo.getOpt()==null) createTableFeatureVo.setOptString("");
            else if(createTableFeatureVo.getOpt()==0) createTableFeatureVo.setOptString("AND");
            else if(createTableFeatureVo.getOpt()==1) createTableFeatureVo.setOptString("OR");
            else createTableFeatureVo.setOptString("AND NOT");
        }
        // 处理varchar类型的数据
        for (CreateTableFeatureVo createTableFeatureVo : characterList) {
            if(createTableFeatureVo.getType()==null || createTableFeatureVo.getType().equals("character varying")){
                createTableFeatureVo.setValue("'"+createTableFeatureVo.getValue()+"'");
            }
        }
        // 依次查询每一个表中符合条件的数据
        List<List<LinkedHashMap<String, Object>>> otherWideTableData = new ArrayList<>();
        for (CategoryEntity wideTable : otherWideTable) {
            otherWideTableData.add(tableDataMapper.getFilterData(wideTable.getLabel(),characterList)); // TODO 筛选SQl xml
        }
        /** 数据合并List<List<Map<String, Object>>> otherWideTableData(多张表) 合并到 List<Map<String,Object>> diseaseData(一张表) **/
        ArrayList<LinkedHashMap<String, Object>> res = new ArrayList<>();
        for (List<LinkedHashMap<String, Object>> otherWideTableDatum : otherWideTableData) {
            for (LinkedHashMap<String, Object> rowData : otherWideTableDatum) {
                res.add(rowData);
            }
        }

//        // 插入 filter_data_info 表信息
//        FilterDataInfo filterDataInfo = new FilterDataInfo();
//        filterDataInfo.setUid(UserThreadLocal.get().getUid());
//        filterDataInfo.setCreateUser(UserThreadLocal.get().getUsername());
//        filterDataInfo.setUsername(UserThreadLocal.get().getUsername());
//        filterDataInfo.setCateId(nodeData.getId());
//        filterDataInfo.setParentId(nodeData.getParentId());
//        filterDataInfo.setFilterTime(new Timestamp(System.currentTimeMillis())); // 时间
//        filterDataInfoMapper.insert(filterDataInfo);
//
//
//        ArrayList<FilterDataCol> filterDataCols = new ArrayList<>();
//        for (CreateTableFeatureVo createTableFeatureVo : characterList) {
//            FilterDataCol filterDataCol = new FilterDataCol();
//            BeanUtils.copyProperties(createTableFeatureVo,filterDataCol);
//            filterDataCol.setFilterDataInfoId(filterDataInfo.getId());
//            FieldManagementEntity fieldManagementEntity = fieldManagementService.getOne(new QueryWrapper<FieldManagementEntity>().eq("feature_name", createTableFeatureVo.getFeatureName()));
//            filterDataCol.setRange(fieldManagementEntity.getRange());
//            filterDataColMapper.insert(filterDataCol);
//        }


        UserLog userLog = new UserLog(null, UserThreadLocal.get().getUid(),UserThreadLocal.get().getUsername(),new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),"筛选数据");
        userLogService.save(userLog);
        return res;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public List<String> storeTableData(MultipartFile file, String tableName) throws IOException {
        ArrayList<String> featureList = null;
        if (!file.isEmpty()) {
            // 使用 OpenCSV 解析 CSV 文件
            Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream(),"UTF-8"));
            CSVReader csvReader = new CSVReader(reader);
            List<String[]> csvData = csvReader.readAll();
            csvReader.close();
            // 获取表头信息
            String[] headers = csvData.get(0);
            featureList = new ArrayList<String>(Arrays.asList(headers));
            // 删除表头行,剩余的即为数据行
            csvData.remove(0);
            // 解析字段类型
            String[] featureDataType = getFeatureDataType(csvData);
            // 创建表信息
            tableDataMapper.createTable2(headers,featureDataType, tableName);

//            // 批量
            // TODO 分批插入 防止sql参数传入过多导致溢出
            if(csvData.size()>10000){
                int batch = csvData.size()/10000;
                for(int i=0; i<batch; i++){
                    int start = i*10000, end = (i+1)*10000;
                    tableDataMapper.batchInsertCsv(csvData.subList(start,end),tableName); // diseaseData.subList(start,end) 前闭后开
                }
                tableDataMapper.batchInsertCsv(csvData.subList(batch*10000,csvData.size()),tableName);
            }else{
                tableDataMapper.batchInsertCsv(csvData,tableName);
            }
            // TODO 改进
//            int count = csvData.size();
//            int pageSize = 5000;
//            int threadNum = count % pageSize == 0 ?  count / pageSize:  count / pageSize + 1;
//            CountDownLatch downLatch = new CountDownLatch(threadNum);
//            long start = System.currentTimeMillis();
//
//            for (int i = 0; i < threadNum; i++) {
//                //开始序号
//                int startIndex = i * pageSize;
//                //结束序号
//                int endIndex = Math.min(count, (i+1)*pageSize);
//                //分割list
//                List<String[]> epochData = csvData.subList(startIndex, endIndex);
//
//                taskExecutor.execute(() -> {
//                    try {
//                        tableDataMapper.batchInsertCsv(epochData,tableName);
//
//                    }catch (Exception e){
//                        e.printStackTrace();
//                    }finally {
//                        //执行完后 计数
//                        downLatch.countDown(); // 计数器减1
//                    }
//                });
//            }
//            try {
//                //等待
//                downLatch.await(); //等待所有的线程执行结束 当里面的数值变为0的时候主线程就不在等待
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//            long end = System.currentTimeMillis();
//            System.out.println("插入数据耗费时间:"+(end-start));

        }
        return featureList;
    }

    private String[] getFeatureDataType(List<String[]> csvData) {
        String[] dataType = new String[csvData.get(0).length];
        for (String[] csvDatum : csvData) {  //遍历每一行
            for (int i=0; i<csvDatum.length; i++) { // 遍历每一列
                try {
                    Float.parseFloat(csvDatum[i]); // 可以转成数字
                }catch (Exception e){ // 不可以转成数字
                    dataType[i] = "VARCHAR(255)";
                }
            }
        }
        for(int i=0; i<csvData.get(0).length; i++){
            if(dataType[i]==null) dataType[i]="float8";
        }
        return dataType;
    }

    // 数据填充后将数据导出csv 文件 List<String> 每一个string都是一行数据,以逗号分开
    @Override
    public List<String> exportFile(ExportFilledDataTableVo dataFillMethodVo){
        // 获取填充的数据信息
        List<Map<String, IsFillVo>> fillData = indicatorManagementService.fillData(dataFillMethodVo.getDataFillMethodVo()); // 每一个map是一行数据(只有填充的列)
        // 获取这个表的所有数据
        List<LinkedHashMap<String, Object>> tableData = tableDataMapper.getAllTableData(dataFillMethodVo.getDataFillMethodVo().getTableName());
        // 获取表头信息
        List<FieldManagementEntity> fields = fieldManagementService.list();
        // 数据整合 表的所有数据有空值,使用填充后的数据替换
        for(int i=0; i<tableData.size(); i++){
            for (IndicatorsMissDataVo colNameVos : dataFillMethodVo.getDataFillMethodVo().getMissCompleteMethod()) {
                if(!tableData.get(i).containsKey(colNameVos.getIndex())){ // 不包含这个列就说明这个是空
                    tableData.get(i).put(colNameVos.getIndex(),fillData.get(i).get(colNameVos.getIndex()).getValue());
                }
            }
        }
        // 每行map长度补齐
        for (LinkedHashMap<String, Object> row : tableData) {
            for (FieldManagementEntity field : fields) {
                if(!row.containsKey(field.getFeatureName())){
                    row.put(field.getFeatureName(),"");
                }
            }
        }
        List<String> fileData = new ArrayList<>();
        StringBuffer tableHead = new StringBuffer();
        for(int i=0; i<fields.size(); i++){
            if(i!=fields.size()-1){
                tableHead.append(fields.get(i).getFeatureName()+",");
            }else{
                tableHead.append(fields.get(i).getFeatureName());
            }
        }
        fileData.add(tableHead.toString());
        for (LinkedHashMap<String, Object> rowData: tableData) {
            StringBuffer temp = new StringBuffer();
            for(int i=0; i<fields.size(); i++){
                if(i!=fields.size()-1) {
                    temp.append(rowData.get(fields.get(i).getFeatureName())+",");
                }else{
                    temp.append(rowData.get(fields.get(i).getFeatureName()));
                }
            }
            fileData.add(temp.toString());
        }
        UserLog userLog = new UserLog(null, UserThreadLocal.get().getUid(),UserThreadLocal.get().getUsername(),new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),"疾病数据文件导出");
        userLogService.save(userLog);
        return fileData;
    }


    // 对某个特征进行描述性分析
    @Override
    public FeatureDescAnaVo featureDescAnalyze(String featureName, String tableName,CreateTaskEntity taskInfo) throws IOException, URISyntaxException {
        // 判断这个特征属于离散还是非离散
        FeatureDescAnaVo featureDescAnaVo = new FeatureDescAnaVo();
        FieldManagementEntity featureEntity = fieldManagementService.getOne(new QueryWrapper<FieldManagementEntity>().eq("feature_name", featureName));
        if(featureEntity==null){ // 不被字段管理表管理
            featureEntity = new FieldManagementEntity();
            // 查询数据库判断是否离散
            Map<String, Long> map= indicatorManagementMapper.getFiledCount(featureName, tableName);
            if(map.get("num1")<=10 && map.get("num1")>=1 && 1.0*map.get("num1")/map.get("num2")<0.05) {
                System.out.println("判断为离散");
                featureEntity.setDiscrete(true);
            }

            else featureEntity.setDiscrete(false);
        }
        if(featureEntity.getDiscrete()==null || !featureEntity.getDiscrete()){ // 非离散
            // 获取 总条数 中位数 众数 均值 中位数 最小值 最大值 众数
            // 调用远程方法
            Integer totalCount = tableDataMapper.getAllCount(tableName);
            ArrayList<String> cols = new ArrayList<>();
            cols.add(featureName);
            RunPyEntity param = new RunPyEntity(tableName,null,cols);
            JsonNode jsonNode = HTTPUtils.postRequest(param, "/notDiscreteFeatureDesc");
            // 解析返回值
            NotDiscrete notDiscrete = getDataFromPy(jsonNode);
            /**  数据分段 柱状图数据 6个柱子 一个柱子表示一个数据范围取值的数据量 跟据最大最小值划分区间 判断类型 如果是整数就转换成整数就不保留小数, 浮点数就保留小数 **/
            LinkedHashMap<String, Integer> binData = getBinData(notDiscrete.getMax(), notDiscrete.getMin(), tableName, featureName);

            notDiscrete.setBinData(binData);
            notDiscrete.setTotal(totalCount);
            featureDescAnaVo.setNotDiscrete(notDiscrete);
            featureDescAnaVo.setDiscrete(false);
        }else{ // 离散
            List<String> values = new ArrayList<>();
            if(featureEntity.getRange() == null) { // 不被字段管理表管理
                // 获取表中这个字段有哪些不同的取值
                System.out.println("表名:"+tableName +"  列名:"+featureName+ "  mapper:"+tableDataMapper);
                Object[] res =  tableDataMapper.getDistinctValue(tableName, featureName);
                System.out.println("返回结果"+JSON.toJSONString(res));
                for (Object re : res) values.add(re.toString());
            }else{
                String s = featureEntity.getRange().replace("{", "").replace("}", "");
                String[] featureValues = s.split(",");
                for (String featureValue : featureValues) values.add(featureValue);
            }
            ArrayList<DiscreteVo> discreteVos = new ArrayList<>();
            // 获取数据总条数

            Integer totalCount = tableDataMapper.getAllCount(tableName);
            Integer validCount = 0;
            for (String featureValue : values) {
                DiscreteVo discreteVo = new DiscreteVo();
                // 计算每个取值的数据总条数
                featureValue = featureValue.trim().replace("\"", "");
                System.out.println("featureValue = "+featureValue);
                Integer count = tableDataMapper.getCount(featureValue,tableName,featureName);
                validCount+=count;
                discreteVo.setFrequent(count);
                discreteVo.setTotalAmount(Float.parseFloat(String.format("%.2f",(float)count/totalCount*100))); // 累计占比
                discreteVo.setVariable(featureValue);
                discreteVos.add(discreteVo);
                System.err.println("当前离散vo:"+discreteVo);
            }
            for (DiscreteVo discreteVo : discreteVos) {
                discreteVo.setAmount(Float.parseFloat(String.format("%.2f",(float)discreteVo.getFrequent()/validCount*100))); // 有效值占比
            }
            featureDescAnaVo.setDiscrete(true);
            featureDescAnaVo.setDiscreteVos(discreteVos);

        }
        UserLog userLog = new UserLog(null, UserThreadLocal.get().getUid(),UserThreadLocal.get().getUsername(),new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),"疾病数据描述性分析");
        userLogService.save(userLog);


        //判断任务管理中是否有该任务,如果有就不在继续创建 没有就创建任务
        List<Task> list = taskService.list(null);
        List<Task> isRepeat = list.stream().filter(task -> {
            return "描述性分析".equals(task.getTasktype()) && task.getFeature().equals(featureName) && task.getDataset().equals(tableName) && task.getTaskname().equals(taskInfo.getTaskName());
        }).collect(Collectors.toList());
        if(isRepeat == null || isRepeat.size() == 0){
            Task task = new Task();
            task.setCreatetime(new Timestamp(System.currentTimeMillis()));
            task.setDataset(tableName);
            task.setFeature(featureName);

            String leader = taskInfo.getPrincipal();
            if(leader == null || leader=="") {
                System.out.println("操作人为空");
                leader = UserThreadLocal.get().getUsername();
            }
            task.setLeader(leader);

            String taskName = taskInfo.getTaskName();
            if(taskName == null || taskName=="") {
                System.out.println("任务名称为空");
                taskName = UserThreadLocal.get().getUsername()+"_"+"描述性分析_"+ LocalDate.now().toString();
            }
            task.setTaskname(taskName);
            task.setParticipant(taskInfo.getParticipants());
            task.setTasktype(taskInfo.getTasktype()==null?"描述性分析":taskInfo.getTasktype());

            // 获取关联疾病 TODO
            // 跟据表名获取父节点的名称 select label from category where "id"=(select parent_id from category where label='copd')
            String label = categoryMapper.getParentLabelByLabel(tableName);
            task.setDisease(label);
            task.setRemark(taskInfo.getTips());

            task.setResult(JSON.toJSONString(featureDescAnaVo));
            task.setUserid(UserThreadLocal.get().getUid());
            task.setTargetcolumn(featureName);
            System.out.println("插入:"+task);
            taskService.save(task);
        }
        return featureDescAnaVo;
    }

    @Override
    public SingleAnalyzeVo singleFactorAnalyze(String tableName, List<String> colNames,CreateTaskEntity taskInfo) throws IOException, URISyntaxException {
        RunPyEntity param = new RunPyEntity(tableName,null,colNames);
        JsonNode jsonNode = HTTPUtils.postRequest(param, "/singleFactorAnalyze");
        SingleAnalyzeVo singleAnalyzeDataFromJsonNode = getSingleAnalyzeDataFromJsonNode(jsonNode);

        List<Task> list = taskService.list(null);
        List<Task> isRepeat = list.stream().filter(task -> {
            return task.getTasktype().equals("单因素分析") && task.getFeature().equals(colNames.stream().collect(Collectors.joining(","))) && task.getDataset().equals(tableName) && task.getTaskname().equals(taskInfo.getTaskName());
        }).collect(Collectors.toList());
        if(isRepeat == null || isRepeat.size() == 0){
            // 创建任务
            System.err.println("开始创建任务");
            Task task = new Task();
            task.setCreatetime(new Timestamp(System.currentTimeMillis()));
            task.setDataset(tableName);
            String featureNames = colNames.stream().collect(Collectors.joining(","));
            task.setFeature(featureNames);

            String leader = taskInfo.getPrincipal();
            if(leader == null || leader=="") {
                leader = UserThreadLocal.get().getUsername();
            }
            task.setLeader(leader);
            task.setRemark(taskInfo.getTips());
            String taskName = taskInfo.getTaskName();
            if(taskName == null || taskName=="") taskName = UserThreadLocal.get().getUsername()+"_"+"单因素分析_"+ LocalDate.now().toString();
            task.setTaskname(taskName);
            task.setParticipant(taskInfo.getParticipants());
            task.setTasktype(taskInfo.getTasktype()==null?"单因素分析":taskInfo.getTasktype());

            // 获取关联疾病 TODO
            // 跟据表名获取父节点的名称 select label from category where "id"=(select parent_id from category where label='copd')
            String label = categoryMapper.getParentLabelByLabel(tableName);
            task.setDisease(label);
            task.setResult(JSON.toJSONString(singleAnalyzeDataFromJsonNode));
            task.setUserid(UserThreadLocal.get().getUid());
            task.setTargetcolumn(colNames.get(1));
            taskService.save(task);
        }
        return singleAnalyzeDataFromJsonNode;
    }

    // TODO 一致性验证
    @Override
    public ConsistencyAnalyzeVo consistencyAnalyze(String tableName, String featureName,CreateTaskEntity taskInfo) throws IOException, URISyntaxException {
        ArrayList<String> featureNames = new ArrayList<>();
        featureNames.add(featureName);
        RunPyEntity param = new RunPyEntity(tableName,null,featureNames);
        JsonNode jsonNode = HTTPUtils.postRequest(param, "/consistencyAnalyze");
        System.out.println("返回状态码:"+jsonNode.get("code").asInt());
        if(jsonNode.get("code").asInt()==500) return null;
        List<ICCVo> consistencyAnalyzeFromJsonNode = getConsistencyAnalyzeFromJsonNode(jsonNode);
        ConsistencyAnalyzeVo consistencyAnalyzeVo = new ConsistencyAnalyzeVo();
        consistencyAnalyzeVo.setICCAnalyzeResult(consistencyAnalyzeFromJsonNode);

        List<Task> list = taskService.list(null);
        List<Task> isRepeat = list.stream().filter(task -> {
            return task.getTasktype().equals("一致性验证") && task.getFeature().equals(featureName) && task.getDataset().equals(tableName)&&task.getTaskname().equals(taskInfo.getTaskName());
        }).collect(Collectors.toList());
        if(isRepeat == null || isRepeat.size() == 0) {
            // 创建任务
            Task task = new Task();
            task.setCreatetime(new Timestamp(System.currentTimeMillis()));
            task.setDataset(tableName);
            task.setFeature(featureName);

            String leader = taskInfo.getPrincipal();
            if(leader == null || leader=="") {
                leader = UserThreadLocal.get().getUsername();
            }
            task.setLeader(leader);
            task.setRemark(taskInfo.getTips());
            String taskName = taskInfo.getTaskName();
            if(taskName == null || taskName=="") taskName = UserThreadLocal.get().getUsername()+"_"+"一致性验证_"+ LocalDate.now().toString();
            task.setTaskname(taskName);
            task.setParticipant(taskInfo.getParticipants());
            task.setTasktype(taskInfo.getTasktype()==null?"一致性验证":taskInfo.getTasktype());

            // 获取关联疾病 TODO
            // 跟据表名获取父节点的名称 select label from category where "id"=(select parent_id from category where label='copd')
            String label = categoryMapper.getParentLabelByLabel(tableName);
            task.setDisease(label);
            task.setModel("ICC");
            task.setResult(JSON.toJSONString(consistencyAnalyzeVo));
            task.setUserid(UserThreadLocal.get().getUid());
            task.setTargetcolumn(featureName);
            System.err.println("保存任务信息:"+task);
            taskService.save(task);
        }
        return consistencyAnalyzeVo;
    }

    @Override
    public List<Map<String, Object>> getTableDataByFields(String tableName, List<String> featureList) {
        List<Map<String, Object>> tableData = tableDataMapper.getTableDataByFields(tableName,featureList);
        return tableData;
    }

    @Override
    public Integer getDataCount(List<CategoryEntity> categoryEntities) {
        int count = 0;
        for (CategoryEntity categoryEntity : categoryEntities) {
            count+=tableDataMapper.getCountByName(categoryEntity.getLabel());
        }
        return count;
    }

    private List<ICCVo> getConsistencyAnalyzeFromJsonNode(JsonNode jsonNode){
        JsonNode icc1 = jsonNode.get("ICC1");
        JsonNode icc2 = jsonNode.get("ICC2");
        ICCVo iccVo1 = new ICCVo();
        ICCVo iccVo2 = new ICCVo();
        iccVo1.setMethod(icc1.get("method").asText());
        iccVo1.setType(icc1.get("type").asText());
        iccVo1.setICC(icc1.get("ICC").asDouble());
        iccVo1.setDf1(icc1.get("df1").asInt());
        iccVo1.setDf2(icc1.get("df2").asInt());
        iccVo1.setF(icc1.get("F").asDouble());
        iccVo1.setP(icc1.get("p").asDouble());

        iccVo2.setMethod(icc2.get("method").asText());
        iccVo2.setType(icc2.get("type").asText());
        iccVo2.setICC(icc2.get("ICC").asDouble());
        iccVo2.setDf1(icc2.get("df1").asInt());
        iccVo2.setDf2(icc2.get("df2").asInt());
        iccVo2.setF(icc2.get("F").asDouble());
        iccVo2.setP(icc2.get("p").asDouble());
        ArrayList<ICCVo> iccVos = new ArrayList<>();
        iccVos.add(iccVo1);
        iccVos.add(iccVo2);
        System.out.println("ICC:"+JSON.toJSONString(iccVos));
        return iccVos;
    }

    private SingleAnalyzeVo getSingleAnalyzeDataFromJsonNode(JsonNode jsonNode){
        SingleAnalyzeVo singleAnalyzeVo = new SingleAnalyzeVo();
        singleAnalyzeVo.setWilcoxonW(jsonNode.get("w_stat").asDouble());
        singleAnalyzeVo.setWilcoxonP(jsonNode.get("p_value_w").asDouble());
        singleAnalyzeVo.setTT(jsonNode.get("t_stat").asDouble());
        singleAnalyzeVo.setTP(jsonNode.get("p_value_t").asDouble());
        singleAnalyzeVo.setCorrectTT(jsonNode.get("correct_t_stat").asDouble());
        singleAnalyzeVo.setCorrectTP(jsonNode.get("correct_p_value_t").asDouble());

        JsonNode classInfo = jsonNode.get("classInfo"); // 字典对象list。包含了每个类别的统计信息类别名称(className)类别总数 有效个数 缺失值个数
        System.out.println("classInfo:"+JSON.toJSONString(classInfo));
        ArrayList<DiscreteVo> discreteVos = new ArrayList<>();
        for (JsonNode node : classInfo) {
            DiscreteVo discreteVo = new DiscreteVo();
            discreteVo.setVariable(node.get("className").asText());
            discreteVo.setFrequent(node.get("frequent").asInt());
            discreteVo.setValidFrequent(node.get("validFrequent").asInt());
            discreteVo.setMissFrequent(node.get("missFrequent").asInt());
            discreteVos.add(discreteVo);
        }
        singleAnalyzeVo.setDiscreteVos(discreteVos);
        // 分类获取两组数据
        ArrayList<Double> group1 = new ArrayList<>();
        JsonNode group1Node = jsonNode.get("group1");
        for (JsonNode node : group1Node) {
            group1.add(node.asDouble());
        }
        ArrayList<Double> group2 = new ArrayList<>();
        JsonNode group2Node = jsonNode.get("group2");
        for (JsonNode node : group2Node) {
            group2.add(node.asDouble());
        }
        // 分成六个柱状图的柱子描述数据分布区间
        NotDiscrete notDiscrete1 = new NotDiscrete();
        NotDiscrete notDiscrete2 = new NotDiscrete();
        if(group1.size()>0) notDiscrete1.setBinData(getBinData(group1,7));
        singleAnalyzeVo.setNotDiscrete(notDiscrete1);
        if(group2.size()>0) notDiscrete2.setBinData(getBinData(group2,7));
        singleAnalyzeVo.setNotDiscrete2(notDiscrete2);
        return singleAnalyzeVo;
    }


    private LinkedHashMap<String,Integer> getBinData(List<Double> data,int binCount){
        LinkedHashMap<String, Integer> res = new LinkedHashMap<>();
        data.sort(new Comparator<Double>() {
            @Override
            public int compare(Double o1, Double o2) {
                if(o1>o2) return 1;
                else if(o1<o2) return -1;
                else return 0;
            }
        });
        // 找到最大值 最小值 分区间划分
        double max = data.get(data.size()-1);
        double min = data.get(0);
        double gap = (max-min)/binCount;

        for(int i=0; i<binCount; i++){
            int count = 0;
            Double end,start;

            start = min + gap * i;
            if(i==binCount-1) end = max;
            else end = min + gap * (i+1);
            for (Double datum : data) {
                if(i==binCount-1){
                    if (datum < end && datum >= start) count++;
                }else{
                    if (datum <= end && datum >= start) count++;
                }

            }
            start = Double.parseDouble(String.format("%.2f", start));
            end = Double.parseDouble(String.format("%.2f", end));
            res.put(start+"~"+end,count);
        }
        return res;
    }




    private boolean writeDataToCSV(List<String> data, String filePath) {
        try (CSVWriter writer = new CSVWriter(new FileWriter(filePath))) {
            // 写入数据
            for (String line : data) {
                String[] parts = line.split(","); // 分割每行的数据
                writer.writeNext(parts); // 写入CSV文件
            }
            return true;
        } catch (IOException e) {
            System.err.println("写入CSV文件时出现错误: " + e.getMessage());
            return false;
        }
    }

    private NotDiscrete getDataFromPy(JsonNode jsonNode){
        NotDiscrete notDiscrete = new NotDiscrete();
        String averageAsString = jsonNode.get("average").asText();
        float average = Float.parseFloat(averageAsString);
        notDiscrete.setAverage(Float.parseFloat(String.format("%.2f", average)));
        notDiscrete.setMax(Float.parseFloat(jsonNode.get("max").asText()));
        notDiscrete.setMin(Float.parseFloat(jsonNode.get("min").asText()));
        notDiscrete.setMode(Float.parseFloat(jsonNode.get("mode").asText()));
        notDiscrete.setMiddle(Float.parseFloat(jsonNode.get("middle").asText()));
        notDiscrete.setTotal(jsonNode.get("middle").asInt());
        return notDiscrete;
    }
    private LinkedHashMap<String,Integer> getBinData(Float max, Float min, String tableName, String featureName){
        // 分成6个区间
        float gap = (max-min)/6;
        gap = Float.parseFloat(String.format("%.2f", gap));
        LinkedHashMap<String, Integer> binData = new LinkedHashMap<>();
        float start = min;
        float end = min;
        for(int i=0; i<6; i++){
            start = Float.parseFloat(String.format("%.2f",min+gap*i));
            if(i==5) end = max;
            else {
                end = Float.parseFloat(String.format("%.2f",min+gap*(i+1)));
            }

            // 获取每个区间的数据量
            String type = null;
            FieldManagementEntity fieldManagementEntity = fieldManagementService.getOne(new QueryWrapper<FieldManagementEntity>().eq("feature_name", featureName));
            if(fieldManagementEntity==null) type =  indicatorManagementMapper.getColType(tableName,featureName);
            else type = fieldManagementEntity.getType();
            if ("integer".equals(type)){
                int s = (int)start;
                int e = (int)end;
                Integer count = tableDataMapper.getCountByCondition(String.valueOf(s),String.valueOf(e), tableName,featureName);
                binData.put(start+"~"+end,count);
            }else{
                Integer count = tableDataMapper.getCountByCondition(String.valueOf(start),String.valueOf(end), tableName,featureName);
                binData.put(start+"~"+end,count);
            }

        }
        return binData;
    }

    private void getLeafNode(CategoryEntity nodeData,List<CategoryEntity> leafNodes){
        if(nodeData.getChildren()!=null && nodeData.getChildren().size()>0){
            for (CategoryEntity child : nodeData.getChildren()) {
                if(child.getIsLeafs()!=null && child.getIsLeafs()==1) leafNodes.add(child);
                else getLeafNode(child,leafNodes);
            }
        }

    }

    private CategoryEntity getBelongType(CategoryEntity nodeData, ArrayList<CategoryEntity> leafNodes){
        getLeafNode(nodeData, leafNodes);
        if(leafNodes!=null && leafNodes.size()>0){
            for (CategoryEntity leafNode : leafNodes) {
                if(leafNode.getIsWideTable()!=null && leafNode.getIsWideTable()==1) {
                    return leafNode;
                }
            }
        }
        return null;
    }




    @Override
    public Integer getCountByTableName(String tableName) {
        return tableDataMapper.getCountByTableName(tableName);
    }

    @Override
    public List<String> getTableFields(String tableName) {
        return tableDataMapper.getTableFields(tableName);
    }

    @Override
    public List<LinkedHashMap<String, Object>> getDataLikeMatch(String tableName, List<String> tableFields, String value) {
        return tableDataMapper.getDataByLikeMatch(tableName, tableFields, value);
    }

//    @Override
//    public void createFilterBtnTable(String dataName, List<CreateTableFeatureVo> characterList, String createUser, String status, String uid, String username, String isFilter, String isUpload, String uidList, String nodeid) {
//
//    }

    @Override
    public void createFilterBtnTable(String tableName, List<CreateTableFeatureVo> characterList, String createUser, String status, String uid, String username, String IsFilter, String IsUpload, String uid_list,String nodeid) {
        /**
         *          筛选数据
         *              查询当前目录下的宽表所有数据
         *                  1、查询nodeData的所有子节点,找到是宽表的节点信息(表名)
         *              筛选 其他病种符合条件的所有数据
         *                  2、遍历所有目录信息 找到所有的宽表节点,排除上一步找到的宽表节点,使用剩下的宽表节点筛选数据
         *              合并所有数据
         *          创建表头信息
         *              3、根据宽表的字段管理表创建一个新表,存储筛选后的数据
         *          保存创建表的数据信息信息
         *              4、将1、2步骤的数据插入到3创建的表中
         *          保存目录信息
         *              5、创建目录节点信息,并保存数据库
         *
         */

        System.out.println("前端传递的值:"+"表名"+tableName+"  userName"+username+"  userId"+uid+"  IsFilter"+IsFilter+"  IsUpload"+"  uid_list"+uid_list+"  nodeID"+nodeid);

        CategoryEntity nodeData = categoryMapper.selectById(nodeid);
        List<LinkedHashMap<String, Object>> res = getFilterDataByConditionsByDieaseId(characterList,uid,username,nodeid);
//        CategoryEntity mustContainNode = getBelongType(nodeData, new ArrayList<CategoryEntity>());
//        // 查询考虑疾病的宽表数据
        //List<LinkedHashMap<String,Object>> diseaseData = tableDataMapper.getAllTableData("merge"); // 传递表名参数
        List<LinkedHashMap<String,Object>> diseaseData = res;
//        System.out.println("考虑疾病所有数据");
//        // 合并考虑疾病和非考虑疾病的所有数据
//        for (LinkedHashMap<String, Object> re : res) {
//            diseaseData.add(re);
//        }
        // 创建表头信息 获取宽表字段管理信息
        List<FieldManagementEntity> fields = fieldManagementService.list(null);
        // System.out.println("字段长度为:"+fields.size());
        HashMap<String, String> fieldMap = new HashMap<>();
        for (FieldManagementEntity field : fields) {
            fieldMap.put(field.getFeatureName(),field.getUnit());
        }
        // TODO 创建表头信息
        tableDataMapper.createTableByField(tableName,fieldMap);
        // TODO 数据保存 批量插入
        // TODO 保证value值数量与字段个数一致
        for (Map<String, Object> diseaseDatum : diseaseData) {
            for (FieldManagementEntity field : fields) {
                if(diseaseDatum.get(field.getFeatureName())==null)
                {
                    diseaseDatum.put(field.getFeatureName(),"");
                }
            }
//            System.out.println("数据长度为:"+diseaseDatum.size());
        }
        System.out.println("========================================");
        System.out.println("数据长度:"+diseaseData.size());
        // TODO 分批插入 防止sql参数传入过多导致溢出
        if(diseaseData.size()>200){
            int batch = diseaseData.size()/200;
            for(int i=0; i<batch; i++){
                int start = i*200, end = (i+1)*200;
                System.out.println("插入第"+i+"轮数据");
                tableDataMapper.bachInsertData(diseaseData.subList(start,end),tableName); // diseaseData.subList(start,end) 前闭后开
            }
            tableDataMapper.bachInsertData(diseaseData.subList(batch*200,diseaseData.size()),tableName);
        }else{
            tableDataMapper.bachInsertData(diseaseData,tableName);
        }
        // 目录信息
        CategoryEntity node = new CategoryEntity();
        node.setIsDelete(0);
        node.setParentId(nodeData.getId());
        node.setIsLeafs(1);
        node.setStatus(status);
        node.setUid(uid);
        node.setUsername(username);
        node.setCatLevel(nodeData.getCatLevel()+1);
        node.setLabel(tableName);
        node.setIs_filter(IsFilter);
        System.out.println(uid_list);
        node.setIs_upload(IsUpload);
        node.setUidList(uid_list);
        System.out.println(node);
        categoryMapper.insert(node); // 保存目录信息

        // 表描述信息
        TableDescribeEntity tableDescribeEntity = new TableDescribeEntity();
        tableDescribeEntity.setTableName(tableName);
        tableDescribeEntity.setCreateUser(node.getUsername());
//        tableDescribeEntity.setUid(Integer.parseInt(uid));
        tableDescribeEntity.setUid(UserThreadLocal.get().getUid());
        tableDescribeEntity.setTableStatus(node.getStatus());
        tableDescribeEntity.setCreateUser(username);
        tableDescribeEntity.setCreateTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        tableDescribeEntity.setClassPath(nodeData.getLabel()+"/"+tableName);
        tableDescribeEntity.setTableId(node.getId());
        tableDescribeEntity.setTableSize(0.0f);
        // 保存表描述信息
        tableDescribeMapper.insert(tableDescribeEntity);

    }

    @Override
    public List<LinkedHashMap<String, Object>> getFilterDataByConditionsByDieaseId(List<CreateTableFeatureVo> characterList, String uid, String username, String nodeid) {
        System.out.println("历史数据筛选参数:nodeId "+nodeid +"  uid "+uid+"  username "+username);

        List<CategoryEntity> categoryEntities = categoryMapper.selectList(null); // 查询所有的目录信息
        CategoryEntity nodeData = categoryMapper.selectById(nodeid);
        // 找到所有的宽表节点
        List<CategoryEntity> allWideTableNodes = categoryEntities.stream().collect(Collectors.toList());
        // 遍历当前节点的所有叶子节点,找到这个宽表节点
        ArrayList<CategoryEntity> leafNodes = new ArrayList<>();
//        getLeafNode(nodeData, leafNodes);
        /** 找到所有的非考虑疾病的宽表节点 **/
        List<CategoryEntity> otherWideTable = null;
        if(leafNodes!=null && leafNodes.size()>0){
        }else{
            otherWideTable = allWideTableNodes;
        }
        if(otherWideTable==null) otherWideTable = allWideTableNodes;
        // 筛选所有非考虑疾病的宽表数据
        /** select * from ${tableName} where ${feature} ${computeOpt} ${value} ${connector} ... **/
        // 前端传过来的 AND OR NOT 是数字形式0,1,2,需要变成字符串拼接sql
        for (CreateTableFeatureVo createTableFeatureVo : characterList) {
            if(createTableFeatureVo.getOpt()==null) createTableFeatureVo.setOptString("");
            else if(createTableFeatureVo.getOpt()==0) createTableFeatureVo.setOptString("AND");
            else if(createTableFeatureVo.getOpt()==1) createTableFeatureVo.setOptString("OR");
            else createTableFeatureVo.setOptString("AND NOT");
        }
        // 处理varchar类型的数据
        for (CreateTableFeatureVo createTableFeatureVo : characterList) {
            if(createTableFeatureVo.getType()==null || createTableFeatureVo.getType().equals("character varying")){
                createTableFeatureVo.setValue("'"+createTableFeatureVo.getValue()+"'");
            }
        }
        List<List<LinkedHashMap<String, Object>>> otherWideTableData = new ArrayList<>();
        ArrayList<LinkedHashMap<String, Object>> res = new ArrayList<>();
        otherWideTableData.add(tableDataMapper.getFilterData("merge",characterList));
        ArrayList<LinkedHashMap<String, Object>> res2 = new ArrayList<>();
        for (List<LinkedHashMap<String, Object>> otherWideTableDatum : otherWideTableData) {
            for (LinkedHashMap<String, Object> rowData : otherWideTableDatum) {
                res.add(rowData);
            }
        }
        // 插入 filter_data_info 表信息
        FilterDataInfo filterDataInfo = new FilterDataInfo();
//        filterDataInfo.setUid(Integer.parseInt(uid));
        filterDataInfo.setUid(UserThreadLocal.get().getUid());
        filterDataInfo.setCreateUser(username);
        filterDataInfo.setUsername(username);
        filterDataInfo.setCateId(nodeData.getId());
        filterDataInfo.setParentId(nodeData.getParentId());
        filterDataInfo.setFilterTime(new Timestamp(System.currentTimeMillis())); // 时间
        filterDataInfoMapper.insert(filterDataInfo);


        ArrayList<FilterDataCol> filterDataCols = new ArrayList<>();
        for (CreateTableFeatureVo createTableFeatureVo : characterList) {
            FilterDataCol filterDataCol = new FilterDataCol();
            BeanUtils.copyProperties(createTableFeatureVo,filterDataCol);
            filterDataCol.setFilterDataInfoId(filterDataInfo.getId());
            FieldManagementEntity fieldManagementEntity = fieldManagementService.getOne(new QueryWrapper<FieldManagementEntity>().eq("feature_name", createTableFeatureVo.getFeatureName()));
            filterDataCol.setRange(fieldManagementEntity.getRange());
            filterDataColMapper.insert(filterDataCol);
        }
        return res;
    }


    @Override
    public List<Map<String, Object>> getInfoByTableName(String tableName) {
        return tableDataMapper.getInfoByTableName(tableName);
    }


}



TableDescribeServiceImpl

这段代码是一个服务实现类,用于操作数据库中表的描述信息。让我逐步解释:
1. `TableDescribeServiceImpl` 类实现了 `TableDescribeService` 接口,并继承了 `ServiceImpl<TableDescribeMapper, TableDescribeEntity>`。这意味着它是一个基于 MyBatis-Plus 的服务实现类,用于处理 `TableDescribeEntity` 实体类的数据库操作。
2. 在类上标注了 `@Service` 注解,表示它是一个 Spring 的服务类。
3. `tableDescribeMapper` 属性通过 `@Autowired` 注解注入了 `TableDescribeMapper` 类型的 Bean。
4. `getColCount(String tableName)` 方法用于获取指定表名的列数,它调用了 `tableDescribeMapper` 的 `getColCount` 方法,并将表名作为参数传入。
5. `getRowCount(String tableName)` 方法用于获取指定表名的行数,类似地,它调用了 `tableDescribeMapper` 的 `getRowCount` 方法,并将表名作为参数传入。
这些方法的目的是为了提供对数据库表结构的基本信息查询功能。
package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.entity.TableDescribeEntity;
import com.cqupt.software_1.mapper.TableDescribeMapper;
import com.cqupt.software_1.service.TableDescribeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

// TODO 公共模块新增类

@Service
public class TableDescribeServiceImpl extends ServiceImpl<TableDescribeMapper, TableDescribeEntity> implements TableDescribeService {
    @Autowired
    TableDescribeMapper tableDescribeMapper;
    @Override
    public Integer getColCount(String tableName) {
        return tableDescribeMapper.getColCount(tableName);
    }

    @Override
    public Integer getRowCount(String tableName) {
        return tableDescribeMapper.getRowCount(tableName);
    }
}

TableManagerServiceImpl

这段代码是针对数据库中表 `t_table_manager` 的操作服务实现类,让我逐步解释:
1. `TableManagerServiceImpl` 类实现了 `TableManagerService` 接口,并继承了 `ServiceImpl<TableManagerMapper, TableManager>`。这意味着它是一个基于 MyBatis-Plus 的服务实现类,用于处理 `TableManager` 实体类的数据库操作。
2. 在类上标注了 `@Service` 注解,表示它是一个 Spring 的服务类。
3. `tableManagerMapper` 属性通过 `@Autowired` 注解注入了 `TableManagerMapper` 类型的 Bean。
4. `getAllData()` 方法用于获取表 `t_table_manager` 中的所有数据,它调用了 `tableManagerMapper` 的 `selectList(null)` 方法。
5. `insertTableManager(TableManagerDTO tableManagerDTO)` 方法用于插入表管理信息,它调用了 `tableManagerMapper` 的 `insertTableManager` 方法。
6. `getFiledByTableName(String tableName)` 方法用于根据表名获取字段名列表,它调用了 `tableManagerMapper` 的 `getFiledByTableName` 方法。
7. `getCommentsByTableName(String tableName)` 方法用于根据表名获取字段注释列表,类似地,它调用了 `tableManagerMapper` 的 `getCommentsByTableName` 方法。
8. `getInfoByTableName(String tableName)` 方法用于根据表名获取表信息,它调用了 `tableManagerMapper` 的 `getInfoByTableName` 方法。
9. `getInfoByFiled(String param)` 方法根据字段信息获取表信息,它调用了 `tableManagerMapper` 的 `getInfoByFiled` 方法。
10. `getAllTableManagersByFiledName(List<String> tableNames)` 方法根据
package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.common.TableManagerDTO;
import com.cqupt.software_1.entity.TableManager;
import com.cqupt.software_1.service.TableManagerService;
import com.cqupt.software_1.mapper.TableManagerMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
* @author hp
* @description 针对表【t_table_manager】的数据库操作Service实现
* @createDate 2023-05-23 15:10:20
*/
@Service
public class TableManagerServiceImpl extends ServiceImpl<TableManagerMapper, TableManager>
    implements TableManagerService {


    @Autowired
    private TableManagerMapper tableManagerMapper;

    @Override
    public List<TableManager> getAllData() {


        List<TableManager> tableManager = tableManagerMapper.selectList(null);


        return tableManager;
    }


    @Override
    public void insertTableManager(TableManagerDTO tableManagerDTO) {
        tableManagerMapper.insertTableManager(tableManagerDTO);
    }

    @Override
    public List<String> getFiledByTableName(String tableName) {
        List<String> tableNames = tableManagerMapper.getFiledByTableName(tableName);

        return tableNames;
    }

    @Override
    public List<String> getCommentsByTableName(String tableName) {

        List<String> comments = tableManagerMapper.getCommentsByTableName(tableName);

        return comments;
    }

    @Override
    public List<Object> getInfoByTableName(String tableName) {



        List<Object> res = tableManagerMapper.getInfoByTableName(tableName);

        return res;
    }

    @Override
    public boolean[] getInfoByFiled(String param) {


        boolean r1 = false,r2 = false, r3 = false;
        TableManager tableManager = tableManagerMapper.getInfoByFiled(param);

        if (tableManager != null){

            r1 = Objects.equals(tableManager.getIsDemography(), "1");
           r2 = Objects.equals(tableManager.getIsPhysiological(), "1");
             r3 = Objects.equals(tableManager.getIsSociology(), "1");
        }

        return new boolean[]{r1,r2,r3};
    }

    @Override
    public List<TableManager> getAllTableManagersByFiledName(List<String> tableNames) {

        List<TableManager> res= new ArrayList<>();

        for (int i = 0; i< tableNames.size() ; i++) {
            QueryWrapper queryWrapper = new QueryWrapper();

            queryWrapper.eq("field_name", tableNames.get(i));
            queryWrapper.eq("table_name","Diabetes");
            TableManager tableManager = tableManagerMapper.selectOne(queryWrapper);
            res.add(tableManager);
        }
        return res;
    }

    @Override
    public List<TableManager> getAllDataByUserId(Integer userId) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("user_id",userId);
        List<TableManager> tableManager = tableManagerMapper.selectList(queryWrapper);

        return tableManager;
    }


}

TableServiceImpl

这段代码是一个基于Spring框架的Java服务实现类。让我逐步解释每个部分的功能:

1. **包声明和导入**:
   ```java
   package com.cqupt.software_1.service.impl;

   import com.cqupt.software_1.entity.TableManager;
   import com.cqupt.software_1.mapper.TableMapper;
   import com.cqupt.software_1.service.TableService;
   import org.springframework.beans.factory.annotation.Autowired;
   import org.springframework.stereotype.Service;

   import java.util.List;
   import java.util.Map;
  • com.cqupt.software_1.service.impl 是该类所在的包。
  • TableManagerTableMapper 是引入的实体类和数据访问对象(DAO),用于操作数据库表。
  • TableService 是服务接口,定义了该类需要实现的服务方法。
  • @Autowired@Service 是Spring框架的注解,用于依赖注入和声明该类为服务类。
  1. 类声明

    @Service
    public class TableServiceImpl implements TableService {
    
    • @Service 注解表明这是一个Spring的服务类,负责业务逻辑的实现。
    • TableServiceImpl 类实现了 TableService 接口,意味着需要实现接口中定义的方法。
  2. 依赖注入

    @Autowired
    private TableMapper tableMapper;
    
    • 使用 @Autowired 注解将 TableMapper 注入到 TableServiceImpl 类中,使得可以在类中直接使用 tableMapper 访问数据库。
  3. 方法实现

    • createTable 方法

      @Override
      public void createTable(String tableName, Map<String, String> fieldMap) {
          tableMapper.createTable(tableName, fieldMap);
      }
      
      • createTable 方法用于创建数据库表。
      • 参数 tableName 是表名,fieldMap 是字段名和字段类型的映射。
      • 调用 tableMappercreateTable 方法来执行具体的数据库表创建操作。
    • saveCSV2MySQL 方法

      @Override
      public void saveCSV2MySQL(String remotePath, String originalFilename) {
          tableMapper.saveCSV2MySQL(remotePath, originalFilename);
      }
      
      • saveCSV2MySQL 方法用于将CSV文件保存到MySQL数据库中。
      • 参数 remotePath 是远程文件路径,originalFilename 是原始文件名。
      • 调用 tableMappersaveCSV2MySQL 方法来实现具体的文件导入操作。
    • insertTableInfo 方法

      @Override
      public void insertTableInfo(String tableName) {
          tableMapper.insertTableInfo(tableName);
      }
      
      • insertTableInfo 方法用于向数据库中插入表信息。
      • 参数 tableName 是表名。
      • 调用 tableMapperinsertTableInfo 方法来执行具体的数据库插入操作。

这些方法实现了 TableService 接口中定义的服务功能,通过 TableMapper 实现了与数据库的交互,具体功能包括表创建、CSV文件导入和表信息插入。


```javascript
package com.cqupt.software_1.service.impl;

import com.cqupt.software_1.entity.TableManager;
import com.cqupt.software_1.mapper.TableMapper;
import com.cqupt.software_1.service.TableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;


@Service
public class TableServiceImpl implements TableService {

    @Autowired
    private TableMapper tableMapper;

    @Override
    public void createTable(String tableName, Map<String, String> fieldMap) {

         tableMapper.createTable(tableName, fieldMap);

    }

    @Override
    public void saveCSV2MySQL(String remotePath, String originalFilename) {
        tableMapper.saveCSV2MySQL(remotePath,originalFilename);
    }

    @Override
    public void insertTableInfo(String tableName) {

        tableMapper.insertTableInfo(tableName);
    }
}

TaskServiceImpl

这段代码是一个Java类,实现了`TaskService`接口,并提供了对任务(Task)的各种操作。

1. `getAlgorithmUsageDailyStatsLast7Days()`:获取过去7天内算法的每日使用统计数据。
2. `getAlgorithmName()`:获取所有算法的名称。
3. `getTaskList()`:获取所有任务列表。
4. `getlistbyId(Integer id)`:通过任务ID获取任务信息。
5. `deleteTask(int id)`:根据任务ID删除任务。
6. `getLeaderList()`:获取所有负责人(领导)的列表。
7. `createVisualizationTask(String tableName, Map<String, Object> selectDiseaseMap, CreateTaskEntity taskInfo)`:创建可视化任务,将选定的疾病数据和任务信息存储到数据库中。
8. `getTaskCountByTime(String timeStr)`:根据时间字符串获取任务数量。
9. `addRepresentTask(String tableName, List<String> colNames, String model, CreateTaskEntity taskInfo)`:添加代表性任务,将表名、列名、模型信息以及任务信息存储到数据库中。

这些方法通过调用`TaskMapper`和`CategoryMapper`中的对应方法实现数据库操作。其中,`TaskMapper`用于对任务表进行操作,而`CategoryMapper`用于获取疾病标签信息。
package com.cqupt.software_1.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cqupt.software_1.common.UserThreadLocal;
import com.cqupt.software_1.entity.AlgorithmUsageDailyStats;
import com.cqupt.software_1.entity.CreateTaskEntity;
import com.cqupt.software_1.entity.Task;
import com.cqupt.software_1.mapper.CategoryMapper;
import com.cqupt.software_1.mapper.TaskMapper;
import com.cqupt.software_1.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task>
        implements TaskService {
    @Resource
    TaskMapper taskMapper;
    @Autowired
    CategoryMapper categoryMapper;

    @Override
    public List<AlgorithmUsageDailyStats> getAlgorithmUsageDailyStatsLast7Days() {
        return taskMapper.getAlgorithmUsageDailyStatsLast7Days();
    }

    @Override
    public List<String> getAlgorithmName() {
        return taskMapper.getAlgorithmName();
    }

    @Override
    public List<Task> getTaskList() {
        return taskMapper.getTaskList();
    }

    @Override
    public Task getlistbyId(Integer id) {
        return taskMapper.getlistbyId(id);
    }

    @Override
    public void deleteTask(int id) {
        taskMapper.deleteTask(id);
    }

    @Override
    public List<String> getLeaderList() {
        return taskMapper.getLeaderList();
    }

    @Override
    public void createVisualizationTask(String tableName, Map<String, Object> selectDiseaseMap, CreateTaskEntity taskInfo) {
        Task task = new Task();
        String features = selectDiseaseMap.keySet().stream().collect(Collectors.joining(","));
        task.setFeature(features);
        task.setTargetcolumn(features);
        task.setCreatetime(new Timestamp(System.currentTimeMillis()));
        task.setDataset(tableName);

        task.setLeader(taskInfo.getPrincipal()==null?UserThreadLocal.get().getUsername():taskInfo.getPrincipal());
        task.setParticipant(taskInfo.getParticipants());
        task.setTasktype(taskInfo.getTasktype()==null?"病人画像":taskInfo.getTasktype());
        task.setTaskname(taskInfo.getTaskName()==null?UserThreadLocal.get().getUsername()+"_病人画像_"+ LocalDate.now().toString():taskInfo.getTaskName());

        String label = categoryMapper.getParentLabelByLabel(tableName);
        task.setDisease(label);
        task.setRemark(taskInfo.getTips());
        task.setModel("无");
        task.setResult(JSON.toJSONString(selectDiseaseMap));
        task.setUserid(UserThreadLocal.get().getUid());
        taskMapper.insert(task);
    }

    @Override
    public Integer getTaskCountByTime(String timeStr) {
        return taskMapper.getTaskCountByTime(timeStr);
    }

    @Override
    public void addRepresentTask(String tableName, List<String> colNames,String model, CreateTaskEntity taskInfo) {
        Task task = new Task();
        String features = colNames.stream().collect(Collectors.joining(","));
        task.setFeature(features);
        task.setTargetcolumn(features);

        task.setCreatetime(new Timestamp(System.currentTimeMillis()));
        task.setDataset(tableName);

        task.setLeader(taskInfo.getPrincipal()==null?UserThreadLocal.get().getUsername():taskInfo.getPrincipal());
        task.setParticipant(taskInfo.getParticipants());
        task.setTasktype(taskInfo.getTasktype()==null?"疾病特征表征":taskInfo.getTasktype());
        task.setTaskname(taskInfo.getTaskName()==null?UserThreadLocal.get().getUsername()+"_疾病特征表征_"+ LocalDate.now().toString():taskInfo.getTaskName());
        task.setModel(model);

        String label = categoryMapper.getParentLabelByLabel(tableName);
        task.setDisease(label);
        task.setRemark(taskInfo.getTips());
        task.setModel("无");
        task.setUserid(UserThreadLocal.get().getUid());
        taskMapper.insert(task);
    }

}

UserLogServiceImpl

这段代码是一个基于Spring框架的Java服务实现类。它位于`com.cqupt.software_1.service.impl`包中。首先,它导入了一些必要的类和接口,包括`ServiceImpl`类、`UserLog`实体类、`UserLogMapper`接口以及`UserLogService`接口。

在类声明上方有一段注释,指出了该类的作者、描述以及创建日期。

接着,类名为`UserLogServiceImpl`,它继承了`ServiceImpl<UserLogMapper, UserLog>`类,并实现了`UserLogService`接口。这意味着它提供了对数据库表`user_log`的操作。

在类中,通过`@Autowired`注解将`UserLogMapper`接口的实例注入到了`userLogMapper`变量中。

`insertUserLog`方法是该类的一个重要方法,它接受一个`UserLog`对象作为参数,并将其插入到数据库中。在方法内部,通过`userLogMapper`调用`insert`方法实现插入操作,然后将插入结果返回。

总体来说,这个类是用来处理`user_log`表的数据库操作的实现类,其中最重要的方法是`insertUserLog`,用于插入用户日志信息。
package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.entity.UserLog;
import com.cqupt.software_1.mapper.UserLogMapper;
import com.cqupt.software_1.service.UserLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
* @author hp
* @description 针对表【user_log】的数据库操作Service实现
* @createDate 2023-09-07 14:34:13
*/
@Service
public class UserLogServiceImpl extends ServiceImpl<UserLogMapper, UserLog>
    implements UserLogService {

    @Autowired
    private UserLogMapper userLogMapper;

    @Override
    public int insertUserLog(UserLog userLog) {

        int insert = userLogMapper.insert(userLog);
        return insert;
    }
}

UserServiceImpl

这段代码是另一个基于Spring框架的Java服务实现类,位于`com.cqupt.software_1.service.impl`包中。它也导入了一些必要的类和接口,包括`ServiceImpl`类、`User`实体类、`UserMapper`接口、`UserService`接口以及一些自定义的数据传输对象。

在类声明上方有一段注释,指出了该类的作者、描述以及创建日期。

类名为`UserServiceImpl`,它同样继承了`ServiceImpl<UserMapper, User>`类,并实现了`UserService`接口,用于对数据库表`user`进行操作。

在类中,通过`@Autowired`注解将`UserMapper`接口的实例注入到了`userMapper`变量中。

接下来是一系列方法的实现:

- `getAll`方法返回了所有用户的列表。
- `getUserByName`方法根据用户名获取用户信息。
- `getUserById`方法根据用户ID获取用户信息。
- `saveUser`方法用于保存用户信息。
- `getAllUserInfo`方法用于分页获取所有用户的信息。
- `updateStatusById`方法用于更新用户状态。
- `removeUserById`方法用于删除用户。
- `insertUser`方法用于插入用户信息。
- `getUserPage`方法用于分页获取用户信息,返回包含总数和数据列表的Map。
- `updatePwd`方法用于更新用户密码。
- `querUser`方法用于查询所有用户信息。
- 还有一些管理员端数据管理相关的方法,如`addTableSize`用于增加用户表格大小,`minusTableSize`用于减少用户表格大小,以及`selectByUid`用于根据用户ID查询用户信息。

总体来说,这个类是用于处理用户表`user`的数据库操作的实现类,包含了各种用户信息管理和数据管理的方法。
package com.cqupt.software_1.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.software_1.entity.User;
import com.cqupt.software_1.service.UserService;
import com.cqupt.software_1.mapper.UserMapper;
import com.cqupt.software_1.vo.InsertUserVo;
import com.cqupt.software_1.vo.UserPwd;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author hp
* @description 针对表【user】的数据库操作Service实现
* @createDate 2023-05-16 16:44:39
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<User> getAll() {
        List<User> users = userMapper.selectList(null);
        return users;
    }

    @Override
    public User getUserByName(String userName) {
        User user = userMapper.getUerByUserName(userName);
        return user;
    }

    @Override
    public User getUserById(Integer id) {
        return userMapper.getUserById(id);
    }

    @Override
    public void saveUser(User user) {
        userMapper.saveUser(user);
    }

    @Override
    public Page<User> getAllUserInfo(int pageNum  , int pageSize) {

        Page<User> page = new Page<>(pageNum, pageSize);
       return userMapper.selectPage(page,null);

    }

    @Override
    public boolean updateStatusById(Integer uid, Integer  role ,double uploadSize , String status) {

       boolean b =  userMapper.updateStatusById(uid, role ,uploadSize,  status);
        if ( b )  return true;
        return false;
    }

    @Override
    public boolean removeUserById(Integer uid) {
       userMapper.removeUserById(uid);
        return true;
    }


    @Override
    public boolean insertUser(InsertUserVo user) {

        userMapper.insertUser(user);
        return false;
    }




    public Map<String, Object> getUserPage(int pageNum, int pageSize) {
        int offset = (pageNum - 1) * pageSize;
        List<User> userList = userMapper.selectUserPage(offset, pageSize);
        int total = userMapper.countUsers();

        Map<String, Object> result = new HashMap<>();
        result.put("total", total);
        result.put("data", userList);
        return result;
    }


    @Override
    public boolean updatePwd(UserPwd user) {

        userMapper.updatePwd(user);

        return false;
    }

    @Override
    public List<User> querUser() {

        List<User> users = userMapper.selectList(null);
        return users;
    }



    //    下面方法是管理员端-数据管理新增
    @Override
    public void addTableSize(String uid,float tableSize) {
        userMapper.addTableSize(Integer.parseInt(uid), tableSize);
    }

    @Override
    public void minusTableSize(String uid, float tableSize) {

        userMapper.minusTableSize(Integer.parseInt(uid), tableSize);
    }

    @Override
    public User selectByUid(String uid) {
        return userMapper.selectByUid(Integer.parseInt(uid));
    }
}





  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值