美文网首页nodejsweb前端
如何将word转为好看的导航网页?

如何将word转为好看的导航网页?

作者: 姜治宇 | 来源:发表于2021-11-29 15:29 被阅读0次
    最近接到这样一个需求,产品那边用word写了一个用户手册,要求转为导航类网页,样式大概是这样的: page.png

    手册比较大,word大概有一百多m的样子,从头开发网页的话太浪费时间,能否自动生成呢?
    自动生成的思路是:
    1、开发一个上、左、右的导航网页,头部和左侧目录导航自己定制开发,而右侧使用word直接转成的html。

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>导航页</title>
    </head>
    <body>
        <div style="float:left;width:30%;height:500px;background:red;">
            <a onclick="toPage('b.html#A1')">1、《热爱生命》</a><br/>
            <a onclick="toPage('b.html#A2')" >2、《雪狼》</a><br/>
            <a onclick="toPage('b.html#A3')" >3、《荒野的呼唤》</a><br/>
            <a onclick="toPage('b.html#A4')" >4、《海狼》</a><br/>
        </div>
        <div  style="float:right;width:60%;height:500px;background:green;">
            <iframe src="b.html#A2" id="frm" frameborder="0" style="width:100%;height:100%;"></iframe>
        </div>
    </body>
    <script>
        function toPage(url){
            var page = document.getElementById('frm');
            page.setAttribute('src',url);
        }
    </script>
    

    我们将word右键另存为,保存为网页的形式。
    注意,word默认保存的是gb2312的编码,而我们常用的是utf8编码,需要这样转一下。

    a.png
    保存完之后,会有一个htm文件和一个文件夹。打开网页,我们发现自动生成的目录是这样的: b.png
    一级二级三级菜单都是扁平结构的,而我们一般开发的目录菜单,都是带层级的嵌套ul li结构。
    所以难点就在于:
    如何将word生成的目录,与我们开发的左侧导航联系起来?
    以下是我的解决方案。主要是利用node的cheerio包,将扁平结构的目录,转成带层级的数据结构,然后再生成树结构。
    目录处理完后,将word生成的目录部分去掉即可。
    const fs = require('fs');
    const cheerio = require('cheerio');
    
    //=================================生成内容================================================//
    async function handleContent(path,destPath) { //需清除word的目录
        let newHtml = await fsRead(path);
        let $ = cheerio.load(newHtml);
        let bodyPart = $('body').html();
    
        let $d = cheerio.load(bodyPart);
        $d('.MsoToc1').parent().replaceWith('');
        $d('.MsoTocHeading').replaceWith('');
        $d('.MsoTitle').replaceWith('');
        $d('body').append(`<script src="../layout/jquery.min.js"></script>
        <script>
        $('img').parents('p').removeAttr('style').css('text-align','left');
        </script>`);
        let res = await fsWrite(destPath, $d.html());//生成处理过的html
        if (res === 'ok') {
            console.log('内容处理完毕');
        } else {
            console.log('内容处理出错了');
        }
    }
    
    
    //=================================生成目录================================================//
    async function handlecatalogue(path, destPath) {
        let content = await fsRead(path);
        let listHtml = getHtml();//读取目录文件
        let arr: any[] = [];
        let count = 0;
        let count1 = 0;
        let count2 = 0;
        let $ = cheerio.load(content);
        let $list = cheerio.load(listHtml);
    
        $('.MsoTocHeading').eq(0).siblings('p').each((key, element) => {
    
            let className = $(element).attr('class');
    
            if (className === 'MsoToc1') { // 一级目录
                $(element).find('a').each((k, v) => {
                    count++;
                    let url = $(v).attr('href');
                    let title = $(v).text().replace(/\.{1,}\s+\d+/ig, '');
                    let obj = { id: count, title: title, url: url, parent: 0 };
                    arr.push(obj);
    
                    count1 = count;
    
                });
    
            }
            if (className === 'MsoToc2') { // 一级目录
                $(element).find('a').each((k, v) => {
                    count++;
                    let url = $(v).attr('href');
                    let title = $(v).text().trim().replace(/\.{1,}\s+\d+/ig, '');
                    let obj = { id: count, title: title, url: url, parent: count1 };
                    arr.push(obj);
                    count2 = count;
    
                });
    
    
            }
            if (className === 'MsoToc3') { // 一级目录
                $(element).find('a').each((k, v) => {
                    count++;
                    let url = $(v).attr('href');
                    let title = $(v).text().trim().replace(/\.{1,}\s+\d+/ig, '');
                    let obj = { id: count, title: title, url: url, parent: count2 };
                    arr.push(obj);
    
                });
            }
        });
    
        let newarr = convertData(arr);
        let nodes = createTree(newarr, true);
        $list('.left-part').html(nodes);
        let res = await fsWrite(destPath, $list.html());//生成处理过的html
        if (res === 'ok') {
            console.log('目录处理完毕');
        } else {
            console.log('目录处理出错了');
        }
    }
    
    
    
    
    
    //==================================生成html=======================================================//
    function createTree(list, flag = false) {
    
        if (Array.isArray(list)) {
    
            let str = '';
            if (flag) {
                str = `<ul class="lp-cont">`;//最外层ul
            } else {
                str = `<ul class="lp-cont-child">`;
            }
            list.forEach(item => {
                str += `<li onclick="toPage('./pages/book.html${item.url}')">${item.title}`;
                if (item.children && item.children.length > 0) {
                    str += createTree(item.children);
                }
                str += `</li>`;
            });
            str += `</ul>`;
            return str;
        }
    
    
    
    }
    //======================================生成tree data============================================//
    function convertData(jsonData) {
        var result: any[] = [], temp = {}, i = 0, j = 0, len = jsonData.length;
        for (; i < len; i++) {
            temp[jsonData[i]['id']] = jsonData[i] // 以id作为索引存储元素,可以无需遍历直接定位元素
        }
        for (; j < len; j++) {
            var currentElement = jsonData[j]
            var tempCurrentElementParent = temp[currentElement['parent']] // 临时变量里面的当前元素的父元素 parentId 父级ID
            if (tempCurrentElementParent) { // 如果存在父元素
                if (!tempCurrentElementParent['children']) { // 如果父元素没有chindren键
                    tempCurrentElementParent['children'] = [] // 设上父元素的children键
                }
                tempCurrentElementParent['children'].push(currentElement) // 给父元素加上当前元素作为子元素
            } else { // 不存在父元素,意味着当前元素是一级元素
                result.push(currentElement);
            }
        }
    
        return result;
    }
    
    //======================================读文件====================================================//
    function fsRead(filename) {
        return new Promise((resolve, reject) => {
            fs.readFile(filename, { flag: 'r', encoding: 'utf-8' }, function (err, data) {
                if (err) {
                    reject(err);
                } else {
                    resolve(data);
                }
            })
        })
    }
    
    //===================================写文件===================================================//
    function fsWrite(path, content) {
        return new Promise((resolve, reject) => {
            fs.writeFile(path, content, { flag: 'w', encoding: 'utf-8' }, (err) => {
                if (err) {
                    reject(err);
                } else {
                    resolve('ok');
                }
            })
        })
    }
    //====================================目录文件=====================================================//
    function getHtml() {
        return `
    <!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{
            margin:0;
            padding:0;
        }
        ul{
            margin:0;
            padding:0;
            list-style:none;
            /* margin-bottom:15px; */
        }
        ul li{
            position: relative;
            line-height:40px;
        }
        
        .container{
            width:100%;
            height:100%;
            display:flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
        }
        .header{
            width:inherit;
            height:50px;
            display:flex;
            flex-direction: row;
            align-items: center;
            justify-content: flex-start;
            color:#fff;
            background:#000;
        }
        .h-back{
            
            width:20px;
            height:20px;
            margin-left:15px;
            margin-right:20px;
        
        }
        .content{
            width:inherit;
            height:calc(100vh - 50px);
            display:flex;
            flex-direction: row;
        
            justify-content: center;
        
        }
        .left-part{
            width:30%;
        
            display:flex;
            flex-direction: column;
            overflow-x:hidden;
            overflow-y: auto;
            
        }
        .lp-title{
            font-weight: 400;
            color: #666666;
            margin-left:180px;
            margin-top:30px;
        }
        .lp-cont{
            margin-left:180px;
            margin-top:15px;
        }
        .lp-cont li{
            font-size:16px;
            font-weight: 400;
        
            /* color: #097EFF; */
            color:#333333;
           
        }
        .lp-cont li:hover{
            cursor: pointer;
        }
        .right-part{
            width:70%;
            margin-left:16px;
        }
        .clear-bar{
            width: 183px;
            height: 1px;
            background: #000000;
            opacity: 0.1;
            margin-top:10px;
        }
        .lp-cont-child{
            display:none;
            position: relative;
        
            left:16px;
        }
        .lp-cont-child li{
            font-size:14px;
        }
        
        .lp-cont-cate::before{
            content:"";
            
            position: absolute;
            top:17px;
            left: -15px;
            border-top:6px solid #999999;
            border-left:5px solid transparent;
            border-right:5px solid transparent;
            -webkit-transform: rotate(-90deg);
            -moz-transform: rotate(-90deg);
             -ms-transform: rotate(-90deg);
              -o-transform: rotate(-90deg);
                 transform: rotate(-90deg); 
            
        }
        .li-active::before{
        
            -webkit-transform: rotate(0deg);
               -moz-transform: rotate(0deg);
                -ms-transform: rotate(0deg);
                 -o-transform: rotate(0deg);
                    transform: rotate(0deg); 
        }
        .active{
        
            color: #097EFF !important;
        }
        </style>
        <script src="./layout/jquery.min.js"></script>
    </head>
    
    <body>
        <div class="container">
            <div class="header">
                <img class="h-back" src="./layout/arrow-left.png" onclick="goBack()" />
                <div class="h-title">用户手册</div>
            </div>
            <div class="content">
    
                <div class="left-part">
    
                </div>
                <div class="right-part">
                    <iframe id="frm" src="./pages/book.html" frameborder="0" style="width:100%;height:100%;"></iframe>
                </div>
            </div>
        </div>
    
    </body>
    
    </html>
    <script>
    
        let lp = document.querySelector('.lp-cont');
        $('.lp-cont-child').parent().addClass('lp-cont-cate');//增加类
       
        lp.addEventListener('click', function (e) {
    
            if (e.target.tagName.toLowerCase() === "li") {
                e.stopPropagation();
                let element = $(e.target);//目标节点
                if (element.children('.lp-cont-child').length > 0) {
                    element.removeAttr('onclick');
                    if (element.hasClass('li-active')) {
                        element.removeClass('li-active');
                        element.children('.lp-cont-child').slideUp();
                    } else {
                        element.addClass('li-active');
                        element.children('.lp-cont-child').slideDown();
                    }
                } else {
    
                    $('li').removeClass('active');
                    element.addClass('active');
                }
            }
        });
    
        function toPage(url) {
            var page = document.getElementById('frm');
            page.setAttribute('src', url);
        }
    
        function goBack() {
            location.href = '/';
        }
    </script>
    `;
    }
    export { handlecatalogue, handleContent, fsWrite };
    
    

    相关文章

      网友评论

        本文标题:如何将word转为好看的导航网页?

        本文链接:https://www.haomeiwen.com/subject/htqotrtx.html