基于jeecg-boot集成luckysheet记录

简介: 基于jeecg-boot集成luckysheet记录

1、放在public下面,开始用下面的,会报错,找不到相应的js文件,

<!-- luckysheet for bigscreen -->
  <link rel='stylesheet' href='./luckysheet/plugins/css/pluginsCss.css' />
  <link rel='stylesheet' href='./luckysheet/plugins/plugins.css' />
  <link rel='stylesheet' href='./luckysheet/css/luckysheet.css' />
  <script src="./luckysheet/plugins/js/plugin.js"></script>
  <script src="./luckysheet/luckysheet.umd.js"></script>

2、后来修改如下:

<!-- luckysheet for bigscreen -->
  <link rel='stylesheet' href='<%= BASE_URL %>luckysheet/plugins/css/pluginsCss.css' />
  <link rel='stylesheet' href='<%= BASE_URL %>luckysheet/plugins/plugins.css' />
  <link rel='stylesheet' href='<%= BASE_URL %>luckysheet/css/luckysheet.css' />
  <script src="<%= BASE_URL %>luckysheet/plugins/js/plugin.js"></script>
  <script src="<%= BASE_URL %>luckysheet/luckysheet.umd.js"></script>

3、上面好了后,出现下面问题

4、需要在luckysheet.umd.js  这个文件的引入chartmix进行修改,以后发布生产也要修改了,这个就比较麻烦了,以后生成还要修改成生产的,以后考虑从luckysheet源代码生成修改吧。

5、这样就正常了,可以进行图表的展示了,如下:

6、后来发现上面的保存与预览的图标没有显示,这个是iconfont方式,应该是没有引入对,后来检查了 检查了designer的index文件,正确引入下面文件就正常了

<style src="@/assets/bs/iconfont/iconfont.css" />

7、编辑连接数据集,如下图,不过有问题浏览器兼容性还没做好,我用qq浏览器就不行,不能拖拉进去,用谷歌与edge是都可以。

8、预览如下:

9、报表设计页面代码

<!--
 * @Author: lide1202@hotmail.com
 * @Date: 2021-3-13 11:04:24
 * @Last Modified by:   nbacheng
 * @Last Modified time: 2023-09-09
 !-->
<template>
  <div class="layout">
    <div class="layout-left">
      <div class="add-collection">
        数据集管理
        <el-button
          type="text"
          icon="el-icon-circle-plus-outline"
          @click="queryAllDataSet()"
        />
      </div>
      <div>
        <el-collapse
          v-for="(item, indexs) in dataSet"
          :key="indexs"
          v-model="activeNames"
          @change="handleChange"
        >
          <el-collapse-item :title="item.setName" :name="item.id">
            <el-popconfirm
              :title="'确定删除' + item.setName + '吗?'"
              @confirm="del(item)"
            >
              <el-button
                slot="reference"
                type="text"
                icon="el-icon-close"
                class="delect-all"
              />
            </el-popconfirm>
            <draggable
              v-model="item.setParamList"
              :sort="false"
              group="people"
              style="margin-left: 10px"
              @start="onStart(item.setCode, $event)"
            >
              <!-- <transition-group> -->
              <div
                v-for="(i, index) in item.setParamList"
                :key="index"
                class="field-container"
              >
                <div class="aRow">
                  <span>{{ i }}</span>
                </div>
              </div>
              <!-- </transition-group> -->
            </draggable>
          </el-collapse-item>
        </el-collapse>
      </div>
    </div>
    <div class="layout-middle">
      <div class="push_btn">
        <el-tooltip
          class="item"
          effect="dark"
          content="预览"
          placement="bottom-start"
        >
          <el-button type="text" @click="preview()">
            <i class="iconfont iconfuzhi"></i>
          </el-button>
        </el-tooltip>
        <el-tooltip
          class="item"
          effect="dark"
          content="保存"
          placement="bottom-start"
        >
          <el-button type="text" @click="save()">
            <i class="iconfont iconsave"></i>
          </el-button>
        </el-tooltip>
      </div>
      <div
        id="luckysheet"
        style="margin:0px;padding:0px;position:absolute;width:100%;height:95vh;left: 0px;top: 30px;bottom:0px;"
      />
      <div id="qrCode" ref="qrCodeDiv" />
      <img id="barCode" />
    </div>
    <div class="layout-right">
      <el-tabs v-model="activeName" @tab-click="handleClick">
        <el-tab-pane label="基础配置" name="first">
          <el-form ref="rightForm" :model="rightForm" label-width="70px">
            <el-form-item label="坐标">
              <el-input v-model="rightForm.coordinate" />
            </el-form-item>
            <el-form-item label="值">
              <el-input v-model="rightForm.value" />
            </el-form-item>
            <el-form-item label="自动扩展" v-if="rightForm.autoIsShow">
              <el-col :span="12">
                <el-switch
                v-model="rightForm.auto"
                @change="autoChangeFunc($event)" />
              </el-col>
              <el-col :span="12">
                <el-tooltip class="item" effect="dark" content="只针对静态数据的单元格,具体参考文档" placement="top">
                <i class="el-icon-question"> </i>
                </el-tooltip>
              </el-col>
            </el-form-item>
          </el-form>
        </el-tab-pane>
      </el-tabs>
    </div>
    <el-dialog title="数据集管理" :visible.sync="outerVisible">
      <el-table
        ref="multipleTable"
        :data="dataSetData"
        tooltip-effect="dark"
        style="width: 100%;height: 60vh;overflow-y: scroll;"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" />
        <el-table-column label="数据集名称" width="120" prop="setName" />
        <el-table-column prop="setDesc" label="数据集描述" width="180" />
        <el-table-column
          prop="setCode"
          label="数据集编码"
          show-overflow-tooltip
        />
      </el-table>
      <div slot="footer" class="dialog-footer">
        <el-button @click="outerVisible = false">取 消</el-button>
        <el-button type="primary" @click="checkDataSet()">确定 </el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import draggable from "vuedraggable";
import { queryAllDataSet, detail, detailByReportCode } from "@/api/bigscreen/excelreport";
import { addReportExcel, editReportExcel } from "@/api/bigscreen/excelreport";
import ColorPicker from "../components/colorPicker.vue";
// import QRCode from 'qrcodejs2'
// import JsBarcode from 'jsbarcode'
export default {
  name: "Excels",
  components: {
    draggable,
    ColorPicker
  },
  data() {
    return {
      activeName: "first",
      activeNames: ["1"],
      reportId: null,
      accessKey: null,
      reportCode: "",
      options: [],
      sheet: {},
      sheetData: [],
      dataSetData: [],
      reportExcelDto: {
        id: null,
        jsonStr: "",
        setCodes: "",
        setParam: "",
        reportCode: ""
      },
      multipleSelection: [],
      rightForm: {
        coordinate: "",
        value: "",
        r: "",
        c: "",
        auto: false,
        autoIsShow: false
      },
      qrCodeForm: {
        type: "QRCode",
        content: "https://www.baidu.com",
        width: 125,
        height: 125,
        colorDark: "#333333", // 二维码颜色
        colorLight: "#ffffff", // 二维码背景色
        // correctLevel: QRCode.CorrectLevel.L, // 容错率,L/M/H
        ri: 0,
        ci: 0,
        currentSrc: ""
      },
      barCodeForm: {
        type: "BarCode",
        format: "CODE39",
        displayValue: true,
        content: "99999999999",
        lineColor: "#000",
        background: "#fff",
        width: 100,
        height: 40,
        ri: 0,
        ci: 0,
        currentSrc: ""
      },
      formPrintSetting: {
        size: "",
        pixel1: "",
        pixel2: ""
      },
      pixelList: [
        { paper: "A4", width: 210, height: 297 },
        { paper: "A3", width: 297, height: 420 },
        { paper: "Letter", width: 216, height: 279 },
        { paper: "Legal", width: 216, height: 355 },
        { paper: "Executive", width: 184, height: 266 }
      ],
      dataSet: [],
      outerVisible: false,
      printVisible: false,
      pop: false,
      setCode: null,
      draggableFieldLabel: null,
      dialogVisible: false,
      dialogBarCode: false,
      paperList: [],
      // 纸张标识
      paper: "",
      // 纸张宽高
      width: "",
      height: "",
      // 清晰度
      definition: "",
      // 是否套打
      isBackend: "",
      dpi: "",
      pxWidth: "",
      pxHeight: "",
      show: false,
      config: "",
      settings: {},
      qrCodeList: [],
      moveDataelse: {
        x: null,
        y: null
      }
    };
  },
  mounted() {},
  created() {
    this.reportCode = this.$route.query.reportCode;
    this.accessKey = this.$route.query.accessKey;
    this.loadDataSet();
    this.design();
  },
  methods: {
    handleClose() {
      this.printVisible = false;
    },
    handleChange(val) {},
    // 右侧信息配置tabs
    handleClick(tab, event) {},
    async design() {
      // 根据reportCode获取单条报表
      const { code, result } = await detailByReportCode(this.reportCode);
      if (result != null) {
        this.reportId = result.id;
      }
      console.log("result=",result);
      console.log("this.sheetData=",this.sheetData);
      this.sheetData = result == null ? [{}] : JSON.parse(result.jsonStr);
      console.log("this.sheetData=",this.sheetData);
      this.createSheet();
      if (result != null) {
        if (result.setCodes != null && result.setCodes !== "") {
          let dataSetList = result.setCodes.split("|");
          dataSetList.forEach(code => {
            this.dataSetData.forEach(setData => {
              if (code === setData.setCode) {
                this.detail(setData.id);
              }
            });
          });
        }
      }
    },
    //初始化表格
    createSheet() {
      //将vue对象传入
      const that = this;
      const options = {
        container: "luckysheet", // 设定DOM容器的id
        title: "", // 设定表格名称
        lang: "zh", // 设定表格语言
        plugins: ["chart"],
        hook: {
          cellDragStop: function(cell, postion, sheetFile, ctx, event) {
            // console.info("cellDragStop-cell",cell);
            // console.info("cellDragStop-postion", postion);
            // console.info("cellDragStop-sheetFile", sheetFile);
            // console.info("cellDragStop-ctx",ctx);
            // console.info("cellDragStop-event", event);
            // console.log("cellDragStop-draggableFieldLabel", that);
            luckysheet.setCellValue(
              postion.r,
              postion.c,
              that.draggableFieldLabel
            );
          },
          cellMousedown: function(cell, postion, sheetFile, ctx) {
            //单元格点击事件
            that.rightForm.coordinate = postion.r + "," + postion.c;
            that.rightForm.r = postion.r;
            that.rightForm.c = postion.c;
            that.rightForm.value = cell == null ? "" : cell.v;
            that.rightForm.autoIsShow = true
            //判断单元格是否是静态数据并且是合并单元格
            if(cell != null && ( cell.v == undefined || cell.v.indexOf('#{') === -1)){
                that.rightForm.autoIsShow = true
                if(cell.auto != null && cell.auto == '1'){
                  that.rightForm.auto = true
                }else{
                  that.rightForm.auto = false
                }
            }else{
              that.rightForm.auto = false
            }
          }
        },
        data: [
          {
            name: "report", //工作表名称
            color: "", //工作表颜色
            index: 0, //工作表索引
            status: 1, //激活状态
            order: 0, //工作表的下标
            hide: 0, //是否隐藏
            row: 36, //行数
            column: 18, //列数
            defaultRowHeight: 19, //自定义行高
            defaultColWidth: 73, //自定义列宽
            celldata: [], //初始化使用的单元格数据
            config: {
              merge: {}, //合并单元格
              rowlen: {}, //表格行高
              columnlen: {}, //表格列宽
              rowhidden: {}, //隐藏行
              colhidden: {}, //隐藏列
              borderInfo: {}, //边框
              authority: {} //工作表保护
            },
            scrollLeft: 0, //左右滚动条位置
            scrollTop: 315, //上下滚动条位置
            luckysheet_select_save: [], //选中的区域
            calcChain: [], //公式链
            isPivotTable: false, //是否数据透视表
            pivotTable: {}, //数据透视表设置
            filter_select: {}, //筛选范围
            filter: null, //筛选配置
            luckysheet_alternateformat_save: [], //交替颜色
            luckysheet_alternateformat_save_modelCustom: [], //自定义交替颜色
            luckysheet_conditionformat_save: {}, //条件格式
            frozen: {}, //冻结行列配置
            chart: [], //图表配置
            zoomRatio: 1, // 缩放比例
            image: [], //图片
            showGridLines: 1, //是否显示网格线
            dataVerification: {} //数据验证配置
          }
        ]
      };
      options.data = this.sheetData;
      $(function() {
        luckysheet.create(options);
      });
    },
    onStart(setCode, evt) {
      this.setCode = setCode;
      let fieldLabel = evt.item.innerText; // 列名称
      this.draggableFieldLabel = "#{" + this.setCode + "." + fieldLabel + "}";
      console.log("evt", evt);
      console.log("draggableFieldLabel", this.draggableFieldLabel);
    },
    async loadDataSet() {
      const { code, result } = await queryAllDataSet();
      this.dataSetData = result;
      if (code != "200") return;
    },
    doCancel() {
      this.pop = false;
    },
    async save() {
      // console.log(luckysheet.toJson())
      // console.log(luckysheet.getAllSheets())
      // console.log(luckysheet.getSheetData(0))
      const jsonData = luckysheet.getAllSheets();
      for (let i = 0; i < jsonData.length; i++) {
        //清空data数据,以celldata数据为主
        jsonData[i]["data"] = [];
      }
      this.reportExcelDto.jsonStr = JSON.stringify(luckysheet.getAllSheets());
      let setCodeList = [];
      let setParams = {};
      this.dataSet.forEach(code => {
        setCodeList.push(code.setCode);
        if (
          code.dataSetParamDtoList != null &&
          code.dataSetParamDtoList.length > 0
        ) {
          let dataSetParam = {};
          code.dataSetParamDtoList.forEach(value => {
            dataSetParam[value.paramName] = value.sampleItem;
          });
          setParams[code.setCode] = dataSetParam;
        }
      });
      this.reportExcelDto.setParam = JSON.stringify(setParams);
      this.reportExcelDto.setCodes = setCodeList.join("|");
      this.reportExcelDto.reportCode = this.reportCode;
      if (this.reportId == null) {
        const { code } = await addReportExcel(this.reportExcelDto);
        if (code != "200") return;
        this.$message.success("保存成功");
      } else {
        this.reportExcelDto.id = this.reportId;
        const { code } = await editReportExcel(this.reportExcelDto);
        if (code != "200") return;
        this.$message.success("更新成功");
      }
    },
    async detailByReportCode(reportCode) {
      const { code, result } = await detailByReportCode(reportCode);
      if (result != null) {
        this.reportId = result.id;
      }
    },
    async preview() {
      let routeUrl = this.$router.resolve({
        path: "/excelreport/viewer",
        query: { reportCode: this.reportCode }
      });
      window.open(routeUrl.href, "_blank");
    },
    async queryAllDataSet() {
      this.outerVisible = true;
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    checkDataSet() {
      this.outerVisible = false;
      if (this.multipleSelection.length > 1) {
        this.$message({
          message: "一次最多勾选一个数据集",
          type: "warning"
        });
        this.outerVisible = true;
      } else {
        this.detail(this.multipleSelection[0].id);
      }
    },
    async detail(id) {
      const { code, result } = await detail(id);
      if (code != 200) return;
      let flag = true;
      this.dataSet.forEach(value => {
        if (value.setCode === result.setCode) {
          flag = false;
        }
      });
      if (flag) {
        this.dataSet.push(result);
      }
    },
    del(val) {
      for (let i = 0; i < this.dataSet.length; i++) {
        if (this.dataSet[i].setCode === val.setCode) {
          this.dataSet.splice(i, 1);
        }
      }
    },
    autoChangeFunc(auto){
      if(auto){
        luckysheet.setCellValue(this.rightForm.r, this.rightForm.c, { auto: "1"})
      }else{
        luckysheet.setCellValue(this.rightForm.r, this.rightForm.c, { auto: "0"})
      }
    }
  }
};
</script>
<style src="@/assets/bs/iconfont/iconfont.css" />
<style scoped lang="scss">
.position {
  position: absolute;
  z-index: 100;
}
#qrCode,
#barCode {
  display: none;
}
.yulancopy {
  font-size: 16px;
}
.baocun {
  font-size: 17px;
}
.el-collapse {
  position: relative;
  border-top: 0 solid #e6ebf5;
  border-bottom: 0 solid #e6ebf5;
}
.el-collapse-item__header {
  border-bottom: 0 solid #e6ebf5 !important;
}
.delect-all {
  position: absolute;
  top: 10px;
  right: 30px;
  color: #333;
}
.push_btn {
  position: absolute;
  z-index: 100;
  top: 5px;
  left: 3px;
  .iconfont {
    color: black;
  }
}
.add-collection {
  line-height: 30px;
  .el-button {
    font-size: 16px !important;
    vertical-align: middle;
    margin-left: 20px;
  }
}
.layout {
  display: block;
  position: relative;
  margin: 0;
  padding: 0;
  border: 1px solid #d7dde4;
}
.layout-left {
  display: block;
  position: absolute;
  padding: 20px;
  width: 230px;
  min-height: 99.98vh;
  border-right: 1px solid #eee;
  border-color: #e8eaec;
  background: #fff;
  border-radius: 4px;
  font-size: 14px;
  -webkit-transition: all 0.2s ease-in-out;
  transition: all 0.2s ease-in-out;
  top: 0;
  left: 0;
  .field-container {
    display: block;
    position: relative;
    width: 100%;
    margin: 0;
    cursor: pointer;
    line-height: 30px;
    .aRow {
      padding: 0 10px;
      .operation {
        float: right;
        display: none;
        .el-button--text {
          color: #333 !important;
        }
      }
      &:hover {
        .operation {
          display: block;
        }
        background: #f7fafd;
      }
    }
  }
}
.layout-middle {
  display: block;
  position: absolute;
  left: 230px;
  right: 230px;
  width: calc(100% - 460px);
  margin: 0;
  padding: 0;
  .excel-designer {
    display: block;
    position: relative;
    margin: 0;
    padding: 0;
  }
}
.layout-right {
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  padding: 20px;
  width: 230px;
  min-height: 99.98vh;
  border-left: 1px solid #dcdee2;
  border-color: #e8eaec;
  background: #fff;
  border-radius: 4px;
  font-size: 14px;
  -webkit-transition: all 0.2s ease-in-out;
  transition: all 0.2s ease-in-out;
}
</style>

10、viewer代码如下:

<!--
 * @Author: lide1202@hotmail.com
 * @Date: 2021-3-13 11:04:24
 * @Last Modified by:   nbacheng
 * @Last Modified time: 2023-09-09
 !-->
<template>
  <div class="layout">
    <div class="layout-right">
      <div class="block">
        <div class="download">
          <a v-if="reportCode != null" download="xxx.xlsx">
            <el-button type="text" @click="download('gaea_template_excel')">
              <i class="iconfont iconexcel"></i>导出excel
            </el-button>
          </a>
          <a v-if="reportCode != null" download="xxx.pdf">
            <el-button type="text" @click="download('gaea_template_pdf')">
              <i class="iconfont iconpdf"></i>导出pdf
            </el-button>
          </a>
        </div>
        <el-form class="">
          <h2>表格查询</h2>
          <div v-for="(item, num) in tableData2" :key="num + 'excel'">
            <h4>{{ item.name }}</h4>
            <div
              v-for="(son, y) in item.children"
              :key="y + 'excel2'"
              class="search_input"
            >
              <label>{{ son.name }}:</label>
              <el-input v-model="son.value" />
            </div>
          </div>
          <el-button style="width: 100%" @click="searchPreview">查询</el-button>
        </el-form>
        <!--<el-pagination :current-page="currentPage4" :page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, sizes, prev, pager, next, jumper" :total="400" @size-change="handleSizeChange" @current-change="handleCurrentChange" />-->
      </div>
    </div>
    <div class="layout-middle">
      <div
        id="luckysheet"
        style="margin:0px;padding:0px;position:absolute;width:100%;height:95vh;left: 0px;top: 30px;bottom:0px;"
      />
    </div>
  </div>
</template>
<script>
import { preview, exportExcel } from "@/api/bigscreen/excelreport";
export default {
  name: "Login",
  components: {},
  data() {
    return {
      options: {},
      sheet: {},
      reportId: null,
      reportCode: null,
      reportName: null,
      dataSet: null,
      tableData2: [],
      excelData: {},
      params: {
        reportCode: "",
        setParam: ""
      }
    };
  },
  mounted() {
    this.preview();
  },
  created() {
    this.reportCode = this.$route.query.reportCode;
  },
  methods: {
    async searchPreview() {
      const arr = this.toObject(this.tableData2);
      this.params.setParam = JSON.stringify(arr);
      //每次都重新加载需要改成刷新
      this.preview();
    },
    async preview() {
      this.excelData = {};
      this.params.reportCode = this.reportCode;
      const { code, result } = await preview(this.params);
      if (code != 200) return;
      this.reportName = JSON.parse(result.jsonStr).name;
      // 渲染查询表单
      this.params.setParam = JSON.parse(result.setParam);
      const extendArry = [];
      const extendObj = this.params.setParam;
      for (const i in extendObj) {
        const children = [];
        for (const y in extendObj[i]) {
          children.push({ name: y, value: extendObj[i][y] });
        }
        extendArry.push({ name: i, children: children });
      }
      this.tableData2 = extendArry;
      this.excelData = result.jsonStr;
      this.sheetData = result == null ? [{}] : JSON.parse(result.jsonStr);
      // console.log(this.excelData)
      // console.log(this.sheetData)
      this.createSheet();
    },
    async download(val) {
      if (val == "gaea_template_pdf") {
        this.$message("暂不支持pdf");
        return;
      }
      const result = {};
      result["reportCode"] = this.reportCode;
      result["setParam"] = JSON.stringify(this.params.setParam);
      if (val != "") {
        result["exportType"] = val;
      }
      const { code, message } = await exportExcel(result);
      if (code != 200) return;
      this.$message.success(message);
    },
    // 表单封装json
    toObject(val) {
      const objfirst = {};
      const objSecond = {};
      val.forEach(el => {
        el.name ? (objfirst[el.name] = el.children) : "";
      });
      for (const key in objfirst) {
        const newObj = {};
        objfirst[key].map(ev => {
          Object.assign(newObj, { [ev.name]: ev.value });
        });
        objSecond[key] = newObj;
      }
      return objSecond;
    },
    //初始化表格
    createSheet() {
      const options = {
        container: "luckysheet", // 设定DOM容器的id
        title: "", // 设定表格名称
        lang: "zh", // 设定表格语言
        plugins: ["chart"],
        data: [
          {
            name: "report", //工作表名称
            color: "", //工作表颜色
            index: 0, //工作表索引
            status: 1, //激活状态
            order: 0, //工作表的下标
            hide: 0, //是否隐藏
            row: 36, //行数
            column: 18, //列数
            defaultRowHeight: 19, //自定义行高
            defaultColWidth: 73, //自定义列宽
            celldata: [], //初始化使用的单元格数据
            config: {
              merge: {}, //合并单元格
              rowlen: {}, //表格行高
              columnlen: {}, //表格列宽
              rowhidden: {}, //隐藏行
              colhidden: {}, //隐藏列
              borderInfo: {}, //边框
              authority: {} //工作表保护
            },
            scrollLeft: 0, //左右滚动条位置
            scrollTop: 315, //上下滚动条位置
            luckysheet_select_save: [], //选中的区域
            calcChain: [], //公式链
            isPivotTable: false, //是否数据透视表
            pivotTable: {}, //数据透视表设置
            filter_select: {}, //筛选范围
            filter: null, //筛选配置
            luckysheet_alternateformat_save: [], //交替颜色
            luckysheet_alternateformat_save_modelCustom: [], //自定义交替颜色
            luckysheet_conditionformat_save: {}, //条件格式
            frozen: {}, //冻结行列配置
            chart: [], //图表配置
            zoomRatio: 1, // 缩放比例
            image: [], //图片
            showGridLines: 1, //是否显示网格线
            dataVerification: {} //数据验证配置
          }
        ]
      };
      options.data = this.sheetData;
      // console.log(this.sheetData)
      $(function() {
        luckysheet.create(options);
      });
    }
  }
};
</script>
<style src="@/assets/bs/iconfont/iconfont.css" />
<style scoped lang="scss">
.download {
  width: 100%;
  float: left;
  button {
    color: #444;
    width: 90px;
    text-align: left;
    .svg-icon {
      font-size: 16px;
      margin-right: 10px;
    }
  }
}
.block {
  position: relative;
  z-index: 10000;
  top: 0;
  background: #fff;
  width: 100%;
  h2 {
    font-size: 14px;
    line-height: 30px;
  }
  h4 {
    font-size: 12px;
  }
  .search_input {
    font-size: 12px;
    margin-bottom: 10px;
    label {
      line-height: 20px;
    }
  }
}
.layout {
  display: block;
  position: relative;
  margin: 0;
  padding: 0;
}
.layout-middle {
  display: block;
  position: absolute;
  left: 200px;
  right: 0;
  width: calc(100% - 200px);
  margin: 0;
  padding: 0;
  .excel-designer {
    display: block;
    position: relative;
    margin: 0;
    padding: 0;
  }
}
.layout-right {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  padding: 20px;
  width: 200px;
  min-height: 99.98vh;
  border-left: 1px solid #dcdee2;
  border-color: #e8eaec;
  background: #fff;
  border-radius: 4px;
  font-size: 14px;
  -webkit-transition: all 0.2s ease-in-out;
  transition: all 0.2s ease-in-out;
}
</style>


相关文章
|
5天前
|
小程序 调度 数据库
jeecg-boot集成xxl-job调度平台,每秒/每分钟/手动都能执行成功,但是设置固定时间不触发?
jeecg-boot集成xxl-job调度平台,每秒/每分钟/手动都能执行成功,但是设置固定时间不触发?
51 0
|
5天前
|
前端开发 Java 应用服务中间件
从零手写实现 tomcat-08-tomcat 如何与 springboot 集成?
该文是一系列关于从零开始手写实现 Apache Tomcat 的教程概述。作者希望通过亲自动手实践理解 Tomcat 的核心机制。文章讨论了 Spring Boot 如何实现直接通过 `main` 方法启动,Spring 与 Tomcat 容器的集成方式,以及两者生命周期的同步原理。文中还提出了实现 Tomcat 的启发,强调在设计启动流程时确保资源的正确加载和初始化。最后提到了一个名为 mini-cat(嗅虎)的简易 Tomcat 实现项目,开源于 [GitHub](https://github.com/houbb/minicat)。
|
5天前
|
消息中间件 Java Kafka
Springboot集成高低版本kafka
Springboot集成高低版本kafka
|
5天前
|
NoSQL Java Redis
SpringBoot集成Redis解决表单重复提交接口幂等(亲测可用)
SpringBoot集成Redis解决表单重复提交接口幂等(亲测可用)
378 0
|
5天前
|
存储 JSON Java
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
49 2
|
5天前
|
前端开发 Java 应用服务中间件
从零手写实现 tomcat-08-tomcat 如何与 springboot 集成?
本文探讨了Spring Boot如何实现像普通Java程序一样通过main方法启动,关键在于Spring Boot的自动配置、内嵌Servlet容器(如Tomcat)以及`SpringApplication`类。Spring与Tomcat集成有两种方式:独立模式和嵌入式模式,两者通过Servlet规范、Spring MVC协同工作。Spring和Tomcat的生命周期同步涉及启动、运行和关闭阶段,通过事件和监听器实现。文章鼓励读者从实现Tomcat中学习资源管理和生命周期管理。此外,推荐了Netty权威指南系列文章,并提到了一个名为mini-cat的简易Tomcat实现项目。
|
4天前
|
Java 数据库连接 数据安全/隐私保护
springBoot集成token认证,最全Java面试知识点梳理
springBoot集成token认证,最全Java面试知识点梳理
|
5天前
|
消息中间件 JSON Java
RabbitMQ的springboot项目集成使用-01
RabbitMQ的springboot项目集成使用-01
|
5天前
|
搜索推荐 Java 数据库
springboot集成ElasticSearch的具体操作(系统全文检索)
springboot集成ElasticSearch的具体操作(系统全文检索)
|
5天前
|
消息中间件 Java Spring
Springboot 集成Rabbitmq之延时队列
Springboot 集成Rabbitmq之延时队列
7 0

热门文章

最新文章