首页 > 系统相关 >国产linux系统(银河麒麟,统信uos)使用 PageOffice 国产版在线打开 word文件自定义模板中数据区域

国产linux系统(银河麒麟,统信uos)使用 PageOffice 国产版在线打开 word文件自定义模板中数据区域

时间:2024-07-19 10:54:20浏览次数:21  
标签:uos 自定义 color drName 国产 区域 var border 模板

国产linux系统(银河麒麟,统信uos)使用 PageOffice 国产版在线打开 pdf 文件
PageOffice 国产版 :支持信创系统,支持银河麒麟V10和统信UOS,支持X86(intel、兆芯、海光等)、ARM(飞腾、鲲鹏、麒麟等)芯片架构。

本示例关键代码的编写位置
Vue+Springboot

注意
本文中展示的代码均为关键代码,复制粘贴到您的项目中,按照实际的情况,例如文档路径,用户名等做适当修改即可使用。

在实际的Word文档开发中,经常需要自动填充数据到Word模板中,以生成动态的Word文档,那么应该如何编辑制作Word模板呢?

方法一:直接打开Word文件插入书签

假如使用数据区域(DataRegion)来定义模板中动态填充数据的位置,那么直接打开一个Word文件,在其中添加“PO_”开头的书签即可制作word模板。例如,打开一个Word文件后,可以通过选中需要标记为书签的文字,例如“[姓名]”,然后点击Word菜单中的“插入”-“书签”来添加书签,在弹出的“书签”对话框中,输入新书签的名称PO_userName,并点击右侧的“添加”按钮,即可完成一个数据区域的定义。效果如下图所示:
image

注意
书签名必须以“PO_”开头,并由字母和数字组成,但中间不能有空格。

Word模板中需要多少个动态填充数据的位置,就在Word文件中相应的位置插入多少个“PO_”开头的书签即可,这种制作word模板的方法操作简单,但是常常用于新项目开发中开发人员定义Word模板。开发人员知道在Word模板的哪个位置要插入哪个数据,就比如上面所说的“姓名”的位置需要插入系统里的数据UserName,所以就定义了一个PO_userName的书签,然后就可以编程调用PageOffice接口,把web系统里的UserName赋值给数据区域PO_userName,其他的数据区域也是相同的处理方式。但是项目发布后用户需求变动,希望修改Word模板或创建新的Word模板,用户怎么知道如何制作word模板呢?如何插入书签?如何命名书签?哪些名字的书签与哪些系统数据是对应的呢?

方法二:给用户提供自定义模板功能

开发人员可以给系统增加一个模板管理的模块,拥有模板管理权限的用户可以查看系统中的模板列表,可以新增、删除和在线编辑模板,开发人员通过程序定义好编辑某种模板时可能用到的所有数据区域,用户自定义编辑Word模板时可以把全部数据区域插入到模板的相应位置,也可以根据实际需求只使用部分数据区域,但Word模板中数据区域的数量总是开发人员定义的数据区域集合的子集,这样一来就能实现开发人员与用户的分工合作。

比如说web系统中合同模板的制作,合同模板中可能会用到的数据有:合同编号、购货单位、供货单位、产品名称、购货单位地址、供货单位地址、担保人、担保人手机,那么开发人员可以编写代码定义好这些数据区域,让用户在线打开编辑模板时,只能在Word模板中插入这些系统定义好的数据区域,这样做不但实现了开发人员与用户的一种约定,而且规范了用户的操作。

  1. 开发人员编写代码定义好编辑模板时所有可用的数据区域:
    开发人员调用PageOffice提供的defineDataRegion方法定义用户编辑模板时所有可用的数据区域,第一个参数是数据区域名称,也就是word书签的名称,第二个参数是数据区域在Word文件中显示的文字内容,格式没有特殊要求。下面示例代码中显示的文字内容都使用了中括号(也可以使用其他符号),仅仅是为了便于用户直观的查看Word模板中哪些位置是插入的数据区域。
WordDocument doc = new WordDocument();
doc.getTemplate().defineDataRegion("PO_Guarantor", "[担保人]");
doc.getTemplate().defineDataRegion("PO_SupplierAddress", "[供货单位地址]");
doc.getTemplate().defineDataRegion("PO_BuyerAddress", "[购货单位地址]");
doc.getTemplate().defineDataRegion("PO_No", "[合同编号]");
doc.getTemplate().defineDataRegion("PO_GuarantorPhone", "[担保人手机]");
doc.getTemplate().defineDataRegion("PO_ProductName", "[产品名称]");
doc.getTemplate().defineDataRegion("PO_Buyer", "[购货单位]");
doc.getTemplate().defineDataRegion("PO_Supplier", "[供货单位]");
  1. 用户编辑模板时,直接使用开发人员定义好的数据区域来制作模板:
    由于用户操作习惯和Web系统界面风格的不同,开发人员可以根据实际需求在自己的Web项目中选择实现下面的一种编辑模板效果。

用户在线编辑模板效果1: 把数据区域列表和Word文件编辑界面,一左一右放到同一个页面窗口中,用户在右侧Word文件中点击定位光标到需要插入数据的位置,然后在左侧选择相应的数据区域,添加到当前位置即可。比如下图所示:在Word中需要插入“合同编号”的位置点击一下鼠标,然后在左侧“待添加区域”中点击数据区域“PO_No”的添加按钮,数据区域“PO_No”就被插入到了Word光标所在位置,且“待添加区域”列表中的数据区域“PO_No”被移动到“已添加区域”的列表中。
image

此效果所用到的html、css和javascript代码:

<style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
        }
		div{
			 box-sizing: border-box; 
		}
        #left-container {
            width: 360px;
            display: flex;
            flex-direction: column;
            border-right: 2px solid #ccc;
            padding: 20px;
            overflow: auto;
            font-size: 12px;
            height: 90vh;
        }
        #right-container {
            flex: 1;
            padding: 0px;
            height: 95vh;
        }
        #podiv{
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }
        #left-title{
            text-align: center;
            font-size: 16px;
            padding-bottom: 10px;
            margin-bottom: 10px;
            border-bottom: solid 1px #ccc;
        }

        .input-group {
            margin-bottom: 20px;
            display: flex;
            align-items: center;
        }
        input[type="text"] {
            width: 70%;
            padding: 10px;
            margin-top: 5px;
            box-sizing: border-box;
            border: 1px solid #ccc;
            border-radius: 5px;
            font-size: 12px;
            outline: none;
        }

        input[type="submit"] {
            width: 80px;
            padding: 10px;
            margin-top: 5px;
            margin-left: 10px;
            box-sizing: border-box;
            border: none;
            border-radius: 5px;
            background-color: #4E6EF2;
            color: white;
            font-size: 12px;
            outline: none;
            cursor: pointer;
        }
        /* 表格样式 */
        table {
            border-collapse: collapse;
            width: 100%;
        }

        th, td {
            padding: 8px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }

        th {
            position: sticky;
            top: 0;
            background-color: #f2f2f2;
            z-index: 1;
        }

        /* 容器样式 */
        .container {
            height: 300px;
            overflow: auto;
            border: solid 1px #ccc;
            scrollbar-width: thin;
            scrollbar-color: #888 #f2f2f2;
        }

        /* 滚动条样式 */
        .container::-webkit-scrollbar {
            width: 8px;
        }

        .container::-webkit-scrollbar-track {
            background: #f2f2f2;
        }

        .container::-webkit-scrollbar-thumb {
            background-color: #888;
            border-radius: 4px;
        }

        .container::-webkit-scrollbar-thumb:hover {
            background-color: #555;
        }
        .delete-button {
            padding: 6px 6px;
            border: none;
            border-radius: 5px;
            background-color: #f44336;
            color: white;
            font-size: 12px;
            cursor: pointer;
        }
        .delete-button:hover {
            background-color: #d32f2f;
        }

        .normal-button {
            padding: 6px 6px;
            border: none;
            border-radius: 5px;
            background-color: #4E7EFF;
            color: white;
            font-size: 12px;
            cursor: pointer;
        }
        .normal-button:hover {
            background-color: #4E6EF2;
        }

        .locate-button {
            padding: 6px 6px;
            border: none;
            border-radius: 5px;
            background-color: #0abb87;
            color: white;
            font-size: 12px;
            cursor: pointer;
        }
        .locate-button:hover {
            background-color: #0a9966;
        }
    </style>

    <script type="text/javascript">
        //控件中的一些常用方法都在这里调用,比如保存,打印等等
        function OnPageOfficeCtrlInit() {
            pageofficectrl.AddCustomToolButton("保存", "Save", 1);
        }
        function Save() {
            pageofficectrl.WebSave();
        }
        //加载数据
        function loadData() {
            var kWord1 = document.getElementById("inputKey1").value;
            var kWord2 = document.getElementById("inputKey2").value;

            var definedDataRegionJson = pageofficectrl.word.DataRegionsDefinedAsJson;
            var dataRegionJson = pageofficectrl.word.DataRegionsAsJson;
            searchDataRegion(definedDataRegionJson, dataRegionJson, kWord1);
            searchDataRegion2(dataRegionJson, kWord2);
        }

        //加载上方数据列表
        function searchDataRegion(drDefinedJson, drJson, s){
            var tb1 = document.getElementById("bkmkTable");
            var rCount = tb1.rows.length;
            for (var i = 1; i < rCount; i++) {
                tb1.deleteRow(1);
            }

            if('' == drDefinedJson) drDefinedJson = '[]';
            let definedDataRegionObj = JSON.parse(drDefinedJson);
            let dataRegionsJson = drJson;
            if('' == dataRegionsJson) dataRegionsJson = '[]';
            let dataRegionsObj = JSON.parse(dataRegionsJson);

            var oTable = document.getElementById("bkmkTable");
            var tbodyObj = oTable.tBodies[0];
            for(let key in definedDataRegionObj ){
                let drName = definedDataRegionObj[key].name;
                let drCaption =  definedDataRegionObj[key].caption;
                //alert("数据区域:"+drName+"; 值:"+drValue);

                let bFind = false;
                for(let k in dataRegionsObj){
                    if(dataRegionsObj[k].name == drName){
                        bFind = true;
                        break;
                    }
                }

                if(bFind) continue;

                if (drName.toLocaleLowerCase().indexOf(s.toLocaleLowerCase()) > -1) {
                    var oTr = tbodyObj.insertRow();
                    var oTd = oTr.insertCell();
                    oTd.innerHTML = drName;
                    oTd = oTr.insertCell();
                    oTd.innerHTML = drCaption;
                    oTd = oTr.insertCell();
                    oTd.innerHTML = '<button class="normal-button" onclick="addDataRegion(\''+drName+'\',\''+drCaption+'\');loadData();">添加</button>';
                }
            }
        }

        //加载下方数据列表
        function searchDataRegion2(drJson, s) {
            //删除所有行
            var tb1 = document.getElementById("bkmkTable2");
            var rCount = tb1.rows.length;
            for (var i = 1; i < rCount; i++) {
                tb1.deleteRow(1);
            }

            let dataRegionsJson = drJson;
            if('' == dataRegionsJson) dataRegionsJson = '[]';
            let dataRegionsObj = JSON.parse(dataRegionsJson);
            var oTable = document.getElementById("bkmkTable2");
            var tbodyObj = oTable.tBodies[0];
            for(let key in dataRegionsObj ){
                let drName = dataRegionsObj[key].name;

                if (drName.toLocaleLowerCase().indexOf(s.toLocaleLowerCase()) > -1) {
                    var oTr = tbodyObj.insertRow();
                    var oTd = oTr.insertCell();
                    oTd.innerHTML = drName;
                    oTd = oTr.insertCell();
                    oTd.innerHTML = '<button class="delete-button" onclick="deleteDataRegion(\''+ drName +'\');loadData();">删除</button> <button class="locate-button" onclick="locateDataRegion(\''+ drName +'\');">定位</button>';
                }
            }

        }

        function locateDataRegion(drName) {
            pageofficectrl.word.LocateDataRegion(drName);
        }

        function deleteDataRegion(drName){
            pageofficectrl.word.DeleteDataRegion(drName);
        }

        function addDataRegion(drName, drValue){
            pageofficectrl.word.AddDataRegion(drName, drValue);
        }

        function AfterDocumentOpened() {
            loadData();
        }
    </script>

<div id="left-container">
    <div id="left-title">定义数据区域</div>
    <div class="input-group">
        <span style="font-size: 14px;">待添加区域:</span><input type="text" id="inputKey1" oninput="loadData();" placeholder="请输入数据区域关键字搜索">
    </div>
    <div class="container">
        <table id="bkmkTable">
            <thead>
            <tr>
                <th>数据区域</th>
                <th>显示文字</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            <!-- 数据行 -->
            </tbody>
        </table>
    </div>
    <div class="input-group" style="margin-top: 20px">
        <span style="font-size: 14px;">已添加区域:</span><input type="text" id="inputKey2" oninput="loadData();" placeholder="请输入数据区域关键字搜索">
    </div>
    <div class="container">
        <table id="bkmkTable2">
            <thead>
            <tr>
                <th>数据区域</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            <!-- 数据行 -->
            </tbody>
        </table>
    </div>
</div>

用户在线编辑模板效果2: 编辑模板的界面只显示Word文件,添加数据区域时,弹出一个非模态的数据区域选择框,然后用户就可以在Word文件中点击定位光标到需要插入数据的位置,再点击数据区域选择框中未使用过的数据区域进行添加。比如下图所示:点击“定义数据区域”按钮,弹出数据区域选择框,然后定位光标到Word中需要插入“购货单位”的位置,然后在数据区域选择框左侧“待添加区域”中点击数据区域“PO_Buyer”的添加按钮,数据区域“PO_Buyer”就被插入到了Word光标所在位置,且“待添加区域”列表中的数据区域“PO_Buyer”被移动到“已添加区域”的列表中。
image

此效果所用到的数据区域选择框DataRegionDlg.htm的页面代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>定义数据区域</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            font-size:10px;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100%;
            background-color: #f5f5f5;
        }

        .container {
            display: flex;
            width: 99%;
            max-width: 100%;
        }

        .left, .right {
            background-color: #fff;
            padding:0 10px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        .left{
            flex-grow: 7;
        }
        .right {
            flex-grow: 3;
        }

        h5 {
            margin-bottom: 10px;
        }

        input[type="text"], textarea {
            width: 90%;
            padding: 10px;
            margin-bottom: 15px;
            border-radius: 5px;
            border: 1px solid #ccc;
        }

        /* 表格样式 */
        table {
            border-collapse: collapse;
            width: 100%;
        }

        th, td {
            padding: 8px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }

        th {
            position: sticky;
            top: 0;
            background-color: #f2f2f2;
            z-index: 1;
        }

        /* 容器样式 */
        .tbcontainer {
            height: 300px;
            overflow: auto;
            border: solid 1px #ccc;
            scrollbar-width: thin;
            scrollbar-color: #888 #f2f2f2;
        }

        /* 滚动条样式 */
        .tbcontainer::-webkit-scrollbar {
            width: 8px;
        }

        .tbcontainer::-webkit-scrollbar-track {
            background: #f2f2f2;
        }

        .tbcontainer::-webkit-scrollbar-thumb {
            background-color: #888;
            border-radius: 4px;
        }

        .tbcontainer::-webkit-scrollbar-thumb:hover {
            background-color: #555;
        }
        .delete-button {
            padding: 3px 3px;
            border: none;
            border-radius: 3px;
            background-color: #f44336;
            color: white;
            font-size: 10px;
            cursor: pointer;
        }
        .delete-button:hover {
            background-color: #d32f2f;
        }

        .normal-button {
            padding: 3px 3px;
            border: none;
            border-radius: 3px;
            background-color: #4E7EFF;
            color: white;
            font-size: 10px;
            cursor: pointer;
        }
        .normal-button:hover {
            background-color: #4E6EF2;
        }

        .locate-button {
            padding: 3px 3px;
            border: none;
            border-radius: 3px;
            background-color: #0abb87;
            color: white;
            font-size: 10px;
            cursor: pointer;
        }
        .locate-button:hover {
            background-color: #0a9966;
        }
    </style>
</head>
<body>
<div class="container">
    <div class="left">
        <h5>待添加区域:</h5>
        <input type="text" id="inputKey1" oninput="loadData();" placeholder="请输入数据区域关键字搜索" />
        <div class="tbcontainer">
            <table id="bkmkTable">
                <thead>
                <tr>
                    <th>数据区域</th>
                    <th>显示文字</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                <!-- 数据行 -->
                </tbody>
            </table>
        </div>
    </div>
    <div class="right">
        <h5>已添加区域:</h5>
        <input type="text" id="inputKey2" oninput="loadData();" placeholder="请输入数据区域关键字搜索" />
        <div class="tbcontainer">
            <table id="bkmkTable2">
                <thead>
                <tr>
                    <th>数据区域</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                <!-- 数据行 -->
                </tbody>
            </table>
        </div>
    </div>
</div>

<script>

    let definedDataRegionJson = window.external.UserParams;

    //加载数据
    function loadData() {
        var kWord1 = document.getElementById("inputKey1").value;
        var kWord2 = document.getElementById("inputKey2").value;

        var dataRegionJson = pageofficectrl.word.DataRegionsAsJson;
        searchDataRegion(definedDataRegionJson, dataRegionJson, kWord1);
        searchDataRegion2(dataRegionJson, kWord2);
    }

    //加载待添加区域列表
    function searchDataRegion(drDefinedJson, drJson, s){
        var tb1 = document.getElementById("bkmkTable");
        var rCount = tb1.rows.length;
        for (var i = 1; i < rCount; i++) {
            tb1.deleteRow(1);
        }

        if('' == drDefinedJson) drDefinedJson = '[]';
        var definedDataRegionObj = JSON.parse(drDefinedJson);
        var dataRegionsJson = drJson;
        if('' == dataRegionsJson) dataRegionsJson = '[]';
        var dataRegionsObj = JSON.parse(dataRegionsJson);

        var oTable = document.getElementById("bkmkTable");
        var tbodyObj = oTable.tBodies[0];
        for(let key in definedDataRegionObj ){
            let drName = definedDataRegionObj[key].name;
            let drCaption =  definedDataRegionObj[key].caption;
            //alert("数据区域:"+drName+"; 值:"+drValue);

            let bFind = false;
            for(let k in dataRegionsObj){
                if(dataRegionsObj[k].name == drName){
                    bFind = true;
                    break;
                }
            }

            if(bFind) continue;

            if (drName.toLocaleLowerCase().indexOf(s.toLocaleLowerCase()) > -1) {
                var oTr = tbodyObj.insertRow();
                var oTd = oTr.insertCell();
                oTd.innerHTML = drName;
                oTd = oTr.insertCell();
                oTd.innerHTML = drCaption;
                oTd = oTr.insertCell();
                oTd.innerHTML = '<button class="normal-button" onclick="addDataRegion(\''+drName+'\',\''+drCaption+'\');loadData();">添加</button>';
            }
        }
    }

    //加载已添加区域列表
    function searchDataRegion2(drJson, s) {
        //删除所有行
        var tb1 = document.getElementById("bkmkTable2");
        var rCount = tb1.rows.length;
        for (var i = 1; i < rCount; i++) {
            tb1.deleteRow(1);
        }

        let dataRegionsJson = drJson;
        if('' == dataRegionsJson) dataRegionsJson = '[]';
        let dataRegionsObj = JSON.parse(dataRegionsJson);
        var oTable = document.getElementById("bkmkTable2");
        var tbodyObj = oTable.tBodies[0];
        for(let key in dataRegionsObj ){
            let drName = dataRegionsObj[key].name;

            if (drName.toLocaleLowerCase().indexOf(s.toLocaleLowerCase()) > -1) {
                var oTr = tbodyObj.insertRow();
                var oTd = oTr.insertCell();
                oTd.innerHTML = drName;
                oTd = oTr.insertCell();
                oTd.innerHTML = '<button class="delete-button" onclick="deleteDataRegion(\''+ drName +'\');loadData();">删除</button> <button class="locate-button" onclick="locateDataRegion(\''+ drName +'\');">定位</button>';
            }
        }

    }

    function locateDataRegion(drName) {
        pageofficectrl.word.LocateDataRegion(drName);
    }

    function deleteDataRegion(drName){
        pageofficectrl.word.DeleteDataRegion(drName);
    }

    function addDataRegion(drName, drValue){
        pageofficectrl.word.AddDataRegion(drName, drValue);
    }

    loadData();
</script>
</body>
</html>


自定义工具栏“定义数据区域”按钮的相关代码:

javascript
function Save() {
    pageofficectrl.WebSave();
}

function ShowDefineDataRegions() {
    var drDefinedJson = pageofficectrl.word.DataRegionsDefinedAsJson;
    pageofficectrl.ShowHtmlModelessDialog("DataRegionDlg.htm", drDefinedJson, "left=300px;top=390px;width=560px;height=410px;frame:no;");
}

function OnPageOfficeCtrlInit() {
    pageofficectrl.AddCustomToolButton("保存", "Save", 1);
    pageofficectrl.AddCustomToolButton("定义数据区域", "ShowDefineDataRegions", 10);
}

在最终需要动态填充数据到word模板中生成正式合同文件时,开发人员只管编写代码给所有的数据区域赋值即可,无需关心用户自定义的word模板中到底使用了哪些数据区域,因为那些没有使用的数据区域会被PageOffice自动忽略掉;而最终用户也可以根据自己的实际需要定义好word模板中各项数据及其位置,无需关心数据从哪里来,也不用事事都与开发人员沟通,当业务需求发生简单的变化时,可以自主修改word模板来满足新的需求。这样一来,不管是用户还是开发人员,都在一定程度上从这种纷杂多变的业务需求中解脱出来。

参考链接:用户自定义模板中数据区域

标签:uos,自定义,color,drName,国产,区域,var,border,模板
From: https://www.cnblogs.com/qq742655/p/18311035

相关文章

  • vxe-grid 自定义工具栏,去掉原来的工具栏
    1、如果要自定义那么就少不了slots了2、代码<vxe-gridref="tableRef"v-bind="gridOptions":folding-all="true"><template#toolbar_buttons><Selectv-model:value="searchForm.fieldname&......
  • echarts自定义胶囊柱图并设置每个柱子的渐变色
    drawCharts(){letmyChart=echarts.init(document.getElementById('main'));letoption={tooltip:{trigger:'axis',axisPointer:{type:'line'}......
  • 自定义异常
    了解手动抛出异常对象和自动抛出thrownew异常类的对象throws异常类对象,两者区别throw在方法中用throws在声明时用使用场景多个方法并列,可以使用throw自定义异常继承于现有的异常体系。通常继承于RuntimeException\Exception通常提供几个重载的构造器提供一个全......
  • 微信小程序毕业设计-国产动漫论坛系统项目开发实战(附源码+论文)
    大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。......
  • pytorch 自定义 dataloader 维度不对齐+广播机制导致不易察觉 bug
    很简单,自定义了一个dataloader,出现以下不易察觉buginputs维度:[bs,4],这个没问题labels维度:正确应该是[bs,1],但是dataloader出来是[bs]模型的outputs维度:[bs,1]如果用torch.mean(torch.abs(labels-outputs))计算L1Loss/MAE由于pytorch的广播机制,torch.ab......
  • Qt实现仪表盘-自定义控件
            仪表盘在很多汽车和物联网相关的系统中很常用,本文就来介绍一下Qt 仪表盘的实现示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。一、简述         使用Qt绘制一个仪表盘,用来显示当前的温度,绘制刻度、绘制数字......
  • QT利用QPainter实现自定义圆弧进度条组件
               在可视化应用中,弧形进度条应用也比较广泛,本文示例封装了一个可复用、个性化的弧形进度条组件。本文示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。主要结构就是外围一圈圆角进度,中间加上标题和对应进度的百分比,进度条的起始角......
  • 2024-07-18 给vue项目添加自定义路由守卫
    要配置路由守卫要使用到vue-router,它是Vue.js官方的路由管理器,主要用于帮助开发者构建单页面应用(SinglePageApplication,简称SPA)。步骤一:新建路由文件,文件名随意,建议叫router.ts,规范一点//router.tsimport{createRouter,createWebHashHistory}from"vue-router";i......
  • 使用Spring Boot AOP和自定义注解优雅实现操作日志记录
    使用SpringBootAOP和自定义注解优雅实现操作日志记录大家好,今天我们来聊聊如何在SpringBoot项目中,通过AOP(面向切面编程)和自定义注解,优雅地实现操作日志记录。操作日志对于系统的可维护性和安全性至关重要,它能帮助我们追踪用户行为,排查问题。什么是AOP?AOP,全称Aspect-Oriented......
  • 自定义转换器
    我们要自定义转换器就要声明一个类,然后继承父类的BaseConverter需要用正则表达式的需要重写父类的regex代码实现: fromflaskimportFlaskfromwerkzeug.routingimportBaseConverterapp=Flask(__name__)classCustomConverter(BaseConverter):#自定义转换器要继承......