java導出excel文件1

1.controller

/**
     * 條件下載賬單信息excel
     *
     * @param orderCode 檢索條件
     * @param billDtStart 檢索條件
     * @param billDtEnd 檢索條件
     * @param state 檢索條件
     * @param corganCodes 檢索條件
     * @param status 檢索條件
     * @param flag 檢索條件
     * @param userNameLike 檢索條件
     * @param capitalSide 資金方
     * @param response 相應信息
     */
    @GetMapping("/downloadBillExcel")
    public void downloadBillExcel(@RequestParam(required = false) String orderCode,
                                  @RequestParam(required = false) String billDtStart,
                                  @RequestParam(required = false) String billDtEnd,
                                  @RequestParam(required = false) String state,
                                  @RequestParam(required = false) String corganCodes,
                                  @RequestParam(required = false) String status,
                                  @RequestParam(required = false) String flag,
                                  @RequestParam(required = false) String userNameLike,
                                  @RequestParam(required = false) String capitalSide, HttpServletResponse response) {
        log.info(
                "條件下載賬單信息excel-orderCode:{},billDtStart:{},billDtEnd:{},state:{},corganCodes:{},status:{},flag:{},userNameLike:{}",
                orderCode, billDtStart, billDtEnd, state, corganCodes, status, flag, userNameLike);
        PageMapperDto mapperDto = new PageMapperDto();
        mapperDto.setPageStart(null);
        mapperDto.setPageSize(null);
        mapperDto.setUserName(userNameLike);
        mapperDto.setOrderCode(orderCode);
        mapperDto.setCorganCodeListByParam(VehicleUtils.stringToList(corganCodes));
        mapperDto.setFlagList(VehicleUtils.stringToList(flag));
        mapperDto.setStateList(VehicleUtils.stringToList(state));
        mapperDto.setStatusList(VehicleUtils.stringToList(status));
        mapperDto.setCapitalSideList(VehicleUtils.stringToList(capitalSide));
        if (StringUtils.isNotBlank(billDtStart) && StringUtils.isNotBlank(billDtEnd)) {
            mapperDto
                    .setBillDtStart(DateUtils.date2String(DateUtils.parseTimestampToDate(Long.parseLong(billDtStart))));
            mapperDto.setBillDtEnd(DateUtils.date2String(DateUtils.parseTimestampToDate(Long.parseLong(billDtEnd))));
        }
        log.info("條件下載賬單信息mapperDto:{}", JSON.toJSON(mapperDto));

        try {
            File file = orderBillingService.genFileByCondition(mapperDto);

            commonService.downloadFile(file, response);
        } catch (Exception e) {
            log.error("Exception:{}", JSON.toJSON(e));
        }
    }

2.serviceImpl

/**
     * 條件獲取賬單excel文件
     *
     * @param mapperDto 檢索條件
     * @return excel文件地址
     */
    @Override
    public File genFileByCondition(PageMapperDto mapperDto) {
        List<OrderBillingPageResponseDto> responseDtoList = crudMapper.findOrderBillingPage(mapperDto);
        log.info("條件查詢賬單:{}", responseDtoList.size());

        // 文件存放目錄
        String dir = tempFilePath;
        BankUtils.mkDir(dir);

        String billExcelPath = String.format(OrderBillingConstants.STRING_FORMAT_4, dir,
                OrderBillingConstants.DOWNLOAD_EXCEL_NAME_ORDER_BILL, BankUtils.getCurrentDateTime(),
                OrderBillingConstants.EXCEL_FORMAT_XLS);
        log.info("準備生成的賬單excel文件地址:{}", billExcelPath);

        // sheet頁名稱
        String sheetName = OrderBillingConstants.DOWNLOAD_EXCEL_NAME_ORDER_BILL;

        // 默認列寬
        String defaultColumnLength = OrderBillingConstants.STRING_THIRTY;

        // 列寬
        List<String> columnLengthList = new ArrayList<>();

        // 標題名稱
        Object[] nameObj = Stream
                .of("訂單編號", "賬單期數", "賬單日期", "承租人姓名", "申請時間", "分公司", "分期金額", "應還本金", "應還利息", "逾期違約金", "逾期違約罰息", "代扣結果",
                        "資方業務狀態", "賬單標記", "賬單狀態", "是否已逾期", "實際還款日期", "已還月租", "已還本金", "已還利息", "已還違約金", "已還罰息", "待還月租",
                        "待還本金", "待還利息", "待還違約金", "待還罰息")
                .toArray();
        String[] title = new String[nameObj.length];
        for (int i = 0; i < title.length; i++) {
            title[i] = nameObj[i].toString();
            if (i == 0 || i == 4 || i == 5) {
                columnLengthList.add("30");
            } else {
                columnLengthList.add("20");
            }
        }

        int size = responseDtoList.size();
        String[][] context = new String[size][title.length];
        if (CollectionUtils.isNotEmpty(responseDtoList)) {
            responseDtoList.sort(Comparator.comparing(OrderBillingPageResponseDto::getId));
            for (int i = 0; i < size; i++) {
                OrderBillingPageResponseDto responseDto = responseDtoList.get(i);
                log.info("********responseDto:{}", JSON.toJSON(responseDto));
                for (int j = 0; j < title.length; j++) {
                    if (j == 0) {
                        // 訂單編號
                        context[i][j] = responseDto.getOrderCode();
                    } else if (j == 1) {
                        // 賬單期數
                        context[i][j] = responseDto.getBillPeriod().toString();
                    } else if (j == 2) {
                        // 賬單日期
                        context[i][j] = DateUtils.formatDate(responseDto.getBillDt(),
                                OrderBillingConstants.TIME_FORMAT);
                    } else if (j == 3) {
                        // 承租人姓名
                        context[i][j] = String.valueOf(responseDto.getUserName());
                    } else if (j == 4) {
                        // 申請時間
                        if (null != responseDto.getApplyTime()) {
                            context[i][j] = DateUtils.formatDate(responseDto.getApplyTime(),
                                    VehicleConstants.TIANYI_TIME_FORMAT);
                        }
                    } else if (j == 5) {
                        // 分公司
                        context[i][j] = responseDto.getOrganName();
                    } else if (j == 6) {
                        // 分期金額
                        context[i][j] = String.valueOf(responseDto.getBillFee());
                    } else if (j == 7) {
                        // 賬單應還本金
                        context[i][j] = String.valueOf(responseDto.getBillCapital());
                    } else if (j == 8) {
                        // 賬單應還利息
                        context[i][j] = String.valueOf(responseDto.getBillInterest());
                    } else if (j == 9) {
                        // 逾期違約金
                        context[i][j] = String.valueOf(responseDto.getOverdueContractAmt());
                    } else if (j == 10) {
                        // 逾期罰息
                        context[i][j] = String.valueOf(responseDto.getOverduePenalty());
                    } else if (j == 11) {
                        // 代扣結果
                        context[i][j] = responseDto.getWithholdResult();
                    } else if (j == 12) {
                        BillStateEnum billStateEnum = BillStateEnum.getEnumByCode(responseDto.getState());
                        // 資方業務狀態
                        if (billStateEnum != null) {
                            context[i][j] = billStateEnum.getMsg();
                        }
                    } else if (j == 13) {
                        // 賬單標記
                        BillFlagEnum billFlagEnum = BillFlagEnum.getEnumByCode(responseDto.getFlag());
                        if (billFlagEnum != null) {
                            context[i][j] = billFlagEnum.getMsg();
                        }
                    } else if (j == 14) {
                        // 狀態
                        BillStatusEnum billStatusEnum = BillStatusEnum.getEnumByCode(responseDto.getStatus());
                        if (billStatusEnum != null) {
                            context[i][j] = billStatusEnum.getMsg();
                        }
                    } else if (j == 15) {
                        // 是否已逾期
                        YesNoEnum yesNoEnum = YesNoEnum.getEnumByCode(responseDto.getIsOverdue());
                        if (yesNoEnum != null) {
                            context[i][j] = yesNoEnum.getMsg();
                        }
                    } else if (j == 16) {
                        // 實際還款日期
                        if (null != responseDto.getBillRepayDt()) {
                            context[i][j] = DateUtils.formatDate(responseDto.getBillRepayDt(),
                                    OrderBillingConstants.TIME_FORMAT);
                        }
                    } else if (j == 17) {
                        // 已還月租
                        context[i][j] = responseDto.getPaidFee().toString();
                    } else if (j == 18) {
                        // 已還本金
                        context[i][j] = responseDto.getBillCapital()
                                .subtract(responseDto.getUnpaidCapital())
                                .toString();
                    } else if (j == 19) {
                        // 已還利息
                        context[i][j] = responseDto.getBillInterest()
                                .subtract(responseDto.getUnpaidIntrest())
                                .toString();
                    } else if (j == 20) {
                        // 已還違約金
                        context[i][j] = responseDto.getOverdueContractAmt()
                                .subtract(responseDto.getUnpaidContractAmt())
                                .toString();
                    } else if (j == 21) {
                        // 已還罰息
                        context[i][j] = responseDto.getOverduePenalty()
                                .subtract(responseDto.getUnpaidPenalty())
                                .toString();
                    } else if (j == 22) {
                        // 待還月租
                        context[i][j] = responseDto.getUnpaidFee().toString();
                    } else if (j == 23) {
                        // 待還本金
                        context[i][j] = responseDto.getUnpaidCapital().toString();
                    } else if (j == 24) {
                        // 待還利息
                        context[i][j] = responseDto.getUnpaidIntrest().toString();
                    } else if (j == 25) {
                        // 待還違約金
                        context[i][j] = responseDto.getUnpaidContractAmt().toString();
                    } else {
                        // 待還罰息
                        context[i][j] = responseDto.getUnpaidPenalty().toString();
                    }
                }
            }
        }

        List<Label> labelList = new ArrayList<>();
        List<ExcelMergeCellsDto> mergeCellsDtoList = new ArrayList<>();

        // 生成excel文件
        ExcelUtils.exportExcel(billExcelPath, sheetName, defaultColumnLength, columnLengthList, title, context,
                labelList, mergeCellsDtoList);
        return new File(billExcelPath);
    }

3. ExcelUtils

import java.io.File;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import com.yifenqi.dto.ExcelMergeCellsDto;

import jxl.CellView;
import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.format.UnderlineStyle;
import jxl.format.VerticalAlignment;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import lombok.extern.slf4j.Slf4j;

/**
 * Excel處理工具類
 */
@Slf4j
public class ExcelUtils {

    /**
     * WORD_TO_PDF_OPERAND
     */
    private static final Integer WORD_TO_PDF_OPERAND  = 17;

    /**
     * PPT_TO_PDF_OPERAND
     */
    private static final Integer PPT_TO_PDF_OPERAND   = 32;

    /**
     * EXCEL_TO_PDF_OPERAND
     */
    private static final Integer EXCEL_TO_PDF_OPERAND = 0;

    /**
     * 生成Excel到filePath路徑中
     *
     * @param filePath 生成Excel的保存路徑
     * @param sheetName Excel中sheet名
     * @param defaultColumnLength 整個Excel的默認單元格寬度
     * @param columnLengthList 定義每個列寬
     * @param title 標題
     * @param context 內容
     * @param labelList 需要合併處文字設置
     * @param mergeCellsDtoList 單元格合併座標列表
     */
    public static void exportExcel(String filePath, String sheetName, String defaultColumnLength,
                                   List<String> columnLengthList, String[] title, String[][] context,
                                   List<Label> labelList, List<ExcelMergeCellsDto> mergeCellsDtoList) {
        exportExcel(filePath, sheetName, defaultColumnLength, columnLengthList, title, context, labelList,
                mergeCellsDtoList, null);
    }

    /**
     * 生成Excel到filePath路徑中
     *
     * @param filePath 生成Excel的保存路徑
     * @param sheetName Excel中sheet名
     * @param defaultColumnLength 整個Excel的默認單元格寬度
     * @param columnLengthList 定義每個列寬
     * @param title 標題
     * @param context 內容
     * @param labelList 需要合併處文字設置
     * @param mergeCellsDtoList 單元格合併座標列表
     * @param rowHeightMap 定義行高
     */
    public static void exportExcel(String filePath, String sheetName, String defaultColumnLength,
                                   List<String> columnLengthList, String[] title, String[][] context,
                                   List<Label> labelList, List<ExcelMergeCellsDto> mergeCellsDtoList,
                                   Map<Integer, Integer> rowHeightMap) {

        //操作執行
        try {
            //t.xls爲要新建的文件名
            WritableWorkbook book = Workbook.createWorkbook(new File(filePath));
            //生成名爲“第一頁”的工作表,參數0表示這是第一頁
            WritableSheet sheet = book.createSheet(sheetName, 0);

            if (!StringUtils.isBlank(defaultColumnLength)) {
                sheet.getSettings().setDefaultColumnWidth(Integer.valueOf(defaultColumnLength));
            }

            //Excel相關默認設置
            WritableCellFormat titleFormat = genTitleFormat();
            WritableCellFormat contentFormat = genContentFormat();
            CellView cellView = new CellView();
            cellView.setAutosize(true);

            //寫入標題
            for (int i = 0; i < title.length; i++) {
                //title
                sheet.addCell(new Label(i, 0, title[i], titleFormat));
                if (!CollectionUtils.isEmpty(columnLengthList) && columnLengthList.size() >= title.length) {
                    sheet.setColumnView(i, Integer.valueOf(columnLengthList.get(i)));
                }
            }

            //Excel的內容
            //context
            for (int i = 0; i < context.length; i++) {
                for (int j = 0; j < context[i].length; j++) {
                    sheet.addCell(new Label(j, i + 1, context[i][j], contentFormat));
                }
            }

            //合併單元格
            if (!CollectionUtils.isEmpty(labelList)) {
                for (int i = 0; i < labelList.size(); i++) {
                    addCell(sheet, labelList.get(i));
                }
            }

            if (!CollectionUtils.isEmpty(mergeCellsDtoList)) {
                for (int i = 0; i < mergeCellsDtoList.size(); i++) {
                    ExcelMergeCellsDto record = mergeCellsDtoList.get(i);
                    mergeCells(sheet, record.getM(), record.getN(), record.getP(), record.getQ());
                }
            }

            //設置行高
            if (null != rowHeightMap) {
                for (Map.Entry<Integer, Integer> entry : rowHeightMap.entrySet()) {
                    sheet.setRowView(entry.getKey(), entry.getValue());
                }
            }
            // 空白行,列刪除
            removeColumns(sheet);

            //寫入數據
            book.write();
            //關閉文件
            book.close();
        } catch (Exception e) {
            log.error("exportExcel error{}", e);
        }
    }

    /**
     * 組裝數據
     *
     * @param book 文件
     * @param sheetName Excel中sheet名
     * @param defaultColumnLength 整個Excel的默認單元格寬度
     * @param columnLengthList 定義每個列寬
     * @param title 標題
     * @param context 內容
     * @param labelList 需要合併處文字設置
     * @param mergeCellsDtoList 單元格合併座標列表
     */
    public static void exportExcelData(WritableWorkbook book, String sheetName, String defaultColumnLength,
                                       List<String> columnLengthList, String[] title, String[][] context,
                                       List<Label> labelList, List<ExcelMergeCellsDto> mergeCellsDtoList) {
        exportExcelData(book, sheetName, defaultColumnLength, columnLengthList, title, context, labelList,
                mergeCellsDtoList, null);
    }

    /**
     * 組裝Excel數據
     *
     * @param book ExcelBook
     * @param sheetName Excel中sheet名
     * @param defaultColumnLength 整個Excel的默認單元格寬度
     * @param columnLengthList 定義每個列寬
     * @param title 標題
     * @param context 內容
     * @param labelList 需要合併處文字設置
     * @param mergeCellsDtoList 單元格合併座標列表
     * @param rowHeightMap 定義行高
     */
    public static void exportExcelData(WritableWorkbook book, String sheetName, String defaultColumnLength,
                                       List<String> columnLengthList, String[] title, String[][] context,
                                       List<Label> labelList, List<ExcelMergeCellsDto> mergeCellsDtoList,
                                       Map<Integer, Integer> rowHeightMap) {
        //操作執行
        try {
            //生成名爲“第一頁”的工作表,參數0表示這是第一頁
            WritableSheet sheet = book.createSheet(sheetName, 0);

            if (!StringUtils.isBlank(defaultColumnLength)) {
                sheet.getSettings().setDefaultColumnWidth(Integer.valueOf(defaultColumnLength));
            }

            //Excel相關默認設置
            WritableCellFormat titleFormat = genTitleFormat();
            WritableCellFormat contentFormat = genContentFormat();
            CellView cellView = new CellView();
            cellView.setAutosize(true);

            //寫入標題
            for (int i = 0; i < title.length; i++) {
                //title
                sheet.addCell(new Label(i, 0, title[i], titleFormat));
                if (!CollectionUtils.isEmpty(columnLengthList) && columnLengthList.size() >= title.length) {
                    sheet.setColumnView(i, Integer.valueOf(columnLengthList.get(i)));
                }
            }

            //Excel的內容
            //context
            for (int i = 0; i < context.length; i++) {
                for (int j = 0; j < context[i].length; j++) {
                    sheet.addCell(new Label(j, i + 1, context[i][j], contentFormat));
                }
            }

            //合併單元格
            if (!CollectionUtils.isEmpty(labelList)) {
                for (int i = 0; i < labelList.size(); i++) {
                    addCell(sheet, labelList.get(i));
                }
            }

            if (!CollectionUtils.isEmpty(mergeCellsDtoList)) {
                for (int i = 0; i < mergeCellsDtoList.size(); i++) {
                    ExcelMergeCellsDto record = mergeCellsDtoList.get(i);
                    mergeCells(sheet, record.getM(), record.getN(), record.getP(), record.getQ());
                }
            }

            //設置行高
            if (null != rowHeightMap) {
                for (Map.Entry<Integer, Integer> entry : rowHeightMap.entrySet()) {
                    sheet.setRowView(entry.getKey(), entry.getValue());
                }
            }

            // 空白行,列刪除
            removeColumns(sheet);
        } catch (Exception e) {
            log.error("exportExcel error{}", e);
        }
    }

    /**
     * 特殊單元格數據設置
     *
     * @param sheet Excel中的sheet
     * @param label 頁面
     */
    public static void addCell(WritableSheet sheet, Label label) {
        try {
            sheet.addCell(label);
        } catch (WriteException e) {
            log.error("addCell error{}", e);
        }
    }

    /**
     * 合併單元格.合併既可以是橫向的,也可以是縱向的 WritableSheet.mergeCells(int m,int n,int p,int
     * q); 表示由(m,n)到(p,q)的單元格組成的矩形區域合併
     *
     * @param sheet Excel中的sheet
     * @param m 開始單元格x座標
     * @param n 開始單元格y座標
     * @param p 結束單元格x座標
     * @param q 結束單元格y座標
     */
    public static void mergeCells(WritableSheet sheet, int m, int n, int p, int q) {
        try {
            sheet.mergeCells(m, n, p, q);
        } catch (WriteException e) {
            log.error("mergeCells error{}", e);
        }
    }

    /**
     * Excel中的標題格式
     *
     * @return 標題格式
     */
    public static WritableCellFormat genTitleFormat() {
        WritableCellFormat cellFormat = null;
        //設置垂直居中;
        try {
            //設置字體;
            WritableFont fontTitle = new WritableFont(WritableFont.ARIAL, 14, WritableFont.BOLD, false,
                    UnderlineStyle.NO_UNDERLINE, Colour.BLACK);

            cellFormat = new WritableCellFormat(fontTitle);
            //設置背景顏色;
            cellFormat.setBackground(Colour.GRAY_25);
            //設置邊框;
            cellFormat.setBorder(Border.ALL, BorderLineStyle.THIN);
            //設置自動換行;
            cellFormat.setWrap(true);
            //設置文字對齊方式;
            cellFormat.setAlignment(Alignment.CENTRE);
            cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
        } catch (WriteException e) {
            log.error("genTitleFormat Exception is{}", e);
        }

        return cellFormat;
    }

    /**
     * Excel中的內容格式
     *
     * @return 內容格式
     */
    public static WritableCellFormat genContentFormat() {
        WritableCellFormat cellFormat = null;
        //設置垂直居中;
        try {
            //設置字體;
            WritableFont fontTitle = new WritableFont(WritableFont.ARIAL, 12, WritableFont.NO_BOLD, false,
                    UnderlineStyle.NO_UNDERLINE, Colour.BLACK);

            cellFormat = new WritableCellFormat(fontTitle);
            //設置背景顏色;
            cellFormat.setBackground(Colour.WHITE);
            //設置邊框;
            cellFormat.setBorder(Border.ALL, BorderLineStyle.THIN);
            //設置自動換行;
            cellFormat.setWrap(true);
            //設置文字對齊方式;
            cellFormat.setAlignment(Alignment.LEFT);
            cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
        } catch (WriteException e) {
            log.error("genContentFormat Exception is{}", e);
        }

        return cellFormat;
    }

    /**
     * 刪除空白行
     *
     * @param sheet Excel中的sheet
     */
    public static void removeColumns(WritableSheet sheet) {
        //列數
        int rsCols = sheet.getColumns();
        //行數
        int rsRows = sheet.getRows();
        int nullCellNum;
        //統計行中爲空的單元格數
        for (int i = 1; i < rsRows; i++) {
            nullCellNum = 0;
            for (int j = 0; j < rsCols; j++) {
                String val = sheet.getCell(j, i).getContents();
                val = StringUtils.trimToEmpty(val);
                if (StringUtils.isBlank(val)) {
                    nullCellNum++;
                }
                //如果nullCellNum大於或等於總的列數
                if (nullCellNum >= rsCols) {
                    sheet.removeColumn(j);
                }
            }
        }
    }
}

4.commonServiceImpl

/**
     * 下載單個文件
     *
     * @param file 文件信息
     * @param response 響應信息
     */
    @Override
    public void downloadFile(File file, HttpServletResponse response) {
        long start = System.currentTimeMillis();
        try {
            int fileBufferSize = CommConstant.FILE_BUFFER_SIZE_DEFAULT;
            DictCode dictCode = dictCodeService.findByGroupAndCodeNoCache(CommConstant.FILE_BUFFER_SIZE,
                    CommonFlag.Y.getCode());
            if (dictCode != null) {
                fileBufferSize = Integer.valueOf(dictCode.getName());
            }

            if (file == null) {
                response.getWriter().println("file is null , please check file!");
                return;
            } else if (!file.exists() || file.isDirectory()) {
                response.getWriter().println("file is error , please check file!");
                return;
            }
            log.error("下載-{}-開始", file.getName());

            response.reset();
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + new String((file.getName()).getBytes("gb2312"), "ISO8859-1"));
            InputStream in = new FileInputStream(file);
            OutputStream out = response.getOutputStream();

            byte[] car = new byte[fileBufferSize];
            int l;
            while ((l = in.read(car)) != -1) {
                out.write(car, 0, l);
            }

            out.flush();
            out.close();
            in.close();

            log.error("下載-完成-文件大小:{} , fileBufferSize:{} byte, 耗時:{} ms", VehicleUtils.getFileSize(file),
                    fileBufferSize, System.currentTimeMillis() - start);

            boolean deleteResult = IOUtils.deleteDir(file);
            log.error("下載-完成-刪除本地文件:{}", deleteResult);
        } catch (Exception e) {
            log.error("下載-異常:{}", JSON.toJSON(e));
        }
    }

5.IOUtils

/**
     * 遞歸刪除目錄下的所有文件及子目錄下所有文件
     *
     * @param dir 將要刪除的文件目錄
     * @return boolean Returns "true" if all deletions were successful. If a
     *         deletion fails, the method stops attempting to delete and returns
     *         "false".
     */
    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            //遞歸刪除目錄中的子目錄下
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        // 目錄此時爲空,可以刪除
        return dir.delete();
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章