zoukankan      html  css  js  c++  java
  • 结对作业二

    这个作业属于哪个课程 2021春软件工程实践 W班 (福州大学)
    这个作业要求在哪里 结对作业二
    结对学号 081800306&041802224
    这个作业的目标 顶会热词统计

    PSP表格和效能分析

    PSP表格

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划
    • Estimate • 估计这个任务需要多少时间 30 30
    Development 开发
    • Analysis • 需求分析 30 60
    • Design Review • 设计复审 10 20
    • Coding Standard • 代码规范 (为目前的开发制定合适的规范) 20 30
    • Design • 具体设计 60 60
    • Coding • 具体编码 3000 3500
    • Code Review • 代码复审 60 90
    • Test • 测试(自我测试,修改代码,提交修改) 10 30
    Reporting 报告 50 60
    • Test Report • 测试报告 30 30
    • Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 10 10
    合计 3310 3920

    Github地址&代码规范

    项目地址

    访问地址

    地址

    成果展示

    项目的首页,由导航栏、搜索框、词云构成

    导航栏由首页、论文检索、热度分析构成,支持三个页面的跳转

    词云由echarts-wordcloud引入,从数据库中获取关键词简易排列

    论文检索页面,在下拉框中可选择关键词、编号、内容、标题的方式检索论文

    按照关键词检索论文

    按照编号检索论文

    按照标题检索论文

    点击论文列表的修改图标跳转到详情修改界面

    修改标题为TEST

    查询标题为TEST的论文

    热词分析页面,展示近三年三个会议的关键词统计

    切换显示近三年各个会议的热词走势

    结对过程

    实现过程

    • 前端
      页面的标题栏复用,
      首页的词云使用了echarts-wordcloud
      论文列表页
      分析页面使用echarts的饼图和折线图
      html、css设计页面,jquery ajax请求接口返回数据给图表

    • 后端
      使用基于nodejs的koa框架
      sequelize创建数据库表对应的模型,生成增删改查的数据库方法
      路由接口提供数据

    • 数据库设计

    • 功能结构图

    代码说明

    sequelize根据数据库表article创建模型,编写所需的数据库语句

        static async getArticles(list, page) {
            let ids = [];
            for (let i = page * 5; i < page * 5 + 5; i++) {
                ids.push(list[i].arcid);
            }
            return await Article.findAll({
                where: {
                    id: {
                        [Op.in]: ids,
                    },
                },
            });
        }
    static async getArticleByid(id) {
            let article = await Article.findOne({
                where: {
                    id,
                },
            });
            return article;
        }
        static async getArticleByContent(content) {
            let article = await Article.findAll({
                where: {
                    content,
                },
            });
            return article;
        }
        static async getArticleByTitle(id) {
            let article = await Article.findAll({
                where: {
                    id,
                },
            });
            return article;
        }
    
        static async getIdsByKey(key) {
            let ids = await keywords.getIdByKey(key);
            return ids;
        }
    
        static async updateArticle({ id, title, conclude, link, magazine }) { // eslint-disable-line
            await Article.update({ title, conclude, link, magazine }, { // eslint-disable-line
                where: { id },
            });
        }
    
        static async deleteArticle({ id }) {
            await Article.destroy({
                where: {
                    id,
                },
            });
        }
      }
      Article.init({
        id: {
            type: DataTypes.STRING,
            primaryKey: true,
        },
        title: DataTypes.STRING,
        year: DataTypes.INTEGER,
        conclude: DataTypes.STRING,
        link: DataTypes.STRING,
        magazine: DataTypes.STRING,
    }, {
        sequelize,
        tableName: 'article',
    });
    
    module.exports = {
        Article,
    };
    

    路由请求,通过调用model类的方法返回相应的数据

        let key = ctx.query.key; // eslint-disable-line
        let page = ctx.query.page || 0;
        let kind = ctx.query.kind; // eslint-disable-line
        let articles;
        let list;
        if (key && (kind == 1)) { // eslint-disable-line
            console.log(key);
            list = await Article.getIdsByKey(key);
            articles = await Article.getArticles(list, page);
        }
        if (key && (kind == 0)) { // eslint-disable-line
            articles = await Article.getArticleByid(key);
        }
        if (key && (kind == 2)) { // 内容
            list = await Article.getIdsByKey(key);
            articles = await Article.getArticles(list, page);
        }
        if (key && (kind == 3)) { // 标题
            list = await Article.getIdsByKey(key);
            articles = await Article.getArticles(list, page);
        }
        ctx.body = articles;
    });
    module.exports = router;
    

    前端复用的标题栏

        <div class="logo">
        </div>
        <div class="items">
            <a class="item" index="1">首页</a>
            <a class="item">论文检索</a>
            <a class="item">热度分析</a>
        </div>
    </div>
    <script>
        let items = document.querySelector('.items')
        items.addEventListener('click', (e) => {
            let str = e.target.innerHTML
            if (str === '首页') {
                window.location.href = '/'
            } else if (str === '论文检索') {
                window.location.href = '/list'
            } else if (str === '热度分析') {
                window.location.href = '/hot'
            }
            console.log(str === '首页');
        })
    </script>
    

    展示数据的list

        <% if (articles) {%>
        <% articles.forEach(function(article){ %>
          <%- include('./item.html', {article}); %>
        <% }); %>
        <%}%>
      </div>
    

    list中的item

      <p class="piece-title"><%= article.title %></p>
      <p class="piece-content"><%= article.conclude%></p>
    </div>
    

    列表数据通过jquery的ajax方法获取

              type: 'GET',
              url: `http://localhost:3000/getArticles?key=${key}&page=${page}&kind=${kind}`,
              success(res) {
                console.log(res);
                if (!Array.isArray(res)) {
                  res = [res]
                }
                let $lis = ''
                $('.list').empty()
                for(let i = 0; i < res.length; i++) {
                  $lis += `<div class="piece"><a href="/detail?id=${res[i].id}"><i><svg t="1616326953943" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4559" width="32" height="32"><path d="......" fill="#e6e6e6" p-id="4561"></path><path d="......" fill="#e6e6e6" p-id="4562"></path><path d="......" fill="#e6e6e6" p-id="4563"></path></svg></i></a>
                    <p class="piece-title">${res[i].title}</p>
                    <p class="piece-content">
                      ${res[i].conclude}
                    </p>
                    <a class="link" href="${res[i].link}" target="_blank">原文链接</a>
                  </div>`
                            }
                            $('.list').append($lis)
                        }
                    })
    

    echart饼图的数据请求

            type: 'POST',
            url: 'http://localhost:3000/hot/gettop',
            //http://150.158.180.107:3000
            success(res) {
                var data1 = []
                data1 = res
                var chartDom1 = document.getElementById('container1');
                var myChart1 = echarts.init(chartDom1);
                var option1;
    
                option1 = {
                    title: {
                        text: '关键词TOP10',
                        left: 'center',
                        textStyle: {
                            color: '#fff'
                        }
                    },
                    tooltip: {
                        trigger: 'item'
                    },
    
                    series: [{
                        name: '关键词',
                        type: 'pie',
                        radius: '50%',
                        data: data1,
                        emphasis: {
                            itemStyle: {
                                shadowBlur: 10,
                                shadowOffsetX: 0,
                                shadowColor: 'rgba(0, 0, 0, 0.5)'
                            }
                        }
                    }]
                };
    
                option1 && myChart1.setOption(option1);
            }
        })
    

    项目入口

    const app = new Koa();
    ejs.clearCache();
    app.use(bodyparser());
    app.use(serve(path.join(__dirname, '/public')));
    app.use(views('view', {
        root: path.join(__dirname, '/view'),
        map: { html: 'ejs' },
    }));
    
    function registerRouters(item) {
        if (item instanceof Router) {
            app.use(item.routes());
        }
    }
    const modules = new RequireDirectory(module, './routes', { visit: registerRouters });
    

    package

        "name": "work",
        "version": "1.0.0",
        "description": "",
        "main": "app.js",
        "scripts": {
            "test": "echo "Error: no test specified" && exit 1",
            "lint": "eslint src",
            "lint:create": "eslint --init"
        },
        "author": "",
        "license": "ISC",
        "dependencies": {
            "ejs": "^3.1.6",
            "eslint-config-airbnb-base": "^14.2.1",
            "eslint-plugin-import": "^2.22.1",
            "koa": "^2.13.1",
            "koa-bodyparser": "^4.3.0",
            "koa-router": "^10.0.0",
            "koa-static": "^5.0.0",
            "koa-views": "^7.0.1",
            "mysql2": "^2.2.5",
            "require-directory": "^2.1.1",
            "sequelize": "^6.6.2"
        },
        "devDependencies": {
            "eslint": "^7.22.0"
        }
    }
    

    心路历程

    hanmajack(0418022224):

    这次的作业用到的技术对我来说很陌生,web的基础掌握的也不够好,花费了大量的时间去看API文档、博客等。一路上遇到了很多困难,也都一一与队友讨论解决了。总的来说这次结对的体验很好,让我学到了很多新知识。

    陈志君(081800306):

    这次的作业的技术选型本来想采用前后端分离,前端采用vue框架来完成,但是由于作业文件夹命名必须有&字符,Vue框架就不能采用了,所以我们决定用web半分离的方式来开发,前端通过模板语法来渲染。学到了挺多新知识,包括数据库的高级查询,服务器的部署等等。收获蛮大的

    队友评价

    hanmajack -> 从零开始的代码生活:

    队友很给力,执行力很强,自己的部分总是很快就完成实现了。而且队友在我遇到困难时给了我很多帮助,在编程方面指导我,很耐心的给我讲解,很庆幸这次结对作业遇到了这么好的队友。

    陈志君 -> hanmajack

    队友学习能力很强,很勤奋,刚开始对web可能不太熟悉,但是他课后自学,b站看视频,csdn上看博客,一步一步提升自己,给队友一个大大的好评

  • 相关阅读:
    tree
    gridview XML
    http://jingyan.baidu.com/article/22a299b513f3db9e18376a5e.html
    tree btn
    sss rar jar
    ComponentOne Studio
    http://wpf_sl.cnblogs.com/ WPF/Silverlight深蓝团队
    ddddd
    [牛客每日一题] (前缀和+线性 DP) NC15553 数学考试
    [停更一周,我干了什么] [C++/QT] 一个基于avl树,trie树,哈希散列表的英汉词典
  • 原文地址:https://www.cnblogs.com/Dusks/p/14603737.html
Copyright © 2011-2022 走看看