效果如下:

直接上代码,自己看

工具类:

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.hj.chain.platform.vo.check.CheckFactorInfoVo;
import org.hj.chain.platform.vo.check.CheckFactorSubsetVo;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;@Slf4j
public class PoiUtil<T> {private static final String MAIN_SHEET = "信息";private static final String SHEET_MAP = "仪器";/*** 计算formula** @param offset   偏移量,如果给0,表示从A列开始,1,就是从B列* @param rowId    第几行* @param colCount 一共多少列* @return 如果给入参 1,1,10. 表示从B1-K1。最终返回 $B$1:$K$1*/private static String getRange(int offset, int rowId, int colCount) {char start = (char) ('A' + offset);if (colCount <= 25) {char end = (char) (start + colCount - 1);return "$" + start + "$" + rowId + ":$" + end + "$" + rowId;} else {char endPrefix = 'A';char endSuffix = 'A';if ((colCount - 25) / 26 == 0 || colCount == 51) {// 26-51之间,包括边界(仅两次字母表计算)if ((colCount - 25) % 26 == 0) {// 边界值endSuffix = (char) ('A' + 25);} else {endSuffix = (char) ('A' + (colCount - 25) % 26 - 1);}} else {// 51以上if ((colCount - 25) % 26 == 0) {endSuffix = (char) ('A' + 25);endPrefix = (char) (endPrefix + (colCount - 25) / 26 - 1);} else {endSuffix = (char) ('A' + (colCount - 25) % 26 - 1);endPrefix = (char) (endPrefix + (colCount - 25) / 26);}}return "$" + start + "$" + rowId + ":$" + endPrefix + endSuffix + "$" + rowId;}}//-----------------------------------------------------------/*** 导出三级联动and单个下拉框的excel** @param name       文件名称* @param headers    表头* @param mapOneList 一级所有内容* @param map        三级联动对应内容* @param list       导出数据*/public static <T> void export(HttpServletResponse response, String name, List<String> headers, List<String> mapOneList, Map<String, LinkedList<String>> map, List<T> list) {// 1.创建Excel// 1)创建workbookHSSFWorkbook hssfWorkBook = new HSSFWorkbook();// 2)创建sheetHSSFSheet mainSheet = hssfWorkBook.createSheet(MAIN_SHEET);// 主sheetAtomicInteger add = new AtomicInteger();//获取行数for (int i = 0; i < list.size(); i++) {CheckFactorInfoVo checkFactorInfoVo = (CheckFactorInfoVo) list.get(i);if ("1".equals(checkFactorInfoVo.getIsFactor())) {if (ObjectUtil.isNotEmpty(checkFactorInfoVo.getFactorSubsetVos())) {add.addAndGet(checkFactorInfoVo.getFactorSubsetVos().size());} else {add.addAndGet(1);}} else {add.addAndGet(1);}}// 用于展示//2 创建表头,供用户输入initHeaders(hssfWorkBook, mainSheet, headers);//导出数据到主sheetsetMainSheet(mainSheet, list);//三级联动 sheetHSSFSheet mapSheet = hssfWorkBook.createSheet(SHEET_MAP);// true:隐藏/false:显示//仪器关系sheethssfWorkBook.setSheetHidden(hssfWorkBook.getSheetIndex(mapSheet), true);// 设置sheet是否隐藏// 3.写入数据writeData(hssfWorkBook, mapSheet, mapOneList, map);// 将数据写入隐藏的sheet中并做好关联关系// 4.设置数据有效性setDataValid(hssfWorkBook, mainSheet, mapOneList, map, add.get());response.reset();try (OutputStream output = response.getOutputStream()) {response.setContentType("application/octet-stream;charset=utf-8");response.setHeader("Content-Disposition", "attachment; filename=" + name);output.flush();hssfWorkBook.write(output);} catch (IOException e) {log.error("导出失败!");e.printStackTrace();}response.setCharacterEncoding("UTF-8");}/*** 生成主页面表头** @param wb* @param mainSheet* @param headers*/private static void initHeaders(HSSFWorkbook wb, HSSFSheet mainSheet, List<String> headers) {//表头样式HSSFCellStyle style = wb.createCellStyle();style.setAlignment(HorizontalAlignment.CENTER); // 创建一个居中格式//字体样式HSSFFont fontStyle = wb.createFont();fontStyle.setFontName("微软雅黑");fontStyle.setFontHeightInPoints((short) 12);fontStyle.setBold(true);style.setFont(fontStyle);//生成主内容HSSFRow rowFirst = mainSheet.createRow(0);//第一个sheet的第一行为标题mainSheet.createFreezePane(0, 1, 0, 1); //冻结第一行CellRangeAddress region1 = new CellRangeAddress(0, 0, 5, 6);CellRangeAddress region2 = new CellRangeAddress(0, 0, 9, 11);mainSheet.addMergedRegion(region1);mainSheet.addMergedRegion(region2);//写标题for (int i = 0; i < headers.size(); i++) {HSSFCell cell;if (i < 6) {cell = rowFirst.createCell(i); //获取第一行的每个单元格} else if (i >= headers.size() - 3) {cell = rowFirst.createCell(i + 3);} else {cell = rowFirst.createCell(i + 1);}mainSheet.setColumnWidth(i, 4000); //设置每列的列宽if (i == 3) {mainSheet.setColumnWidth(i, 6000);}cell.setCellStyle(style); //加样式cell.setCellValue(headers.get(i)); //往单元格里写数据}}private static <T> void setMainSheet(HSSFSheet mainSheet, List<T> list) {HSSFCellStyle style = mainSheet.getWorkbook().createCellStyle();style.setVerticalAlignment(VerticalAlignment.CENTER); // 创建一个居中格式HSSFFont font = mainSheet.getWorkbook().createFont();font.setFontName("宋体");style.setFont(font);//同系套餐因子占用的总行数AtomicInteger add = new AtomicInteger();for (int j = 0; j < list.size(); j++) {//行Row row = mainSheet.createRow(j + 1 + add.get());CheckFactorInfoVo obj = (CheckFactorInfoVo) list.get(j);if (obj != null) {//因子数据填充if (!"1".equals(obj.getIsFactor())) {for (int i = 0; i <= 13; i++) {Cell cell = row.createCell(i);cell.setCellStyle(style);switch (i) {case 0:cell.setCellValue(obj.getSampleNo());break;case 1:case 5:cell.setCellValue(obj.getFactorName());break;case 2:cell.setCellValue(obj.getStandardNo());break;case 3:cell.setCellValue(obj.getStandardName());break;case 4:cell.setCellValue(obj.getFactorRemark());break;case 6:if (ObjectUtil.isNotNull(obj.getCheckRes())) {JSONObject jsonObject = JSONObject.parseObject(obj.getCheckRes());String v1 = jsonObject.getString("v1");String v2 = jsonObject.getString("v2");if (ObjectUtil.isNull(v2)|| "".equals(v2)) {cell.setCellValue(v1);} else {String initial = getInitial(v1, v2);cell.setCellValue(initial);}}break;case 7:cell.setCellValue(obj.getUnitName());break;case 8:if (ObjectUtil.isNotNull(obj.getRemark())) {cell.setCellValue(obj.getRemark());}break;case 9:if (ObjectUtil.isNotNull(obj.getCheckEquipment())) {JSONObject jsonObject = JSONObject.parseObject(obj.getCheckEquipment());cell.setCellValue(jsonObject.getString("equipmentName"));}break;case 10:if (ObjectUtil.isNotNull(obj.getCheckEquipment())) {JSONObject jsonObject = JSONObject.parseObject(obj.getCheckEquipment());cell.setCellValue(jsonObject.getString("equipmentModel"));}break;case 11:if (ObjectUtil.isNotNull(obj.getCheckEquipment())) {JSONObject jsonObject = JSONObject.parseObject(obj.getCheckEquipment());cell.setCellValue(jsonObject.getString("equipmentNumber"));}break;case 12:cell.setCellValue(obj.getCheckFactorId());break;case 13:cell.setCellValue("1".equals(obj.getIsFactor()) ? "是" : "否");break;}}} else {//套餐内容填充for (int i = 0; i < 5; i++) {Cell cell = row.createCell(i);cell.setCellStyle(style);switch (i) {case 0:cell.setCellValue(obj.getSampleNo());break;case 1:cell.setCellValue(obj.getFactorName());break;case 2:cell.setCellValue(obj.getStandardNo());break;case 3:cell.setCellValue(obj.getStandardName());break;case 4:cell.setCellValue(obj.getFactorRemark());break;}}List<CheckFactorSubsetVo> factorSubsetVos = obj.getFactorSubsetVos();row.createCell(12).setCellValue(obj.getCheckFactorId());//套餐因子填充if (ObjectUtil.isNotEmpty(factorSubsetVos)) {for (int i = 0; i < factorSubsetVos.size(); i++) {if (i != 0) {row = mainSheet.createRow(j + 1 + add.get() + i);}//填充因子名称Cell cell5 = row.createCell(5);cell5.setCellValue(factorSubsetVos.get(i).getFactorName());cell5.setCellStyle(style);Cell cell7 = row.createCell(7);cell7.setCellValue(factorSubsetVos.get(i).getUnitName());cell7.setCellStyle(style);Cell cell12 = row.createCell(12);cell12.setCellValue(obj.getCheckFactorId());cell12.setCellStyle(style);Cell cell13 = row.createCell(13);cell13.setCellValue("1".equals(obj.getIsFactor()) ? "是" : "否");cell13.setCellStyle(style);Cell cell14 = row.createCell(14);cell14.setCellValue(factorSubsetVos.get(i).getId());cell14.setCellStyle(style);if (ObjectUtil.isNotNull(factorSubsetVos.get(i).getCheckSubRes())) {JSONObject jsonObject = JSONObject.parseObject(factorSubsetVos.get(i).getCheckSubRes());String v1 = jsonObject.getString("v1");String v2 = jsonObject.getString("v2");Cell cell6 = row.createCell(6);if (ObjectUtil.isNull(v2)|| "".equals(v2)) {cell6.setCellValue(v1);} else {String initial = getInitial(v1, v2);cell6.setCellValue(initial);}cell6.setCellStyle(style);}if (ObjectUtil.isNotNull(obj.getRemark())) {Cell cell8 = row.createCell(8);cell8.setCellStyle(style);cell8.setCellValue(obj.getRemark());}if (ObjectUtil.isNotNull(obj.getCheckEquipment())) {JSONObject jsonObject = JSONObject.parseObject(obj.getCheckEquipment());Cell cell9 = row.createCell(9);cell9.setCellStyle(style);cell9.setCellValue(jsonObject.getString("equipmentName"));Cell cell10 = row.createCell(10);cell10.setCellStyle(style);cell10.setCellValue(jsonObject.getString("equipmentModel"));Cell cell11 = row.createCell(11);cell11.setCellStyle(style);cell11.setCellValue(jsonObject.getString("equipmentNumber"));}}}//累加套餐因子所占行数int oldAdd = add.getAndAdd(factorSubsetVos.size() - 1);// 四个参数分别是:起始行、终止行、起始列、终止列.CellRangeAddress region1 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 0, 0);CellRangeAddress region2 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 1, 1);CellRangeAddress region3 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 2, 2);CellRangeAddress region4 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 3, 3);CellRangeAddress region5 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 4, 4);CellRangeAddress region6 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 8, 8);CellRangeAddress region7 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 9, 9);CellRangeAddress region8 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 10, 10);CellRangeAddress region9 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 11, 11);mainSheet.addMergedRegion(region1);mainSheet.addMergedRegion(region2);mainSheet.addMergedRegion(region3);mainSheet.addMergedRegion(region4);mainSheet.addMergedRegion(region5);mainSheet.addMergedRegion(region6);mainSheet.addMergedRegion(region7);mainSheet.addMergedRegion(region8);mainSheet.addMergedRegion(region9);}}mainSheet.setColumnHidden(12, true);mainSheet.setColumnHidden(13, true);mainSheet.setColumnHidden(14, true);}}private static void setDataValid(HSSFWorkbook HSSFWorkBook, HSSFSheet mainSheet, List<String> firstList, Map<String, LinkedList<String>> siteMap, Integer line) {//设置一级下拉HSSFDataValidationHelper dvHelper = new HSSFDataValidationHelper((HSSFSheet) mainSheet);String[] dataArray = firstList.toArray(new String[0]);HSSFSheet hidden = HSSFWorkBook.createSheet("hidden");HSSFCell cell = null;for (int i = 0, length = dataArray.length; i < length; i++) {String name = dataArray[i];HSSFRow row = hidden.createRow(i);cell = row.createCell(0);cell.setCellValue(name);}Name namedCell = HSSFWorkBook.createName();namedCell.setNameName("hidden");namedCell.setRefersToFormula("hidden!$A$1:$A$" + dataArray.length);//加载数据,将名称为hidden的DVConstraint constraint = DVConstraint.createFormulaListConstraint("hidden");// 四个参数分别是:起始行、终止行、起始列、终止列.// 1 (一级下拉框代表从excel第1+1行开始) line(一级下拉框代表从excel第1+10行结束) 9(代表第几列开始,0是第一列,1是第二列) 1(代表第几列结束,0是第一列,1是第二列)CellRangeAddressList firstRangeAddressList = new CellRangeAddressList(1, line, 9, 9);DataValidation firstDataValidation = dvHelper.createValidation(constraint, firstRangeAddressList);firstDataValidation.createErrorBox("error", "请选择正确");firstDataValidation.setShowErrorBox(true);// firstDataValidation.setSuppressDropDownArrow(true);//将第二个sheet设置为隐藏// true:隐藏/false:显示HSSFWorkBook.setSheetHidden(HSSFWorkBook.getSheetIndex(hidden), true);// 设置sheet是否隐藏
//        HSSFWorkBook.setSheetHidden(1, true);mainSheet.addValidationData(firstDataValidation);// 设置第二级、第三级下拉// i <= 10 ,10代表第二级、第三级下拉框到10+1行结束for (int i = 0; i <= 10; i++) {setDataValidation('J', mainSheet, i + 1, 10);// "J"是指父类所在的列,i+1初始值为1代表从第2行开始,10要与“J”对应,为J的列号加1,假如第一个参数为“C”,那么最后一个参数就3}}/*** 设置有效性** @param offset 主影响单元格所在列,即此单元格由哪个单元格影响联动* @param sheet* @param rowNum 行数* @param colNum 列数*/private static void setDataValidation(char offset, HSSFSheet sheet, int rowNum, int colNum) {HSSFDataValidationHelper dvHelper = new HSSFDataValidationHelper(sheet);DataValidation dataValidationList1;DataValidation dataValidationList2;dataValidationList1 = getDataValidationByFormula("INDIRECT($" + offset + (rowNum) + ")", rowNum, colNum, dvHelper);dataValidationList2 = getDataValidationByFormula("INDIRECT($" + (char) (offset + 1) + (rowNum) + ")", rowNum, colNum + 1, dvHelper);sheet.addValidationData(dataValidationList1);sheet.addValidationData(dataValidationList2);}private static DataValidation getDataValidationByFormula(String formulaString, int naturalRowIndex, int naturalColumnIndex, HSSFDataValidationHelper dvHelper) {DataValidationConstraint dvConstraint = dvHelper.createFormulaListConstraint(formulaString);CellRangeAddressList regions = new CellRangeAddressList(naturalRowIndex, 65535, naturalColumnIndex, naturalColumnIndex);HSSFDataValidation data_validation_list = (HSSFDataValidation) dvHelper.createValidation(dvConstraint, regions);data_validation_list.setEmptyCellAllowed(false);if (data_validation_list instanceof HSSFDataValidation) {// data_validation_list.setSuppressDropDownArrow(true);data_validation_list.setShowErrorBox(true);} else {// data_validation_list.setSuppressDropDownArrow(false);}// 设置输入信息提示信息data_validation_list.createPromptBox("下拉选择提示", "请使用下拉方式选择合适的值!");return data_validation_list;}private static void writeData(HSSFWorkbook hssfWorkBook, HSSFSheet mapSheet, List<String> firstList, Map<String, LinkedList<String>> subMap) {//循环将父数据写入siteSheet的第1行中int siteRowId = 0;HSSFRow firstRow = mapSheet.createRow(siteRowId++);firstRow.createCell(0).setCellValue("父列表");for (int i = 0; i < firstList.size(); i++) {firstRow.createCell(i + 1).setCellValue(firstList.get(i));}// 将具体的数据写入到每一行中,行开头为父级区域,后面是子区域。Iterator<String> keyIterator = subMap.keySet().iterator();while (keyIterator.hasNext()) {String key = keyIterator.next();List<String> son = subMap.get(key);HSSFRow siteRow = mapSheet.createRow(siteRowId++);siteRow.createCell(0).setCellValue(key);for (int i = 0; i < son.size(); i++) {siteRow.createCell(i + 1).setCellValue(son.get(i));}// 添加名称管理器String range = getRange(1, siteRowId, son.size());Name name = hssfWorkBook.createName();name.setNameName(key);String formula = mapSheet.getSheetName() + "!" + range;name.setRefersToFormula(formula);}}private static String getInitial(String a, String b) {if (ObjectUtil.isNull(b)|| "".equals(b)) {return a;} else {StringBuffer sb = new StringBuffer();return sb.append(a).append("*").append("10^").append(b).toString();}}}

使用方法:
根据自身业务进行组装数据

    public void export(HttpServletResponse response, CheckFactorSearchVo searchVo) {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");String dateString = format.format(new Date());//文件名称String name = dateString+".xls";//excel 表头List<String> headers = Arrays.asList("样品编号","检测因子","标准号", "检测标准", "备注信息", "检测结果","单位","备注","检测设备","检测因子id","因子套餐","套餐因子id");JSONArray tree = (JSONArray)equipmentInfoService.laboratoryEquipmentTree().getResult();LinkedList<String> firstList = new LinkedList<>();HashMap<String, LinkedList<String>> subMap = new HashMap();tree.forEach( object->{String firstName = ((JSONObject) object).getString("name");firstList.add(firstName);JSONArray children = ((JSONObject) object).getJSONArray("children");LinkedList<String> subList = new LinkedList<>();children.forEach( subObject ->{String secondName = ((JSONObject) subObject).getString("name");LinkedList<String> thirdList = new LinkedList<>();subList.add(secondName);JSONArray secondChildren = ((JSONObject) subObject).getJSONArray("children");secondChildren.forEach( thirdObject->{String thirdName = ((EquipmentTreeVo)thirdObject).getEquipmentNumber();thirdList.add(thirdName);});subMap.put(secondName,thirdList);});subMap.put(firstName,subList);});PoiUtil.export(response,name,headers,firstList,subMap,factorInfoVos);}

导出内容如下:

有两个隐藏的表格用来实现级联下拉


Excel导出级联下拉功能实现相关推荐

  1. 使用EasyExcel导出模板并设置级联下拉及其原理分析

    一.概述 项目中有时会遇到需要导出一个Excel模板,然后在导出的Excel中填充数据,最终再调用接口批量把Excel中的数据导入到数据库当中的需求. 其中级联下拉选择,手机号校验,性别校验等都是比较 ...

  2. Java EXCEL 表格导入导出(带下拉选-带VLOOKUP函数封装)

    Java EXCEL 表格导入导出(带下拉选-带VLOOKUP函数封装) 对于excel Java POI 使用 目前简单导出导入功能网上很多,但是对于有下拉选,样式等缺点却是最大硬伤,故此封装一个通 ...

  3. java 基于注解实现动态级联下拉excel模板

    动态级联下拉模板导出 前言 一.构建项目结构 二.最终效果(下载到本地,流的形式可自行测试) 三.具体实现 1)pom.xml 依赖 2)注解类 Excel 和 ExcelFile 3)构建实体类 T ...

  4. EasyExcel在项目中的应用-在web中导出带下拉框和批注的excel文件

    前言 ​ 好长一段时间没有更新博客了,最近刚刚找到实习工作,接触了企业中的项目,在这段时间的实习过程中,终于知道了企业级项目的体量和业务难度跟之前的小项目是完全不同的.10多天的适应期也逐渐让我找到了 ...

  5. Excel 2019:二级级联下拉框设置

    Execl 2019:二级级联下拉框 场景需求 实现效果展示 二级级联设置步骤 1.填写基础信息 2.设置一级数据验证 3.设置依赖于一级选择的二级下拉内容 场景需求 当我们需要规范输入的数据时,会用 ...

  6. excel添加列下拉框票价_excel表格下拉表格添加数据-excel2017表格中怎么制作下拉菜单列表框...

    在Excel表中,如何将增加下拉菜单的选项? excel中的下拉菜单选项,就是筛选的功能,具体操作如下: 1.首先选中a.b两列数据,在"开始"选项卡上选择"筛选&quo ...

  7. excel 表做下拉框_Excel工作表的组合框下拉列表

    excel 表做下拉框 Would you prefer a bigger font size for items in a data validation drop down list? Would ...

  8. excel中通过下拉菜单显示不同的报表内容,类似下拉选项中,一旦切换内容,后面的表格内容全都不同?

    EXCEL是日常办公中应用非常多的办公软件之一,其强大的数据统计.分析功能为我们的工作带来不少方便.我们可以在EXCEL中设置下拉菜单,以方便我们输入相同内容.本文就以将性别设置为下拉菜单为例,介绍具 ...

  9. jsf的初步使用(包括jsf框架的引入、用户登录、自定义表单验证、valueChangeEvent值变更事件处理做的级联下拉框)

    jsf初步使用 一.新建一个web项目MyJSF 直接把生成index.jsp和web.xml勾选上生成对应的文件. 在web项目跟目录下(一般是web或者是WebRoot,也可以自己指定,本人用的是 ...

  10. excel表格往下拉数字不变该怎么解决?

    excel是办公软件中唯一一个表格专业户文件,它的功能最常用的就是统计数据,通过它的函数功能.求和功能等进行统计数据会变得非常简单粗暴.那么它还有一个功能在统计数据的时候也会用到,就是递增.excel ...

最新文章

  1. bat自动输入密码登录_如何制作自动设置计算机管理员密码的脚本
  2. 纹理对象的实时姿态估计
  3. java集合框架栈_自己实现集合框架(九):栈接口
  4. python基础教程:类和对象
  5. 【STM32】 keil软件工具--Configuration详解(上)
  6. HDU 1874 畅通工程续 (Dijkstra , Floyd , SPFA, Bellman_Ford 四种算法)
  7. VisualStudio中的代码段
  8. 网站程序员的程序员成长之路大概分几个阶段 和未来的发展
  9. php按数字分页类,PHP简单实现数字分页功能示例
  10. 【POJ 3614 Sunscreen】贪心 优先级队列
  11. linux shell 基本规范
  12. 加入鹅厂,就趁现在!
  13. C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训
  14. 如何在matlab中打开图片
  15. 【openGL2021版】天空盒
  16. 我一生中最重要的12个人
  17. seaborn画各种典型图的代码备忘录(1)——dataframe数据画双Y坐标轴柱状图
  18. Android内存优化汇总
  19. 智能语音计算器(三)
  20. r7000p装linux双系统,联想拯救者 刃7000台式机设置u盘启动(支持uefi/bios双启动)

热门文章

  1. 上肢康复机器人结构设计【论文、19张CAD图纸、开题报告、任务书、中期检查表】
  2. liigo:在PC电脑屏幕上模拟显示移动设备屏幕的物理尺寸示意图
  3. 设置按钮上的文字靠左靠右居中显示
  4. 数字图像处理:图像复原
  5. ELK(数据批量导入、查询)
  6. 游戏碰撞表示以及检测的原理
  7. iOS WKWebView网页文字加载完了但过了很久才执行didFinishNavigation该怎么办,我需要在文字的加载完后进行页面操作
  8. github学习笔记第三篇《学习github的分支操作》
  9. 智能水位检测系统proteus_基于at89c51单片机的水箱水位检测控制系统设计.pdf
  10. Model Integrity 功能详述与启动方法图文教程