springboot+vue3+antdesignvue实现文件的导入导出javaguns框架

发布时间:2024年01月16日

1.技术要点

mybatisplus;vue3,springboot2;javaguns框架

2实现导入功能

后端实现:

①controller层

@RestController
@ApiResource(name = "项目评价")
public class ProjectAppraisalController {

 /**
     * 导入excel表数据
     * @param file
     * @return
     */
    @PostResource(name = "数据导入" ,path = "/projectAppraisal/import")
    public ResponseData<?> importData(MultipartFile file){
        return new SuccessResponseData<>(projectAppraisalService.importData(file));

    }


}
  • 这段代码是一个使用了Spring Boot框架的控制器方法。它使用了@PostResource注解来定义一个POST请求的资源,并指定了资源的名称为"数据导入",路径为"/awardPatent/import"。

    该方法接收一个MultipartFile类型的文件作为参数,表示要导入的文件。MultipartFile是Spring框架提供的一个类,用于处理文件上传。

    在方法体内,调用了awardPatentService.importData(file)来处理文件导入的逻辑。awardPatentService是一个服务类的实例,通过调用其importData方法来处理文件导入操作。

    最后,将导入操作的结果封装在一个SuccessResponseData对象中,并作为响应返回。SuccessResponseData是一个自定义的响应数据类,表示成功的响应,并包含了导入操作的结果数据。

    总结来说,这段代码定义了一个用于处理文件导入的控制器方法。它接收一个文件作为参数,调用服务类的方法来处理文件导入操作,并将结果封装在响应数据中返回。具体的实现逻辑需要根据代码的上下文来确定。

②service层:

public interface ProjectAppraisalService extends IService<ProjectAppraisal> {

ResponseData<?> importData(MultipartFile file);


}
  • ResponseData<?> importData(MultipartFile file) 是一个方法声明,其中 ResponseData<?> 表示返回类型为 ResponseData,而 MultipartFile file 是该方法的参数,表示接收一个文件作为输入。

    具体来说,这个方法可能是用于处理文件导入的逻辑。它接收一个 MultipartFile 类型的文件作为参数,表示要导入的文件。MultipartFile 是Spring框架提供的一个类,用于处理文件上传。

    ResponseData 是一个自定义的响应数据类,可能包含了请求的处理结果和相关的数据。<?> 表示泛型,表示可以是任意类型的数据。

    这个方法的作用可能是将接收到的文件进行处理,然后返回一个包含处理结果和相关数据的 ResponseData 对象。

    总结来说,ResponseData<?> importData(MultipartFile file) 是一个方法声明,用于处理文件导入操作。它接收一个文件作为参数,并返回一个包含处理结果和相关数据的 ResponseData 对象。具体的实现逻辑需要根据代码的上下文来确定。

③实体层:

@TableName("project_appraisal")
@Data
@ExcelIgnoreUnannotated
@EqualsAndHashCode(callSuper = true)
public class ProjectAppraisal extends BaseEntity {

    @ExcelProperty(value = "序号",index = 0)
    @TableField(exist = false)
    private Integer serialNum;

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    @ChineseDescription("主键")
    private Long id;

    /**
     * 流程ID
     */
    @TableField("process_id")
    @ChineseDescription("流程ID")
    private String processId;

    /**
     * 管理编号
     */
    @TableField("manage_code")
    @ChineseDescription("管理编号")
    private String manageCode;

    /**
     * 案件状态
     */
    @TableField("status")
    @ChineseDescription("案件状态")
    private String status;

    @TableField(exist = false)
    @ChineseDescription("工作流相关")
    private WorkflowModel workflowModel;

    /**
     * 项目名称
     */
    @TableField("project_name")
    @ExcelProperty(value = "项目名称",index = 1)
    @ChineseDescription("项目名称")
    private String projectName;

    /**
     * 投产单位
     */
    @TableField("production_unit")
    @ChineseDescription("投产单位")
    @ExcelProperty(value = "投产单位",index = 2)
    private String productionUnit;

    /**
     * 评价单位
     */
    @TableField("evaluation_unit")
    @ChineseDescription("评价单位")
    @ExcelProperty(value = "评价单位",index = 3)
    private String evaluationUnit;

    /**
     * 评价方式
     */
    @TableField("evaluation_method")
    @ChineseDescription("评价方式")
    @ExcelProperty(value = "评价方式",index = 4)
    private String evaluationMethod;

    /**
     * 评价时间
     */
    @DateTimeFormat("yyyy-MM-dd")
    @TableField("evaluation_time")
    @ChineseDescription("评价时间")
    @ExcelProperty(value = "评价时间",index = 5)
    private Date evaluationTime;

    /**
     * 评价结果
     */
    @TableField("evaluation_result")
    @ChineseDescription("评价结果")
    @ExcelProperty(value = "评价结果",index = 6)
    private String evaluationResult;

    /**
     * 附件
     */
    @TableField("attachment")
    @ChineseDescription("附件")
    private String attachment;

}

④serviceImpl

@Service
public class ProjectAppraisalServiceImpl extends ServiceImpl<ProjectAppraisalMapper, ProjectAppraisal> implements ProjectAppraisalService {

@Override
    public ResponseData<?> importData(MultipartFile file) {

        if (file != null){
            List<ProjectAppraisal>  projectAppraisalList = null;

            try {
                //创建监听器
                GeneralListener<ProjectAppraisal> listener = new GeneralListener<>();
                //执行Excel的读取,read方法需要三个参数 ,文件(流) 大的Class实例  监听器
                EasyExcel.read(file.getInputStream() , ProjectAppraisal.class , listener).sheet().doRead();
                //获取监听器的数据
                projectAppraisalList = listener.getList();

            } catch (IOException e) {
                return  new ErrorResponseData<>("F0002" ,"数据格式有误");
            }
            //处理表头的第一行数据、
            projectAppraisalList.stream().filter(item -> Pattern.matches("//d+", String.valueOf(item.getSerialNum())));

            //添加表中数据
            projectAppraisalList.forEach(projectAppraisal -> {
                String projectName = projectAppraisal.getProjectName();
                String productionUnit = projectAppraisal.getProductionUnit();
                LambdaQueryWrapper<ProjectAppraisal> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(ProjectAppraisal::getProjectName ,projectName);
                wrapper.eq(ProjectAppraisal::getProductionUnit,productionUnit);
                List<ProjectAppraisal> projectAppraisals = projectAppraisalService.list(wrapper);
                //如果不存在,加入
                if (projectAppraisals.isEmpty()){
                    projectAppraisal.setStatus("完成");
                    projectAppraisal.setCreateTime(new Date());
                    projectAppraisalService.save(projectAppraisal);
                }

            });
            return  new SuccessResponseData<>("00000" ,"上传成功" ,null);

        }else {
            return new ErrorResponseData<>("F0003" ,"上传失败");
        }

    }

}

这段代码是一个实现了importData方法的具体实现。该方法接收一个MultipartFile类型的文件作为参数,并返回一个ResponseData<?>类型的响应数据。

在方法体内,首先判断传入的文件是否为空。如果不为空,则继续执行文件导入的逻辑。

在文件导入的逻辑中,首先创建一个GeneralListener<ProjectAppraisal>类型的监听器对象。然后使用EasyExcel库的read方法,传入文件流、ProjectAppraisal类的实例和监听器对象,来读取Excel文件的内容。通过监听器对象获取读取到的数据,将其赋值给projectAppraisalList变量。

接下来,对projectAppraisalList进行处理。首先使用stream()方法和filter()方法,过滤出表头的第一行数据。然后使用forEach()方法遍历projectAppraisalList,对每个ProjectAppraisal对象进行处理。根据项目名称和生产单位查询数据库中是否存在相同的记录,如果不存在,则将该记录保存到数据库中。

最后,根据处理结果返回相应的响应数据。如果文件上传成功,返回一个SuccessResponseData对象,包含成功的响应码和消息。如果文件上传失败,返回一个ErrorResponseData对象,包含失败的响应码和消息

3.前端代码:

<template>
  <div class="ele-body">
    <!-- 搜索表单 -->
    <div class="block-interval">
      <a-card :bordered="false">
        <a-form :model="where">
          <a-row :gutter="20">
            <a-col>
              <a-form-item label="项目名称:">
                <a-input v-model:value.trim="where.projectName" placeholder="请输入项目名称" allow-clear />
              </a-form-item>
            </a-col>
            <a-col>
              <a-form-item label="评价单位:">
                <a-input v-model:value.trim="where.evaluationUnit" placeholder="请输入评价单位" allow-clear />
              </a-form-item>
            </a-col>
            <a-col>
              <a-space class="ele-text-center">
                <a-button type="primary" @click="reload">查询</a-button>
                <a-button @click="reset">重置</a-button>
              </a-space>
            </a-col>
          </a-row>
        </a-form>
      </a-card>
    </div>

    <!-- 表格 -->
    <div>
      <a-card :bordered="false" class="table-height">
        <ele-pro-table
          ref="table"
          row-key="id"
          :datasource="datasource"
          :columns="columns"
          :where="where"
          v-model:selection="selection"
          :scroll="{ x: 'max-content' }"
        >
          <!-- table上边工具栏 -->
          <template #toolbar>
            <a-space>
              <a-button type="primary" @click="openEdit()" v-permission="'PROJECTEVALUATION_ADD_BUTTON'">
                <template #icon>
                  <plus-outlined />
                </template>
                <span>新建</span>
              </a-button>
              <a-button class="export-excel-button" type="primary" @click="exportExcel" v-permission="'PROJECTEVALUATION_EXPORT_BUTTON'">
                <template #icon>
                  <download-outlined />
                </template>
                <span>导出</span>
              </a-button>
              <a-button @click="showImport()" v-if="hasRole()">
                <upload-outlined />
                导入
              </a-button>
            </a-space>
            <a-modal v-model:visible="isShowImport" title="导入数据" :footer="null">
              <a-upload-dragger
                ref="fileImport"
                v-model:file-list="fileList"
                name="file"
                :multiple="true"
                :accept="importAccept"
                :action="baseUrl + '/projectAppraisal/import'"
                :headers="headers"
                @change="handleChange"
                @reject="handleReject"
                :before-upload="beforeImport"
              >
                <p class="ant-upload-drag-icon">
                  <inbox-outlined></inbox-outlined>
                </p>
                <p class="ant-upload-text">点击选择文件或拖拽文件到此处</p>
              </a-upload-dragger>

              <p style="margin-top: 20px; text-align: center; color: #ccc">
                请上传Excel格式文件,<a href="/static/template/projectappraisal.xlsx" download="项目评价数据导入模板.xlsx">下载模板</a>
              </p>
            </a-modal>
          </template>

          <template #bodyCell="{ column, record }">
            <template v-if="column.key === 'ended'">
              <a-tag color="green" v-if="(record.workflowModel ? record.workflowModel.isEnd : '') === 1">是</a-tag>
              <a-tag color="red" v-else> 否</a-tag>
            </template>

            <!-- 当前节点 -->
            <template v-if="column.key === 'active'">
              <span v-if="record.workflowModel">
                <a @click="tracking(record)" v-if="record.workflowModel.isEnd === 1">结束</a>
                <a @click="tracking(record)" v-else>{{ record.workflowModel.actName }}</a>
              </span>
              <span v-else> - </span>
            </template>

            <!-- 申报结果 -->
            <template v-if="column.key === 'evaluationResult'">
              <span v-if="record.evaluationResult">
                <a-tag color="green" v-if="record.evaluationResult === '是'">通过</a-tag>
                <a-tag color="red" v-else>未通过</a-tag>
              </span>
              <span v-else> - </span>
            </template>
            <!-- table操作栏按钮 -->
            <template v-if="column.key === 'action'">
              <a-space>
                <a @click="openDetail(record)">查看</a>
                <a-space
                  v-permission="'PROJECTEVALUATION_UPDATE_BUTTON'"
                  v-if="(record.workflowModel && record.workflowModel.isEnd) !== 1 || hasRole()"
                >
                  <a-divider type="vertical" />
                  <a @click="openEdit(record)">修改</a>
                </a-space>
                <a-space v-permission="'PROJECTEVALUATION_UPDATE_BUTTON'" v-if="record.status === '完成' && !record.evaluationResult">
                  <a-divider type="vertical" />
                  <a-popconfirm
                    title="该记录是否通过申报?"
                    ok-text="通过"
                    cancel-text="不通过"
                    @confirm="resultFun(record, '是')"
                    @cancel="resultFun(record, '否')"
                  >
                    <a>结果</a>
                  </a-popconfirm>
                </a-space>
                <a-space v-permission="'PROJECTEVALUATION_DEL_BUTTON'" v-if="record.status === '暂存' || hasRole()">
                  <a-divider type="vertical" />
                  <a-popconfirm title="确定要删除此记录吗?" @confirm="remove(record)">
                    <a class="ele-text-danger">删除</a>
                  </a-popconfirm>
                </a-space>
              </a-space>
            </template>
          </template>
        </ele-pro-table>
      </a-card>
    </div>
    <common-tracking ref="tracking" />
    <!-- 编辑弹窗 -->
    <projectAppraisal-edit v-model:visible="showEdit" :data="current" @done="reload" />
  </div>
</template>
<script>
import { message } from 'ant-design-vue';
import { PlusOutlined } from '@ant-design/icons-vue';
import ProjectAppraisalEdit from './project_appraisal_edit.vue';
import { ProjectAppraisalApi } from '@/api/bohua/ProjectAppraisalApi';
import CommonTracking from '@/views/workflow/tracking/common-tracking.vue';
import { useUserStore } from '@/store/modules/user';
import { hasRole } from '@/utils/permission';
import { toDateString } from 'ele-admin-pro';
import { ref } from 'vue';
import { getToken } from '@/utils/token-util';

export default {
  name: 'ProjectAppraisal',
  components: {
    PlusOutlined,
    ProjectAppraisalEdit,
    CommonTracking
  },
  async mounted() {},
  data() {
    return {
      isShowImport: ref(false),
      fileList: [],
      importAccept: ['.xlsx', '.xls'],
      baseUrl: import.meta.env.VITE_API_URL,
      // 表格列配置
      columns: [
        {
          key: 'index',
          title: '序号',
          align: 'center',
          width: 48,
          customRender: ({ index }) => this.$refs.table.tableIndex + index
        },
        {
          title: '项目名称',
          dataIndex: 'projectName'
        },
        {
          title: '投产单位',
          dataIndex: 'productionUnit'
        },
        {
          title: '评价单位',
          dataIndex: 'evaluationUnit'
        },
        {
          title: '评价方式',
          dataIndex: 'evaluationMethod'
        },
        {
          title: '评价时间',
          dataIndex: 'evaluationTime',
          customRender: ({ text }) => {
            return !text ? '-' : toDateString(text, 'yyyy-MM-dd');
          }
        },
        {
          title: '评价结果',
          dataIndex: 'evaluationResult',
          key: 'evaluationResult'
        },
        {
          ellipsis: true,
          resizable: true,
          title: '审批节点',
          dataIndex: 'workflowModel.actName',
          key: 'active'
        },
        {
          title: '流程结束',
          dataIndex: 'workflowModel.isEnd',
          key: 'ended'
        },
        {
          title: '操作',
          key: 'action',
          width: 180,
          fixed: 'right',
          align: 'center'
        }
      ],
      // 表格搜索条件
      where: {},
      // 表格选中数据
      selection: [],
      // 当前编辑数据
      current: null,
      // 是否显示编辑弹窗
      showEdit: false,
      // 是否查看
      isDetail: false,
      headers: {
        authorization: getToken()
      }
    };
  },
  methods: {
    showImport() {
      this.isShowImport = true;
    },
    isAllowedFile(fileName, allowedExtensions) {
      const fileExtension = '.' + fileName.split('.').pop().toLowerCase();
      return allowedExtensions.includes(fileExtension);
    },

    hasRole() {
      return hasRole('superAdmin');
    },
    handleChange(info) {
      if (!this.isAllowedFile(info.file.name, this.importAccept) || info.file.status !== 'uploading') {
        // 如果文件格式支持或不在上传
        if (info.file.status == 'done' || info.file.status == 'error') {
          const success = info.file?.response?.success || false;
          const msg = info.file?.response?.message || '';
          if (!success || info.file.status == 'error') {
            message.error(info.file.name + '导入失败!' + msg);
          } else if (info.file.status == 'done') {
            message.success(info.file.name + '导入成功!');
          }
        }
        //console.log('移除上传完成、上传错误或不允许上传的文件');
        this.fileList = info.fileList.filter(file => file.uid !== info.file.uid);
      }
    },

    handleReject() {
      message.error('上传文件格式不正确!');
    },
    beforeImport(file) {
      if (!this.isAllowedFile(file.name, this.importAccept)) {
        message.error('上传文件只能是' + this.importAccept.join('、') + '格式!');
        return false; // 阻止上传
      }
      return true; // 允许上传
    },
    /**
     * 打开追踪界面
     *
     *
     */
    tracking(row) {
      this.$refs.tracking.tracking(row.processId);
    },
    /**
     * 搜索按钮
     *
     * 
     */
    reload() {
      this.selection = [];
      this.$refs.table.reload({ page: 1 });
    },

    /**
     * 重置搜索
     *
     * 
     */
    reset() {
      this.reloadPage = 1;
      this.where.projectName = '';
      this.where.evaluationUnit = '';
      this.$nextTick(() => {
        this.reload();
      });
    },

    /**
     * 删除
     *
     * @author zhihui
     * @date 2023/12/26 09:38
     */
    async remove(row) {
      const result = await ProjectAppraisalApi.delete({ id: row.id });
      message.success(result.message);
      this.reload();
    },

    /**
     * 打开新增或编辑弹窗
     *
     * 
     */
    openEdit(row) {
      if (row) this.current = row;
      else {
        //新建时,默认企业名称为用户所在单位
        const loginUserInfo = useUserStore().info;
        this.current = { companyName: loginUserInfo.orgName };
      }
      this.showEdit = true;
      this.isDetail = false;
    },
    openDetail(row) {
      this.current = row;
      this.showEdit = true;
      this.isDetail = true;
    },
    /**
     * 获取表格数据
     *
     * 
     */
    datasource({ page, limit, where, orders }) {
      return ProjectAppraisalApi.findPage({ ...where, ...orders, pageNo: page, pageSize: limit });
    },
    resultFun(record, i) {
      ProjectAppraisalApi.edit({ id: record.id, evaluationResult: i }).then(result => {
        message.success(result.message);
        this.reload();
      });
    },
    exportExcel() {
      ProjectAppraisalApi.exportExcel(this.where);
    }
  }
};
</script>

文章来源:https://blog.csdn.net/2301_76604664/article/details/135623284
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。