尚医通-数据字典-EasyExcel-导入 导出(十四)

news2024/10/4 19:24:11

目录:

(1)EasyExcel-写操作

(2)EasyExcel-读操作

(3)后台系统-数据字典-导出

(4) 后台系统-数据字典-导入


(1)EasyExcel-写操作

往数据字典里面写数据,可以通过先把数据写到Excel表格里面,然后再导入进去,需要用到第三方技术来实现,操作excel表格

  1. EasyExcel介绍

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便。

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。

文档地址:https://alibaba-easyexcel.github.io/index.html

github地址:GitHub - alibaba/easyexcel: 快速、简洁、解决大文件内存溢出的java处理Excel工具

首先在service_cmn的pom文件下引入依赖:

 

演示一下,创建实体类:

 

UserData:和:

package com.atguigu.easyexcel;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

@Data  //lombok插件注解生成getset方法
public class UserData {
    @ExcelProperty("用户编号") //表格标题注解
    private int uid;

    @ExcelProperty("用户名称")
    private String username;
}

 TestWrite:

package com.atguigu.easyexcel;

import com.alibaba.excel.EasyExcel;

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

public class TestWrite {
    public static void main(String[] args) {
        //设置excel文件的路径和文件名称
        String filename="E:\\excel\\01.xlsx";//路径

        //构建数据的list集合
        List<UserData> list=new ArrayList();
        for (int i=0;i<10;i++){
            UserData data=new UserData();
            data.setUid(i);
            data.setUsername("Lucy"+i);
            list.add(data);
        }

        //调用方法实现写操作
        EasyExcel.write(filename,UserData.class).sheet("用户信息")
                .doWrite(list);
    }
}

E盘创建一个文件夹excel:

 

 运行:

 目录下多了一个文件:

打开文件:

 

(2)EasyExcel-读操作

 写一个实体类:

UserData:

package com.atguigu.easyexcel;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

@Data  //lombok插件注解生成getset方法
public class UserData {
    @ExcelProperty(value = "用户编号",index = 0) //表格标题注解
    private int uid;

    @ExcelProperty(value = "用户名称",index = 1)
    private String username;
}

创建一个监听器,实现一行一行的读:

ExcelListener:

package com.atguigu.easyexcel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;

import java.util.Map;

public class ExcelListener extends AnalysisEventListener<UserData> {
    //一行一行的读取excel内容,从第二行读取
    @Override
    public void invoke(UserData userData, AnalysisContext analysisContext) {
        System.out.println(userData);
    }

    //读取表头内容
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        System.out.println("表头信息"+headMap);
    }
    //读取之后执行
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }
}

 TestRead:

package com.atguigu.easyexcel;

import com.alibaba.excel.EasyExcel;

public class TestRead {
    public static void main(String[] args) {
        //读取文件的路径
        String filename="E:\\excel\\01.xlsx";//路径

        //调用方法实现读取操作
        EasyExcel.read(filename,UserData.class,new ExcelListener()).sheet().doRead();
    }
}

运行:

(3)后台系统-数据字典-导出

 把下面的数据写入到一个excel表中去:

 

在DicController中添加接口:方法:

//导出数据字典接口
    @GetMapping("exportData")
    public void exportDict(HttpServletResponse response) {
        dictService.exportDictData(response);
    }

 DicService:接口:

写这个方法:

package com.atguigu.yygh.cmn.service;

import com.atguigu.yygh.model.cmn.Dict;
import com.baomidou.mybatisplus.extension.service.IService;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

public interface DictService extends IService<Dict> {
    //根据数据id查询子数据列表
    List<Dict> findChlidData(Long id);

    //导出数据字典接口
    void exportDictData(HttpServletResponse response);
}

实现类:DictServiceImpl:

//导出数据字典接口
    @Override
    public void exportDictData(HttpServletResponse response) {
        //设置下载
        response.setContentType("application/vnd.ms-excel");//设置类型
        response.setCharacterEncoding("utf-8");//设置编码
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = "dict";//名字
        response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");//头信息,以下载方式打开

        //查询数据库
        List<Dict> dictList = baseMapper.selectList(null);

        //将Dict转--DictEeVo
        List<DictEeVo> dictEeVoList=new ArrayList<>();
        for (Dict dict:dictList){
            DictEeVo dictEeVo=new DictEeVo();
            //dictEeVo.setId(dict.getId());用下面替换
            BeanUtils.copyProperties(dict,dictEeVo);
            dictEeVoList.add(dictEeVo);//放入集合
        }

        //调用方法进行写操作
        try {
            EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("dict").doWrite(dictEeVoList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

实体类我们原来创建好了:

 

package com.atguigu.yygh.vo.cmn;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

/**
 * <p>
 * Dict
 * </p>
 *
 * @author qy
 */
@Data
public class DictEeVo {

	@ExcelProperty(value = "id" ,index = 0)
	private Long id;

	@ExcelProperty(value = "上级id" ,index = 1)
	private Long parentId;

	@ExcelProperty(value = "名称" ,index = 2)
	private String name;

	@ExcelProperty(value = "值" ,index = 3)
	private String value;

	@ExcelProperty(value = "编码" ,index = 4)
	private String dictCode;

}

 

 前端:

在dict-list.vue:

加导出按钮:

 点击导出:

 

(4) 后台系统-数据字典-导入

在DictController中添加接口方法:

 

package com.atguigu.yygh.cmn.controller;

import com.atguigu.yygh.cmn.service.DictService;
import com.atguigu.yygh.common.result.Result;
import com.atguigu.yygh.model.cmn.Dict;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
@Api(tags = "数据字典接口")  //swagger中的提示注解
@RestController
@RequestMapping("/admin/cmn/dict")
@CrossOrigin         //跨域访问注解
public class DictController {

    @Autowired
    private DictService dictService;


    //根据数据id查询子数据列表
    @ApiOperation(value = "根据数据id查询子数据列表")
    @GetMapping("findChildData/{id}")
    public Result findChildData(@PathVariable Long id) {
        List<Dict> list = dictService.findChlidData(id);
        return Result.ok(list);
    }

    //导出数据字典接口
    @GetMapping("exportData")
    public void exportDict(HttpServletResponse response) {
        dictService.exportDictData(response);
    }

    //导入数据字典
    @PostMapping("importData")
    public Result importDict(MultipartFile file) {
        dictService.importDictData(file);
        return Result.ok();
    }

}

 DictService:接口添加这个方法:

package com.atguigu.yygh.cmn.service;

import com.atguigu.yygh.model.cmn.Dict;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

public interface DictService extends IService<Dict> {
    //根据数据id查询子数据列表
    List<Dict> findChlidData(Long id);

    //导出数据字典接口
    void exportDictData(HttpServletResponse response);

    //导入数据字典
    void importDictData(MultipartFile file);
}

  DictServiceImpl:实现类:实现这个方法:

 

package com.atguigu.yygh.cmn.service.impl;

import com.alibaba.excel.EasyExcel;
import com.atguigu.yygh.cmn.listener.DictListener;
import com.atguigu.yygh.cmn.mapper.DictMapper;
import com.atguigu.yygh.cmn.service.DictService;
import com.atguigu.yygh.model.cmn.Dict;
import com.atguigu.yygh.vo.cmn.DictEeVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {


    //根据数据id查询子数据列表
    @Override
    public List<Dict> findChlidData(Long id) {
        QueryWrapper<Dict> wrapper=new QueryWrapper<>();
        wrapper.eq("parent_id",id);
        List<Dict> dictList = baseMapper.selectList(wrapper);
        //向dictList集合中的每个Dict对象设置hasChildren属性
        for (Dict dict:dictList){
            Long dictId = dict.getId();
            boolean ischild = this.isChildren(dictId);//调用下面方法获取是否有子节点
            dict.setHasChildren(ischild);//设置属性
        }
        return dictList;
    }

    //导出数据字典接口
    @Override
    public void exportDictData(HttpServletResponse response) {
        //设置下载
        response.setContentType("application/vnd.ms-excel");//设置类型
        response.setCharacterEncoding("utf-8");//设置编码
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = "dict";//名字
        response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");//头信息,以下载方式打开



        //查询数据库
        List<Dict> dictList = baseMapper.selectList(null);

        //将Dict转--DictEeVo
        List<DictEeVo> dictEeVoList=new ArrayList<>();
        for (Dict dict:dictList){
            DictEeVo dictEeVo=new DictEeVo();
            //dictEeVo.setId(dict.getId());用下面替换
            BeanUtils.copyProperties(dict,dictEeVo);
            dictEeVoList.add(dictEeVo);//放入集合
        }

        //调用方法进行写操作
        try {
            EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("dict").doWrite(dictEeVoList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //导入数据字典
    @Override
    public void importDictData(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(),DictEeVo.class,new DictListener(baseMapper)).sheet().doRead();

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

    //判断id下面是否有字节点
    private boolean isChildren(Long id){
        QueryWrapper<Dict> wrapper=new QueryWrapper<>();
        wrapper.eq("parent_id",id);
        Integer count = baseMapper.selectCount(wrapper);

        return count>0;
    }
}

创建监听器:

DictListener:

package com.atguigu.yygh.cmn.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.atguigu.yygh.cmn.mapper.DictMapper;
import com.atguigu.yygh.model.cmn.Dict;
import com.atguigu.yygh.vo.cmn.DictEeVo;
import org.springframework.beans.BeanUtils;

public class DictListener extends AnalysisEventListener<DictEeVo> {

    //引入dictMapper
    private DictMapper dictMapper;

    public DictListener(DictMapper dictMapper) {
        this.dictMapper = dictMapper;
    }


    //一行一行的读取excel内容,从第二行读取
    @Override
    public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) {
        //调用方法添加数据库
        //将dictEeVo转换为Dict
        Dict dict=new Dict();
        //使用工具类转换
        BeanUtils.copyProperties(dictEeVo,dict);

        dictMapper.insert(dict);
    }

    //读取之后执行
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }
}

 前端:

在list.vue中加按钮:

 添加导入弹出框:

 

 

 

<template>
<div class="app-container">
        <!-- 导出按钮 -->
          <div class="el-toolbar">
           <div class="el-toolbar-body" style="justify-content: flex-start;">
            <a href="http://localhost:8202/admin/cmn/dict/exportData" target="_blank">
                <el-button type="text" @click="exportData"><i class="fa fa-plus"/> 导出</el-button>
            </a>
            <!-- 导入按钮 -->
            <el-button type="text" @click="importData"><i class="fa fa-plus"/> 导入</el-button>
          </div>
         </div>

        <el-table
        :data="list"
        :load="getChildrens"
        :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
        style="width: 100%"
        row-key="id"
        border
        lazy >
            <el-table-column label="名称" width="230" align="left">
            <template slot-scope="scope">
            <span>{{ scope.row.name }}</span>
            </template>
            </el-table-column>

            <el-table-column label="编码" width="220">
            <template slot-scope="{row}">
                    {{ row.dictCode }}
            </template>
            </el-table-column>
            <el-table-column label="值" width="230" align="left">
            <template slot-scope="scope">
            <span>{{ scope.row.value }}</span>
            </template>
            </el-table-column>
            <el-table-column label="创建时间" align="center">
            <template slot-scope="scope">
            <span>{{ scope.row.createTime }}</span>
            </template>
            </el-table-column>
        </el-table>
<!-- 导入弹出框 -->
    <el-dialog title="导入" :visible.sync="dialogImportVisible" width="480px">
        <el-form label-position="right" label-width="170px">
         <el-form-item label="文件">

          <el-upload
          :multiple="false"
          :on-success="onUploadSuccess"
          :action="'http://localhost:8202/admin/cmn/dict/importData'"
          class="upload-demo">
          <el-button size="small" type="primary">点击上传</el-button>
          <div slot="tip" class="el-upload__tip">只能上传excel.xls文件,且不超过500kb</div>
          </el-upload>

          </el-form-item>

         </el-form>
        <div slot="footer" class="dialog-footer">

         <el-button @click="dialogImportVisible = false">
          取消
         </el-button>
        </div>
    </el-dialog>

    </div>

</template>
<script>

//引入接口定义的js文件
import dict from '@/api/dict'

export default {
    data() {//定义变量和初始值
        return {
            list: [],//数据字典列表数组
            dialogImportVisible:false,//设置弹框是否弹出
        }
    },
    created() {//页面初始化之前执行
        this.getDictList(1)
    },
    methods: {//具体的方法
        getDictList(id) {
            dict.dictList(id)
                .then(response => {
                  this.list=response.data  //往数组里赋值
               })
        },
        //查询层级的方法
        getChildrens(tree, treeNode, resolve) {
            //第一级下面的查询
            dict.dictList(tree.id).then(response => {
                resolve(response.data)
            })
        },
        //导出数据字典
        exportData() {
            //调用导出接口
            window.location.href="http://localhost:8202/admin/cmn/dict/exportData"
        },
        //导入数据字典方法
        importData() {
			this.dialogImportVisible = true  //显示弹出框
		},
		//上传成功调用方法,
		onUploadSuccess(response, file) {
			this.$message.info('上传成功')
			//关闭弹框
			this.dialogImportVisible = false
			//刷新页面
			this.getDictList(1)
		},
    }
    
}
</script>

 

点击导入:

 

 提前准备好:excel数据

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/126298.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

家用摄像头选择(户内外)

不知道摄像头怎么选&#xff1f;看下面几篇就够了。 1、户外监控摄像头&#xff0c;哪个品牌的比较好&#xff1f; - 知乎 2、【室外篇】家用监控摄像头选购要素及不同场景下高性价比监控摄像头推荐 - 知乎 3、家用摄像头选什么牌子的好? - 知乎 优先选焦距 IP防水防尘&…

超宽带(UWB)开发板BU0/DW1000性能测试

简介 本实验目的是测试NodeMCU-BU01开发板测距的性能。 BU01是基于Decawave的DW1000设计的超宽带&#xff08;UWB&#xff09;收发器模组。BU01可以用于双向测距或TWR定位系统中&#xff0c;定位精度可达到10厘米&#xff0c;并支持高达6.8 Mbps的数据速率。 UWB技术是一种使…

“ 1天投200次简历,依旧石沉大海 ” 这届年轻人的“求职焦虑”,如何缓解?

最近在新闻上看到这样一则热议事件&#xff1a;“1天投200次简历”&#xff1f;多方发力&#xff0c;缓解应届生“求职焦虑”。 教育部公布的数据显示&#xff0c;我国2022届全国普通高校毕业生数量为1076万人&#xff0c;而2023届预计达1158万人&#xff0c;同比将增加82万人…

通过webpack配置【程序打包时间】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、webpack打包定义全局常量二、将全局常量设置为当前时间三、在console中输出BUILDTIME前言 大家都是做项目研发的&#xff0c;“打包”、“提测”、“发版”…

低代码-零代码基础教育结合场景

在此次大会上&#xff0c;杭州市学军小学教育集团总校长张军林受邀出席。作为将低代码与校园教学管理成功结合运用的一所数字化小学&#xff0c;校长张军林在会上分享了他的数智化管理思想&#xff0c;并发布了学军小学智慧校园系统—学军大脑2.0。 “学军大脑2.0是基于钉钉宜…

ES6-ES11笔记(2)

笔记 (https://www.bilibili.com/video/BV1uK411H7on?p30&vd_source3cf72bb393b8cc11b96c6d4bfbcbd890) 1.ES6 1.14集合介绍与API 1.14.1 set常用的api //声明一个set //set 里面的元素是唯一的,会自动去重 let s1 new Set(); //创建 //可以传入可以迭代的数据 let s…

Windows服务器调整TLS1.2加密套件

由于部分服务器默认不支持&#xff1a;TLS1.2加密条件&#xff0c;这会导致谷歌、火狐等浏览器无法访问网站&#xff0c;这种情况下需要调整加密条件。 支持TLS1.2协议的服务器操作系统需要&#xff1a;windows 2008R2 IIS7以上。 注意&#xff1a;微软说明windows 2003、win…

软件测试期末复习(二)试题及答案

文章目录试卷答案试卷 一、选择题(每题 2 分&#xff0c;共 20 分) 1、下面关于软件测试的说法&#xff0c;_______是错误的。 A 软件测试就是程序测试 B 软件测试贯穿于软件定义和开发的整个期间 C 需求规格说明、设计规格说明都是软件测试的对象 D 程序是软件测试的对象 2…

github工具之OA综合利用python

文章目录0x01 下载地址0x02 主要功能0x03 使用方法0x04 参数使用OA v11.6 report_bi.func.php SQL注入漏洞OA v11.6 print.php 任意文件删除漏洞&#xff0c;删除auth.inc.php中OA v11.8 api.ali.php 任意文件上传漏洞OA v11.8 logincheck_code.php登陆绕过漏洞免责声明0x01 下…

adb工具包环境变量配置

官方下载 Android SDK Platform-Tools 一、关于 adb Android SDK Platform-Tools 是 Android SDK 的一个组件。它包含与 Android 平台进行交互的工具&#xff0c;主要是 adb 和 fastboot。   adb是什么? 他的全称叫安卓调试桥&#xff0c;也就是Android debug bridge &…

AAAI2023 | 针对联邦推荐场景的非定向攻击与防御

嘿&#xff0c;记得给“机器学习与推荐算法”添加星标TLDR&#xff1a;今天跟大家分享一篇通过利用聚类算法来操纵物品嵌入特征以此针对联邦推荐场景进行非定向攻击的工作&#xff0c;随后作者针对这一攻击又提出了一种基于一致性的对应防御机制&#xff0c;该论文已被AAAI2023…

如何在Power BI中使用Python导入数据

在这篇文章中&#xff0c;我们将学习如何在Power BI中使用Python编程语言进行数据源化。 简介 Python可以说是业界最流行、最普遍的编程语言之一。一方面&#xff0c;Python可用于网络和应用程序开发&#xff0c;另一方面&#xff0c;它在数据世界中也非常流行&#xff0c;特…

生产制造业ERP管理系统能解决哪些仓库管理难题?

仓库管理够不够好&#xff0c;安不安全&#xff0c;直接关系到生产制造企业的发展。要知道制造型企业的大部分“身家”&#xff0c;都在仓库里了。来料是否及时&#xff0c;物料是否齐套&#xff0c;库存是否安全&#xff0c;配件品质是否合格&#xff0c;库容是否足够&#xf…

【蓝桥杯备赛系列 | 简单题】素数判断 字符串输入输出

&#x1f935;‍♂️ 个人主页: 计算机魔术师 &#x1f468;‍&#x1f4bb; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 蓝桥杯竞赛专栏 | 简单题系列 &#xff08;一&#xff09; 作者&#xff1a; 计算机魔术师 版本&#xff1a; 1.0 &#xff08…

[leetcode.10]正则表达式匹配

&#xff08;1&#xff09;题目分析如下 题目要求完成一个正则表达式的匹配&#xff0c;其中s为目标串&#xff0c;p为正则串 .符号代表任何字符&#xff0c;*符号代表把前一个字符重复n次&#xff08;可能为0次&#xff09; &#xff08;2&#xff09;具体思路 一开始的时…

c++算法基础必刷题目——贪心

文章目录贪心1、拼数2、排座椅3、矩阵消除游戏4、华华听月月唱歌贪心 贪心算法&#xff08;greedy algorithm &#xff0c;又称贪婪算法&#xff09;是指&#xff0c;在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&a…

《图解TCP/IP》阅读笔记(第八章 8.5)—— WWW知多少?

8.5 WWW 看到这章的名字&#xff0c;对于日常上网冲浪的我们而言&#xff0c;应该是再熟悉不过了。这不就是常见网址前的那三个字母&#xff0c;号称万维网&#xff08;WWW&#xff0c;World Wide Web&#xff09;的东西吗? 确实&#xff0c;我们本篇文章就要介绍与之相关的…

Dimitra 2022: 年度回顾

大家好&#xff0c; 我首先要感谢 Dimitra 社区和我们所有的投资者在 2022 年期间的支持。俗话说&#xff0c;“这些都会过去”&#xff0c;2022 年的宏观加密环境尤其具有挑战性&#xff0c;一些非常糟糕的行为者给广泛的加密行业带来很多痛苦。 2023 年可能是监管框架最终显…

公司来了个新测试开发,一副毛头小子的样儿,哪想到......

最近公司来了个新同事&#xff0c;学历并不高&#xff0c;而且大学也不是计算机专业的&#xff0c;今年刚满25岁。。 本以为也是来干点基础的活混混日子的&#xff0c;结果没想到这个人上来就把现有项目的性能优化了一遍&#xff0c;直接给公司节省了不少成本&#xff0c;这种…

Qt通过QProcess启动进程并传递命令行参数

目录QProcess启动外部程序的两种方式依赖式分离式&#xff1a;启动进程前的预处理设置启动路径设置启动命令参数启动的状态更多说明Public FunctionsSignals设计一个拉起进程的程序基本设计思路效果图核心代码控件对象header file&#xff08;头文件&#xff09;member variabl…