结对第二次作业--编程实现

222000309李典游 学生 2023-03-24 20:50:54
这个作业属于哪个课程2023年福大-软件工程实践-W班
这个作业要求在哪里结对第二次作业--编程实现
结对学号222000309,222000310
这个作业的目标编程实现结对第一次作业原型设计作业的部分功能
其他参考文献《构建之法》

目录

  • 一、Gitcode仓库地址
  • 二、PSP表格
  • 三、项目的访问链接
  • 四、项目成果展示
  • 五、结对讨论过程
  • 5.1 任务分工
  • 5.2仓库导入
  • 5.3 数据交互
  • 六、设计实现过程
  • 6.1 功能结构图
  • 6.2 系统设计
  • 七、关键代码展示
  • 7.1 前端关键代码
  • 7.2 后端关键代码
  • 八、心路历程与收获
  • 九、结对队友互评

一、Gitcode仓库地址

m0_52688898 / pair_project 仓库地址

二、PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划2520
• Estimate• 估计这个任务需要多少时间2520
Development开发18002280
• Analysis• 需求分析 (包括学习新技术)500720
• Design Spec• 生成设计文档90120
• Design Review• 设计复审4030
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)3040
• Design• 具体设计4050
• Coding• 具体编码12001800
• Code Review• 代码复审90200
• Test• 测试(自我测试,修改代码,提交修改)180120
Reporting报告120180
• Test Repor• 测试报告90120
• Size Measurement• 计算工作量2040
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划5040
合计21502890

三、项目的访问链接

我们的项目访问链接

四、项目成果展示

五、结对讨论过程

5.1 任务分工

img

5.2仓库导入

img

5.3 数据交互

img

六、设计实现过程

6.1 功能结构图

img

6.2 系统设计

前端的实现过程:

  • 采用技术:Vue框架、响应式设计、Axios技术
  • 设计思路:根据原型设计部分内容,前端部分组件结构应包括:导航栏、关于部分、选手排名、每日赛程、晋级图以及详细数据,数据获取主要采用存储在纯前端的数据部分,其中选手排名是采用前后端交互的方式进行
  • 遇到的问题以及解决的方式:
  • -1.使用elemen-ui时, 样式要求不符合自己的预期,修改了style样式却不生效
    解决方式:由于<style> 标签中带有scoped属性导致不生效, 通过在样式选择器前添加 ::v-deep解决了问题
  • -2.使用vue语法动态引用图片链接时,图片加载不出来
    解决方式: 通过 require(url) 引用的方式, 使图片成功加载
  • -3.由于不熟悉第三方组件, 在想配置各种属性时, 不知道具体措施
    解决方式: 通过百度、CSDN、询问同学的方式得出其解决办法

后端的实现过程:

  • 采用技术:tomcat、servlet、JDBC
  • 设计思路:根据原型设计部分内容,将选手排名所需要的各项数据手动输入到数据库中,再创建继承自HttpServlet的类,用线性表存取数据,再将线性表转为JSON形式传送至前端
  • 遇到的问题以及解决的方式:
  • -前后端跨域问题
    解决方法:调用setHeader方法,设置允许跨域的主机地址

七、关键代码展示

7.1 前端关键代码

  • 相较于创建全局引入,按需引入所占用的内存打包空间要小一些,这将极大地影响打包以后文件在执行时的效果,所以我们在main.js里面仅仅引入并应用我们所需要的element-ui组件
//按需引入  ElementUI组件
import { Menu, MenuItem, Submenu } from 'element-ui';
...

//应用ElementUI
Vue.component(Menu.name, Menu);
Vue.component(MenuItem.name, MenuItem);
Vue.component(Submenu.name, Submenu);
...
  • 创建整个项目的路由,使用户点击页面中的导航栏链接时,不会刷新页面,只会做页面的局部更新
//创建并暴露一个路由器
// router/index.js
export default new VueRouter({
    routes: [
        {
            name: "Home",
            path: '/',
            redirect: "/Rank",
            component: Home,
            children: [
                {
                    name: "Rank",
                    path: 'Rank',
                    component: Rank,
                },
                {
                    name: "Daily",
                    path: 'Daily',
                    component: Daily,
                },
                {
                    name: "Promotion",
                    path: 'Promotion',
                    component: Promotion,
                },
                {
                    name: "Detail",
                    path: 'Detail',
                    component: Detail,
                },
                
            ],
        },
        {
            name: "About",
            path: '/About',
            component: About,
        },
    ]
})
  • 前端页面导航条组件的内容结构和功能实现
    <!-- 导航条组件, 由router属性配置路由跳转 -->
  <div class="navigation">
    <el-menu
      :default-active="activeIndex"
      class="el-menu-demo"
      mode="horizontal"
      router
    >
      <el-menu-item index="About">
        <img src="../assets/icon.png" alt="澳网图标" id="icon" />
      </el-menu-item>
      <el-menu-item index="Rank">选手排名</el-menu-item>
      <el-menu-item index="Daily">每日赛程</el-menu-item>
      <el-menu-item index="Promotion">晋级图</el-menu-item>
    </el-menu>
  </div>
  • vue2-org-tree插件的可定制性较高,能满足个性化的需求,在data函数中定义数据,通过设置horizontal属性为true使晋级图从左到右展示,使用 render-content 属性可以渲染树节点的结构和样式
<!-- 使用vue2-org-tree插件实现晋级图树状展示 -->
<!-- render-content属性负责渲染每个树节点结构与样式 -->
<div class="tree">
    <vue2-org-tree
        :data="drawData"
        :horizontal="true"
        :render-content="showTree"
     />
</div>
<!-- v-for渲染每日赛程的天数, 并绑定click事件 -->
<!-- 通过selected参数判断点击的是哪一天,并绑定class样式渲染点击那一天的样式 -->
<el-row :gutter="30">
      <el-col :span="8" v-for="key in 3" :key="key">
        <el-card
          shadow="always"
          @click.native="show(key)"
          :class="{ isActive: selected == key }"
        >
          Day{{ key }}
        </el-card>
      </el-col>
</el-row>
    
    <!-- 每日赛程下方赛况卡片 -->
    <div
      class="scoresWrapper"
      v-for="(item, index) in day[selected - 1]"
      :key="index"
    >
      <h3>{{ item.court }}</h3>
      <div class="scores">
        <div
          class="score"
          @click="getDetail"
          v-for="(score, key) in item.scores"
          :key="key"
        >
          <div class="score-row">
            <div class="score-header__title-wrapper">
              <p class="score-header__title font-bold">{{ score.type }}</p>
              <p class="score-header__subtitle">
                {{ score.round }}{{ item.court }}
              </p>
            </div>
            <div class="score-header__status-wrapper">
              <p class="score-header__status font-bold">Complete</p>
              <p class="score-header__duration">{{ score.time }}</p>
            </div>
          </div>
          <el-divider></el-divider>
          <div class="score-row">
            <div class="player-row__team-wrapper winner">
              <span class="player-flag">
                <img :src="score.win.flag" alt="flag" />
              </span>
              <p>
                {{ score.win.name }} <span>{{ score.win.num }}</span>
              </p>
            </div>
            <div class="player-row__score-wrapper">
              <span class="player-row__score-badge winner"></span>
              <div class="player-row__score-game-wrapper">
              <!-- compare函数判断哪方分数高,并加粗赢家的字体 -->
                <p
                  class="player-row__score-game"
                  v-for="(rate, scoreIndex) in score.win.grade"
                  :key="scoreIndex"
                  :class="{
                    winner: compare(rate, score.lose.grade[scoreIndex]),
                  }"
                >
                  {{ rate }}
                </p>
              </div>
            </div>
          </div>
          <el-divider></el-divider>
          <div class="score-row">
            <div class="player-row__team-wrapper">
              <span class="player-flag">
                <img :src="score.lose.flag" alt="flag" />
              </span>
              <p>{{ score.lose.name }} <span></span></p>
            </div>
            <div class="player-row__score-wrapper">
              <div class="player-row__score-badge"></div>
              <div class="player-row__score-game-wrapper">
                <p
                  class="player-row__score-game"
                  v-for="(rate, scoreIndex) in score.lose.grade"
                  :key="scoreIndex"
                  :class="{
                    winner: compare(rate, score.win.grade[scoreIndex]),
                  }"
                >
                  {{ rate }}
                </p>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
<script>
export default {
  name: "Daily",
  data() {
    return {
      selected: 1,
     }
   },
  methods: {
    getDetail() {
      this.$router.push({
        name: "Detail",
      });
    },
    show(day) {
      this.selected = day;
    },
    compare(rate1, rate2) {
      return rate1 >= rate2;
    },
  },
};
</script>

<!-- 
isActive样式
.isActive {
  background-color: rgb(0, 115, 178);
  color: #fff;
}
winner样式
.winner {
  font-weight: bold;
}
-->
  • 在Home.vue中,用keep-alive包裹动态组件,使得在路由来回切换的时候会缓存我们所做的操作以及组件的状态,即使用keep-alive保存了之前的组件状态,而不是销毁它们
    <!-- 家页面,由导航栏点击时, 通过router-view渲染不同组件 -->
    <!-- keep-alive标签负责缓存已经加载的组件,提高性能 -->
  <div class="home">
    <Navigation/>
    <keep-alive>
      <router-view></router-view>
    </keep-alive>
  </div>
    <!-- 通过tab-pane构建关于介绍的界面 -->
  <div class="about">
    <h1><i class="el-icon-back" @click="goBack"></i> 澳网介绍</h1>
    <el-tabs tab-position="left" type="border-card">
      <el-tab-pane label="创立之初">...</el-tab-pane>
      <el-tab-pane label="不断发展">...</el-tab-pane>
      <el-tab-pane label="公开赛时代"></el-tab-pane>
    </el-tabs>
  </div>
  • 组件结构与样式展现
    <!-- 详细介绍组件 -->
  <div class="detail">
    <div class="set" v-for="(set, index) in sets" :key="index">
      <h1>{{ set.h1 }}</h1>
      <div class="setWrapper">
        <div class="setHead">
          <div class="player">
            {{ set.setHead.player }} <span class="time"></span>
          </div>
          <div class="score">{{ set.setHead.score }}</div>
        </div>
        <div v-for="(setRow, key) in set.setRows" :key="key">
          <el-divider></el-divider>
          <div class="setRow">
            <div class="playerWrapper">
              <div class="player">
                {{ setRow.player }} <span class="time">{{ setRow.time }}</span>
              </div>
              <div class="info">
                {{ setRow.info }}
              </div>
            </div>
            <div class="game">{{ setRow.game }}</div>
          </div>
        </div>
      </div>
    </div>
  </div>

<!-- 添加 "scoped" 属性来限制这个CSS只属于该组件 -->
<style scoped>
.detail {
  margin-top: 30px;
}
.set {
  width: 60%;
  margin: 0 auto;
}
.setWrapper {
  border: 1px solid rgb(235, 235, 235);
  padding: 10px;
}
.el-divider--horizontal {
  margin: 8px 0;
  background: 0 0;
  border-top: 1px solid rgb(235, 235, 235);
}
/* 每轮的名字 */
h1 {
  text-align: left;
}
/* 每轮的头部 */
.setHead {
  text-align: left;
  font-weight: bold;
}
.setHead .score {
  font-size: 22px;
  font-weight: bolder;
}
/* 每轮的行 */
.setRow .playerWrapper {
  text-align: left;
  display: inline-block;
  width: 50%;
}
.setRow .game {
  text-align: right;
  display: inline-block;
  width: 50%;
  vertical-align: top;
  font-weight: bold;
}
.setRow .info {
  font-size: 10px;
  color: rgb(165, 167, 167);
}
.player {
  font-weight: bolder;
  margin-bottom: 5px;
}
.player .time {
  font-weight: normal;
}
</style>

7.2 后端关键代码

  • 连接数据库,查询男性选手排名等各项数据并用线性表存取数据,再将线性表转为JSON形式进行处理,最后将数据以utf-8形式转换为string类型传送至前端并释放数据库资源
       {    //数据库连接
            Class.forName("com.mysql.jdbc.Driver");

            String url = "jdbc:mysql://127.0.0.1:3306/daily_competition";
            String username = "root";
            String password = "123456";
            Connection connection = DriverManager.getConnection(url,username,password);

            String sql = "SELECT * FROM daily_competition.male_competitor_rank;";

            Statement stmt = connection.createStatement();
            //执行并读取查询数据
            ResultSet rs = stmt.executeQuery(sql);
            //用线性表存取数据
            ArrayList<competitor> list = new ArrayList<competitor>();

            while(rs.next())
            {
                competitor competitor_list = new competitor();
                //从ResultSet中取值并把数据存到competition类中
                competitor_list.setName(rs.getString(1));
                competitor_list.setRank(rs.getInt(2));
                competitor_list.setMatches(rs.getInt(3));
                competitor_list.setAces(rs.getInt(4));
                //将处理好的对象添加到线性表中
                list.add(competitor_list);
            }
            //指定浏览器解析格式
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/html");
            //将线性表转为JSON形式,进行处理
            JSONArray js = JSONArray.fromObject(list);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("tableData", js);
            //将数据以utf-8形式转换为string类型
            String competitors = new String(jsonObject.toString().getBytes(StandardCharsets.UTF_8), "UTF-8");
            PrintWriter writer = resp.getWriter();
            writer.write(competitors);
            writer.close();
            //数据库资源释放
            rs.close();
            stmt.close();
            connection.close();
      }

八、心路历程与收获

222000310:

这次项目主要负责了前端页面的相应开发,此前在软工数据库实践中学习过前端开发的相应知识点,但知识不用便会被遗忘,也让我深刻懂得了不管前端后端,编程能力绝对不是靠死记硬背就能提高的,而是要通过不断的动手实践,形成“肌肉记忆”,本次编程边动手边复习以前的知识,在开发过程中遇到了大大小小的问题,虽然最后通过百度、询问同学的方式解决了大部分问题,从总体来说效率并不算高,在今后要努力提高自己的编程开发经验,同时每一次的动手开发实践都是对自己的一次挑战

222000309:

这一次项目时间紧任务重,我原本主要应该负责后端部分的开发,将相关Json数据处理并存入数据库中,再将数据编写成Json格式后响应给浏览器,但是在囫囵吞枣般快速地学习了Javaweb的相关知识以后,我就匆匆上手写代码了,缺乏了与前端之间的交互和沟通,导致数据库的设计存在与前端需求的不匹配,再加上前后端交互之间的跨域以及部署云服务器等问题,最后我们还是决定将大部分数据存储在前端代码中。这一次较大的改动,浪费了不少时间,白费了不少力气,也提醒我以后再与其他人一起合作开发项目之前,应当提前确定相互的需求,结合任务时间以及自身水平等因素进行合理的分工。

九、结对队友互评

222000310:

这是第二次进行组队合作了,通过上一次的组队配合,已经和队友达成了些许默契,前期的分工比上一次明确了许多,虽然这次工作量比起上次的模型开发大了许多,但效率也比上次高出许多,两个人对对方代码互相评价,互相促进,遇到问题时能积极协调的沟通,让我领会到了团队协同开发的乐趣。同时使用了git团队协作工具,把团队协作的难度降低了许多,总体而言这是次成功且意义巨大的合作项目(鼓掌)

222000309:

这次组队合作,我的队友几乎以一己之力完成了所有的编程任务,我只是负责了一些简单的数据处理和博客编写的任务,在整个项目中没有发挥很大的作用,实在是惭愧惭愧。


...全文
202 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

688

社区成员

发帖
与我相关
我的任务
社区描述
2023年福州大学软件工程实践课程W班的教学社区
软件工程团队开发软件构建 高校 福建省·福州市
社区管理员
  • FZU_SE_teacherW
  • 张书旖
  • 郭渊伟
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧