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

222100125钱元城 2024-03-26 22:58:10
这个作业属于哪个课程软件工程实践-2023学年-W班
这个作业要求在哪里结对第二次作业——编程实现
结对学号<222100125,222100123>
这个作业的目标①编码实现原型设计
②熟悉Git合作
其他参考文献《Vue.js中文文档》

目录

  • 1.git仓库链接
  • 2.PSP表格
  • 3.成品展示
  • 3.1 项目链接
  • 3.2 项目展示
  • 主页
  • 每日赛程
  • 详细赛况
  • 比赛数据
  • 4.结对讨论过程描述
  • 5.设计实现过程
  • 5.1 后端部分设计思路
  • 5.2 前端部分设计思路
  • 5.3 功能结构图
  • 5.4 遇到的问题
  • 6.代码说明
  • 6.1 代码规范
  • 6.2 后端代码展示
  • 6.3 前端代码展示
  • 7.心路历程和收获
  • 8.评价结对队友

1.git仓库链接

git仓库链接

2.PSP表格

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

3.成品展示

3.1 项目链接

服务器地址

3.2 项目展示

主页

主页提供路由跳转,显示比赛照片等内容


每日赛程

每日赛程使用折叠面板展示,根据接受到的响应数据数目动态生成组件,点击可展开显示参赛运动员信息,点击显示详情功能可跳转至详细赛况,点击上方按钮可切换时区

详细赛况

详细赛况使用折叠面板展示,根据接受到的响应数据数目动态生成组件,点击可展开显示比赛各阶段的结果,可以通过点击相应的按钮切换显示的比赛阶段,当前显示的比赛阶段的按钮会有不同的显示效果提示

比赛数据

比赛数据使用echarts图表库展示,包含各国运动员人数,各项目参赛人数,各国奖牌总数和各国金银铜奖牌数量

4.结对讨论过程描述

  • 在本次项目设计过程中,我们针对用什么方式实现这次作业所提到的的功能,数据应该如何设计,前后端数据的传输过程等一系列问题的讨论使用了微信聊天的方式进行,以下是讨论过程中的部分截图:

img

img

img

img

5.设计实现过程

5.1 后端部分设计思路

  • 将类分成存放处理数据的service类,存储数据的实体类和返回数据的Controller类。
  • 把返回每日赛程和对应运动员信息的方法、返回比赛对应具体信息的方法、返回奖牌个数的方法、返回全体运动员信息的方法放在对应的Controller类中。
  • 将处理数据比赛信息的方法放在对应的service类中
  • 数据使用的是静态json文件,json文件存放在resources的目录下进行访问。

5.2 前端部分设计思路

  • 使用Vue3框架,并借助UI库ElementPlus进行页面搭建;
  • 采用单页面,页面分为三个部分,页头导航,页面主体,页尾,页头导航和页尾所有视图共享;
  • 通过路由改变页面主体的视图,实现功能切换;
  • 在数据展示界面根据接收到的数据数量动态生成组件;
  • 在接收数据时增加加载动画,减少卡顿感,优化用户体验;
  • 考虑到部分选手的照片缺失,对这部分进行默认替换处理;
  • 奖牌统计使用echarts图表库,让展示更直观且美观;
  • 有关嵌套的版块暂时以静态形式嵌入源码中。

5.3 功能结构图

img

5.4 遇到的问题

①在第一次实现前后端数据传输的时候,遇到了跨域的情况。

  • 解决方法:在后端代码中实现了WebMvcConfigurer接口中的addCorsMappings方法,并加上了@Configuration注释。

②在解决跨域的问题之后发现,传过来的数据是空的,不是期待中的json文件数据。

③在部署前端项目时,Nginx服务器老是启动不了,显示端口被占用

  • 在输入查看Ngnix服务器的文件路径时,发现有自己不小心下载了两个Nginx,因此在删除其中一个后正常部署了。

④在本地访问resources文件夹下的数据正常,部署到服务器上后发现访问不到

  • 首先是把访问的那个路径文件分隔符从/改成File.separator,然后发现在Linux上是区分文件大小写的,因此在将文件名中的大小写区分好后就可以在服务器上运行。

⑤在本地解决完跨域问题后,发现在服务器上依旧出现了跨域问题

6.代码说明

6.1 代码规范

Java代码规范
Vue代码规范

6.2 后端代码展示

  • Game类:
@JsonSerialize
public class Game {
    String gameName;
    List<GameMessage> gameMessages;

   ···//这里省略基本方法

}
  • GameMessage类
@JsonSerialize
public class GameMessage {
    String gameType;
    String gameData;
    String gameTime;
    List<PlayerMessage> playerMessageList;

    ...//这里省略基本方法
}
  • GameSchedule类
@JsonSerialize
public class GameSchedule {
    String gameName;
    GameMessage gameMessage;

    ...//这里省略基本方法
}
  • PlayerMessage类
@JsonSerialize
public class PlayerMessage {

    String fullName;
    String country;
    int[] age;
    String preliminaryRank;
    String semifinalRank;
    String finalRank;
    double preliminaryTotalScore;
    double semifinalTotalScore;
    double finalTotalScore;
    double pointBehind;

    ...//这里省略基本方法
}
  • Medals
@JsonSerialize
public class Medals {
    String countryName;
    int goldCount;
    int silverCount;
    int bronzeCount;
    int totalCount

    public void addGold() {
        goldCount++;
    }

    public void addSilver() {
        silverCount++;
    }

    public void addBronze() {
        bronzeCount++;
    }

    public void addTotal() {
        totalCount++;
    }

    // 按照金牌数量降序,金牌数量一样按银牌数量,银牌数量一样按铜牌
    public static Comparator<Medals> CountComparator = new Comparator<Medals>() {
        @Override
        public int compare(Medals medals1, Medals medals2) {
            if (medals1.goldCount != medals2.goldCount) {
                return medals2.goldCount - medals1.goldCount;
            } else if (medals1.silverCount != medals2.silverCount) {
                return medals2.silverCount - medals2.silverCount;
            } else {
                return medals1.bronzeCount - medals1.bronzeCount;
            }
        }
    };
}
    ...//这里省略基本方法
  • GameService类中:解析各场比赛的数据,获得比赛的信息和运动员信息的方法,得到一个Game类
public class GameService {
    /*功    能:解析比赛信息的json*/
    /*入口参数: 对应比赛文件字符串*/
    /*返    回:比赛中运动员信息列表*/
    public Game ParseGameDetail(String gameJSON) throws JSONException {
        JSONObject jsonObject = new JSONObject(gameJSON);
        JSONArray messageArray = jsonObject.getJSONArray("Heats");
        List<GameMessage> gameMessages = new ArrayList<>();

        for (int i = messageArray.length() - 1; i >= 0; i--) {
            List<PlayerMessage> playerMessages = new ArrayList<>();

            GameMessage gameMessage = new GameMessage();

            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat outputFormat = new SimpleDateFormat("EEEE d'st' MMMM");

            // 日期转换
            Date date = null;

            try {
                date = inputFormat.parse(jsonObject.getString("DisciplineStartDate"));
            } catch (ParseException e) {
                e.printStackTrace();
            }

            gameMessage.setGameData(outputFormat.format(date));

            // 处理比赛中运动员信息
            JSONObject gameObject = messageArray.getJSONObject(i);
            //每个运动员的得分
            JSONArray gameArray = gameObject.getJSONArray("Results");
            //取出比赛是final、Semifinal还是Preliminary
            String gameType = gameObject.getString("PhaseName");
            gameMessage.setGameType(gameType);
            gameMessage.setGameTime(gameObject.getString("EndTime"));

            int nowPlayerIndex = 0;

            //从第一次比赛开始读(Results)
            for (int j = 0; j < gameArray.length(); j++) {
                JSONObject playerMessageObject = gameArray.getJSONObject(j);
                String fullName = playerMessageObject.getString("FullName");
                String[] name = fullName.split("/");

                PlayerMessage playerMessage = new PlayerMessage();

                playerMessage.setCountry(playerMessageObject.getString("NAT"));

                if (!playerMessageObject.get("PointsBehind").toString().equals("null")) {
                    playerMessage.setPointBehind(Double.parseDouble(playerMessageObject.get("PointsBehind").toString()));
                } else {
                    playerMessage.setPointBehind(0.0);
                }

                //判断是否为单人项目
                if (name.length == 1) {
                    playerMessage.setFullName(playerMessageObject.getString("FullName"));
                    playerMessage.setAge(playerMessageObject.getInt("AthleteResultAge"));
                } else {
                    String player1LastName = name[0].trim();
                    String player2LastName = name[1].trim();

                    playerMessage.setFullName(player1LastName, player2LastName);

                    JSONArray competitors = playerMessageObject.getJSONArray("Competitors");
                    playerMessage.setAge(competitors.getJSONObject(0).getInt("AthleteResultAge"), competitors.getJSONObject(1).getInt("AthleteResultAge"));
                }

                playerMessages.add(playerMessage);

                //找出当前取出的运动员在队列中的下标
                for (PlayerMessage playerMessage1 : playerMessages) {
                    if (name.length == 1) {
                        if (playerMessage1.getFullName().equals(playerMessageObject.getString("FullName")))
                            nowPlayerIndex = playerMessages.indexOf(playerMessage1);
                    } else {
                        String player1LastName = name[0].trim();
                        String player2LastName = name[1].trim();
                        String playerFullName = "";

                        playerFullName = player1LastName + " & " + player2LastName;

                        if (playerMessage1.getFullName().equals(playerFullName)) {
                            nowPlayerIndex = playerMessages.indexOf(playerMessage1);
                        }
                    }
                }
                playerMessage = playerMessages.get(nowPlayerIndex);

                //判断比赛类型,存入相关信息
                if (gameType.equals("Preliminaries")) {
                    playerMessage.setPreliminaryTotalScore(Double.parseDouble(playerMessageObject.getString("TotalPoints")));
                    playerMessage.setPreliminaryRank(Integer.toString(playerMessageObject.getInt("Rank")));
                } else if (gameType.equals("Semifinals")) {
                    playerMessage.setSemifinalTotalScore(Double.parseDouble(playerMessageObject.getString("TotalPoints")));
                    playerMessage.setSemifinalRank(Integer.toString(playerMessageObject.getInt("Rank")));
                } else {
                    playerMessage.setFinalTotalScore(Double.parseDouble(playerMessageObject.getString("TotalPoints")));
                    playerMessage.setFinalRank(Integer.toString(playerMessageObject.getInt("Rank")));
                }

                playerMessages.set(nowPlayerIndex, playerMessage);
            }
            gameMessage.setPlayerMessageList(playerMessages);
            gameMessages.add(gameMessage);
        }

        Game game = new Game(jsonObject.getString("DisciplineName"), gameMessages);
        return game;
    }
}
  • MessageController类:具有返回每日赛程和运动员信息的方法、返回具体比赛具体信息的方法、返回奖牌个数的方法、全体运动员信息的方法和处理json文件的方法,返回给前端用于展示
@CrossOrigin
@RestController
public class MessageController {

    GameService gameService = new GameService();

    private final ResourceLoader resourceLoader;

    public MessageController(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
    
    /*功    能:用于返回每日赛程信息和参赛选手*/
    /*入口参数:无*/
    /*返    回:对应日期和比赛信息*/
    @GetMapping("/schedule")
    public LinkedHashMap<String, List<GameSchedule>> GetGameMessage() {
        LinkedHashMap<String, List<GameSchedule>> dailyGame = new LinkedHashMap<>();

        List<GameSchedule> Thursday = new ArrayList<>();
        List<GameSchedule> Friday = new ArrayList<>();
        List<GameSchedule> Saturday = new ArrayList<>();
        List<GameSchedule> Sunday = new ArrayList<>();

        Game gameMessagesw = gameService.ParseGameDetail(ReadFile("Women 1m Springboard"));
        Game gameMessagesm = gameService.ParseGameDetail(ReadFile("Men 1m Springboard"));

        Thursday.add(new GameSchedule(gameMessagesw.getGameName(), gameMessagesw.getGameMessages().get(0)));
        Thursday.add(new GameSchedule(gameMessagesm.getGameName(), gameMessagesm.getGameMessages().get(0)));
        Thursday.add(new GameSchedule(gameMessagesw.getGameName(), gameMessagesw.getGameMessages().get(1)));
        Thursday.add(new GameSchedule(gameMessagesm.getGameName(), gameMessagesm.getGameMessages().get(1)));
        Thursday.add(new GameSchedule(gameService.ParseGameDetail(ReadFile("Men 3m Synchronised")).getGameName(), gameService.ParseGameDetail(ReadFile("Men 3m Synchronised")).getGameMessages().get(0)));
        dailyGame.put("Thursday 18th January", Thursday);

        gameMessagesw = gameService.ParseGameDetail(ReadFile("Women 10m Platform"));
        gameMessagesm = gameService.ParseGameDetail(ReadFile("Men 3m Springboard"));

        for (int i = 0; i <= 2; i++) {
            Friday.add(new GameSchedule(gameMessagesw.getGameName(), gameMessagesw.getGameMessages().get(i)));
            Friday.add(new GameSchedule(gameMessagesm.getGameName(), gameMessagesm.getGameMessages().get(i)));
        }
        dailyGame.put("Friday 19th January", Friday);

        gameMessagesw = gameService.ParseGameDetail(ReadFile("Women 3m Springboard"));

        for (int i = 0; i <= 2; i++) {
            Saturday.add(new GameSchedule(gameMessagesw.getGameName(), gameMessagesw.getGameMessages().get(i)));
        }

        Saturday.add(new GameSchedule(gameService.ParseGameDetail(ReadFile("Women 10m Synchronised")).getGameName(), gameService.ParseGameDetail(ReadFile("Women 10m Synchronised")).getGameMessages().get(0)));
        Saturday.add(new GameSchedule(gameService.ParseGameDetail(ReadFile("Men 10m Synchronised")).getGameName(), gameService.ParseGameDetail(ReadFile("Men 10m Synchronised")).getGameMessages().get(0)));
        dailyGame.put("Saturday 20th January", Saturday);

        gameMessagesm = gameService.ParseGameDetail(ReadFile("Men 10m Platform"));

        for (int i = 0; i < 2; i++) {
            Sunday.add(new GameSchedule(gameMessagesm.getGameName(), gameMessagesm.getGameMessages().get(i)));
        }

        Sunday.add(new GameSchedule(gameService.ParseGameDetail(ReadFile("Women 3m Synchronised")).getGameName(), gameService.ParseGameDetail(ReadFile("Women 10m Synchronised")).getGameMessages().get(0)));

        Sunday.add(new GameSchedule(gameMessagesm.getGameName(), gameMessagesm.getGameMessages().get(2)));
        dailyGame.put("Sunday 21st January", Sunday);

        return dailyGame;
    }

    /*功    能:用于返回详细赛程*/
    /*入口参数:无*/
    /*返    回:比赛信息*/
    @GetMapping("/detail")
    public List<Game> GetGameDetail() throws JSONException {

        List<Game> games = new ArrayList<>();
        games.add(gameService.ParseGameDetail(ReadFile("Women 1m Springboard")));
        games.add(gameService.ParseGameDetail(ReadFile("Women 3m Springboard")));
        games.add(gameService.ParseGameDetail(ReadFile("Women 10m Platform")));
        games.add(gameService.ParseGameDetail(ReadFile("Women 3m Synchronised")));
        games.add(gameService.ParseGameDetail(ReadFile("Women 10m Synchronised")));
        games.add(gameService.ParseGameDetail(ReadFile("Men 1m Springboard")));
        games.add(gameService.ParseGameDetail(ReadFile("Men 3m Springboard")));
        games.add(gameService.ParseGameDetail(ReadFile("Men 10m Platform")));
        games.add(gameService.ParseGameDetail(ReadFile("Men 3m Synchronised")));
        games.add(gameService.ParseGameDetail(ReadFile("Men 10m Synchronised")));

        return games;
    }

    /*功    能:用于计算奖牌数量*/
    /*入口参数:无*/
    /*返    回:奖牌信息*/
    @GetMapping("/g")
    public List<Medals> GetMedalsCount() throws JSONException {
        Map<String, Medals> medalsMap = new HashMap<>();

        List<Game> games = GetGameDetail();

        for (Game game : games) {
            for (GameMessage message : game.getGameMessages()) {
                if (message.getGameType().equals("Finals")) {

                    List<PlayerMessage> playerMessages = message.getPlayerMessageList();

                    for (int i = 0; i < 3; i++) {
                        Medals medals;

                        if (!medalsMap.containsKey(playerMessages.get(i).getCountry())) {
                            medals = new Medals();
                        } else {
                            medals = medalsMap.get(playerMessages.get(i).getCountry());
                        }

                        if (i == 0) {
                            medals.addGold();
                        } else if (i == 1) {
                            medals.addSilver();
                        } else {
                            medals.addBronze();
                        }

                        medals.addTotal();
                        medals.setCountryName(playerMessages.get(i).getCountry());
                        medalsMap.put(medals.getCountryName(), medals);
                    }
                }
            }

        }

        List<Medals> medals = new ArrayList<>();

        medalsMap.forEach((key, value) -> medals.add(value));

        Collections.sort(medals, Medals.CountComparator);
        return medals;
    }

    /*功    能:运动员信息*/
    /*入口参数:无*/
    /*返    回:运动员json信息*/
    @GetMapping("/player")
    public String GetPlayerMessage(){
        return ReadFile("Player");
    }

    /*功    能:读json文件*/
    /*入口参数:返回json文件为字符串*/
    /*返    回:文件名*/
    public String ReadFile(String fileName) {
        Resource resource = resourceLoader.getResource("classpath:game" + File.separator + fileName + ".json");
        StringBuilder str = null;

        try {
            InputStream inputStream = resource.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

            str = new StringBuilder("");
            String line;

            while ((line = reader.readLine()) != null) {
                str.append(line);
            }

            reader.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return str.toString();
    }
}

6.3 前端代码展示

  • urlStore,用于储存服务器地址,便于修改
import { defineStore } from 'pinia'

export const urlStore = defineStore('url', {
  actions: {},
  state() {
    return {
      baseUrl: 'http://118.178.124.104',
      backendPort: '8083',
    }
  },
  getters: {
    url: (state): string => state.baseUrl + ':' + state.backendPort,
  }
})
  • ts数据限制接口,保证从服务器fetch到的数据的正确性
interface PlayerMessageList
{
    age: Array<number>;
    country: string;
    finalRank: string;
    finalTotalScore: number;
    fullName: string;
    pointBehind: number;
    preliminaryRank: string;
    preliminaryTotalScore: number;
    semifinalRank: string;
    semifinalTotalScore: number;
}

interface GameMessage
{
    gameDate: string;
    gameTime: string;
    gameType: string;
    playerMessageList: Array<PlayerMessageList>;
}

export interface MatchDataList
{
    gameName: string;
    gameMessages: Array<GameMessage>;
}
  • 每日赛程数据视图
               <el-timeline-item v-for="(date, index) in  tableData " :key="index" :timestamp="index" placement="top"
                    :hollow="true" type="primary" size="large">
                    <el-collapse v-model="activeNames" class="listview">
                        <el-collapse-item v-for="(match, index) in  date " :key="index" class="listitem">
                            <template #title>
                                <div class="title-bar">
                                    <label v-if="timeArea === 'your'"
                                        class="title">{{ match.gameMessage.gameTime.substring(0, 5) }}
                                        PM</label>
                                    <label v-else-if="timeArea === 'local'"
                                        class="title">{{ getLocalTime(match.gameMessage.gameTime) }}</label>
                                    <el-divider direction="vertical" />
                                    <img src="/dive.png" class="logo">
                                    <h3 class="title">{{ match.gameName }}</h3>
                                    <h3 style="font-weight: bold; font-size:36px; margin:0 10px; color:lightgray">·
                                    </h3>
                                    <h3 v-if="match.gameMessage.gameType != 'Finals'" class="type-title-normal">
                                        {{ match.gameMessage.gameType }}
                                    </h3>
                                    <h3 v-else class="type-title-final">{{ match.gameMessage.gameType }}</h3>
                                    <el-button type="primary" plain style="position: absolute; left:1050px;"
                                        @click="goDetail()">查看详情</el-button>
                                </div>
                            </template>
                            <template #default>
                                <el-divider />
                                <div class="center">
                                    <label class="title">参赛选手列表</label>
                                </div>
                                <el-table :data="match.gameMessage.playerMessageList" style="width:100%">
                                    <el-table-column prop="country" label="Country">
                                        <template v-slot="scope">
                                            <div class="cell-container">
                                                <img :src="getFlagPath(scope.row.country)" class="table-icon">
                                                <span>{{ scope.row.country }}</span>
                                            </div>
                                        </template>
                                    </el-table-column>
                                    <el-table-column prop="athlete" label="Athlete" style="position: relative;">
                                        <template v-slot="scope">
                                            <div class="cell-container">
                                                <img :src="getPlayerPath(scope.row.fullName)" class="table-icon"
                                                    style="position: absolute;left:100px;" @error="handleImageError" />
                                                <span v-if="match.gameMessage.playerMessageList[0].age[1] === 0"
                                                    style="position: absolute;left:150px;">{{ scope.row.fullName }}</span>
                                                <span v-else style="position: absolute;left:150px;">
                                                    <div>
                                                        <div>
                                                            {{ cutName(nameSplit(scope.row.fullName)[0]) }}
                                                        </div>
                                                        <div>
                                                            {{ cutName(nameSplit(scope.row.fullName)[1]) }}
                                                        </div>
                                                    </div>
                                                </span>
                                            </div>
                                        </template>
                                    </el-table-column>
                                    <el-table-column v-if="match.gameMessage.playerMessageList[0].age[1] === 0"
                                        prop="age[0]" label="Age" />
                                    <el-table-column v-else label="Age">
                                        <template #default="{ row }">
                                            <div>
                                                <div style="font-size: 12px;">
                                                    {{ row.age[0] }}
                                                </div>
                                                <div style="font-size: 12px;">
                                                    {{ row.age[1] }}
                                                </div>
                                            </div>
                                        </template>
                                    </el-table-column>
                                </el-table>
                            </template>
                        </el-collapse-item>
                    </el-collapse>
                   </el-timeline-item>
  • 详细赛况数据视图
                <el-table :data="match.gameMessages[dataIndex[index]].playerMessageList" style="width: 100%">
                        <el-table-column v-if="match.gameMessages[dataIndex[index]].gameType === 'Finals'"
                            prop="finalRank" label="Overall Rank" width="180" />
                        <el-table-column v-else-if="match.gameMessages[dataIndex[index]].gameType === 'Semifinals'"
                            prop="semifinalRank" label="Overall Rank" width="180" />
                        <el-table-column v-else-if="match.gameMessages[dataIndex[index]].gameType === 'Preliminaries'"
                            prop="preliminaryRank" label="Overall Rank" width="180" />
                        <el-table-column prop="country" label="Country" width="180">
                            <template v-slot="scope">
                                <div class="cell-container">
                                    <img :src="getFlagPath(scope.row.country)" class="table-icon">
                                    <span>{{ scope.row.country }}</span>
                                </div>
                            </template>
                        </el-table-column>
                        <el-table-column prop="athlete" label="Athlete" style="position: relative;">
                            <template v-slot="scope">
                                <div class="cell-container">
                                    <img :src="getPlayerPath(scope.row.fullName)" class="table-icon"
                                        style="position: absolute;left:50px;" @error="handleImageError">
                                    <span v-if="match.gameMessages[dataIndex[index]].playerMessageList[0].age[1] === 0"
                                        style="position: absolute;left:100px;">{{ scope.row.fullName }}</span>
                                    <span v-else style="position: absolute;left:100px;font-size: 12px;">
                                        <div>
                                            <div>
                                                {{ cutName(nameSplit(scope.row.fullName)[0]) }}
                                            </div>
                                            <div>
                                                {{ cutName(nameSplit(scope.row.fullName)[1]) }}
                                            </div>
                                        </div>
                                    </span>
                                </div>
                            </template>
                        </el-table-column>
                        <el-table-column v-if="match.gameMessages[dataIndex[index]].playerMessageList[0].age[1] === 0"
                            prop="age[0]" label="Age" width="180" />
                        <el-table-column v-else label="Age" width="180">
                            <template #default="{ row }">
                                <div>
                                    <div style="font-size: 12px;">
                                        {{ row.age[0] }}
                                    </div>
                                    <div style="font-size: 12px;">
                                        {{ row.age[1] }}
                                    </div>
                                </div>
                            </template>
                        </el-table-column>
                        <el-table-column v-if="match.gameMessages[dataIndex[index]].gameType === 'Finals'"
                            prop="finalTotalScore" label="Points" width="180" />
                        <el-table-column v-else-if="match.gameMessages[dataIndex[index]].gameType === 'Semifinals'"
                            prop="semifinalTotalScore" label="Points" width="180" />
                        <el-table-column v-else-if="match.gameMessages[dataIndex[index]].gameType === 'Preliminaries'"
                            prop="preliminaryTotalScore" label="Points" width="180" />
                        <el-table-column prop="pointBehind" label="Pts Behind" />
                       </el-table>
  • echarts配置
               const totalChart = echarts.init(totalMedalChartContainer.value);
                const optionTotal = {
                    tooltip: {
                        trigger: 'item'
                    },
                    legend: {
                        top: '5%',
                        left: 'center'
                    },
                    series: [
                        {
                            name: '奖牌总数',
                            type: 'pie',
                            radius: ['40%', '70%'],
                            avoidLabelOverlap: false,
                            padAngle: 5,
                            itemStyle: {
                                borderRadius: 10
                            },
                            label: {
                                show: false,
                                position: 'center'
                            },
                            emphasis: {
                                label: {
                                    show: true,
                                    fontSize: 40,
                                    fontWeight: 'bold'
                                }
                            },
                            labelLine: {
                                show: false
                            },
                            data: totalMedal.value,
                        }
                    ]
                };
                totalChart.setOption(optionTotal);

                const medalChart = echarts.init(medalChartContainer.value);
                const option = {
                    color: ['#F5DE0D', '#BCBDB5', '#E2862A'],
                    legend: {},
                    tooltip: {},
                    dataset: {
                        dimensions: ['name', '金牌', '银牌', '铜牌'],
                        source: medalCount.value,
                    },
                    xAxis: {
                        type: 'category',
                        data: medalCount.value.map(item => item.name),
                    },
                    yAxis: {
                        type: 'value',
                    },
                    series: [{ type: 'bar' }, { type: 'bar' }, { type: 'bar' }]
                };
                medalChart.setOption(option);

7.心路历程和收获

  • 222100123 姚磊:在这次作业中,第一次学习使用springboot框架,在这次学习和使用中,遇到了各种各样的问题,好在和队友一同解决了,也使我在这次学习中信心大增。应该是一次次的解决出现的问题后渐渐有信心,也有可能是告诉自己问题总能解决,这次的作业中对于以往遇到问题就心浮气躁,产生放弃念头的我,在本次作业中,罕见的没有出现这种情况。
  • 222100125 钱元城:这段时间我正在学习Vue框架,这次作业刚好就能用上了,在学习时我觉得,Vue框架看起来也挺简单嘛,但是真正实践起来才发现,哪有那么容易哇!跌跌撞撞了几天,也总算是把这次的作业完成了,在完成的过程中,我才知道我还远远没有领会到Vue框架的精髓,学习切忌急于求成,并且对于我们这个专业,我认为实践一定是大于理论的,只有自己真正动手去做去感悟了,才能体会到其中的巧妙的思想,这就是我在这段时间的实践中得到的最大的收获。

8.评价结对队友

  • 222100123 姚磊 对 222100125 钱元城:已经是数不清多少次合作了,每次的合作都能让我感受到和他合作真好,在遇到问题需要解决,需要抱怨的时候,他总能给我帮助。而且他的知识面比较广,经常能给我一些惊喜。在对比我老是找他抱怨,他就显得非常的安静,给人一种特别踏实的感觉。
  • 222100125 钱元城 对 222100123 姚磊:怎么又是你,肚子里的墨水都快全部用来评价你了,你还是一如既往的靠谱,因为我个人的原因我在开发初期耽搁了一段时间,即使你自己也很忙,但是在这段时间里你还是认真完成了任务,你的行动力还是那么强,可惜最后我还是没能来得及把当时的想法全部实现,这也算是一个遗憾吧,在这里和你说声抱歉,下次也要一起加油呀。
...全文
537 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
助教鲍仁俊 助教 2024-03-27
  • 打赏
  • 举报
回复

关于我们的界面中,是否可以用一个列表或者更有趣的时间列表来显示“世界游泳运动与奥林匹克运动”呢。如果是纯搜集的文本粘贴会大大降低用户的使用体验和可读性。

FZU_SE_teacherW 教师 2024-03-27
  • 打赏
  • 举报
回复

整体较完整,使用过程中对于赛事通过鼠标滑动寻找,缺少必要的分类,用户体验较差。

AJAX——新手快车道 前言 AJAX是什么? 首先、AJAX是一种很酷的技术,一旦采用了AJAX,就能让你的Web页面, 你的网站,甚至连同你们公司,都变得很酷。在Web2.0的时代里,不使用一点 AJAX技术的网站,就会显得很老土,很落伍。 但是,这样的理解,其实是很肤浅的。仅仅是从一个外行,从一个使用者的 角度出发,来理解AJAX,就像我在本书的第一章AJAX我也行中那样,开发 出很愚蠢,甚至都没有资格被称之为AJAX应用的纯IE、XMLHTTP应用。 AJAX更酷的一点在于,对于传统的Web开发人员来说,AJAX所运用的, 是更加先进的,更加标准化的,更加和谐高效的,完整的Web开发技术体系。 遵循这样的体系开发Web应用,能让你的开发过程变得更加轻松,也能使你们 的开发团队,显得很酷。在Web2.0 的时代里,还在采用过时的技术来开发 Web,会显得很老土,很落伍。 AJAX的相关组成技术,每一个都已经出现了N年以上了,对这些技术的 组合运用,也远远早于AJAX这个名词出现之前。所以,我真正敬佩的,并非提 出 AJAX这个缩写的Jesse James Garrett。而是那些早在N年以前,就已经在探索、 实践的先行者,他们始终在追求的:是更好的用户体验,以及更好的开发体验。 这样的精神,才是最可宝贵的,也是最值得我们学习的。许多年过去以后,当我 们再回头来看当年的这些热门技术,也许早已经变得老土,变得落伍了。在这样 的历程中,哪些人会成长为高手?会成长为大师呢?就是那些永不满足,永远 在追求更好的用户体验,永远在追求更好的开发体验的人! 新手如何上路 软件开发这个领域,永远都在飞速发展,大家都必须不断的学习新的知识、 技能、框架、IDE、甚至新的语言。传说中的骨灰级高手们,就像传说中的大侠, 任何武器、哪怕是一块木头到了他们手里,也能发挥惊人的威力,人家练了几十 年的看家本领,他们随手使来,也竟然像是打娘胎里就开始练了一样。为什么? 就算不吹那么玄的,平常我们能够碰到的那些老手,在学新东西的时候, 也比那些新手学得更快,理解得更深,运用得更熟练。而新手们呢?往往就会漫 无头绪,焦头烂额,以一副张着茫然的大眼睛的经典表情,出现在各大论坛的 新手求助区里。他们欠缺的,究竟是什么呢?为什么老手学新东西,就没遇到那 么多困难呢? 泛泛地说,自然是经验上的欠缺。仔细地说来,又可以分为三个方面: 一、本质,一种技术与另一种技术之间,往往会有本质上的相通之处,当你 对一种技术的理解与思考越来越深入时,学习一种新技术也会更加容易。触类旁 通,举一反三的能力,就是来自于对于技术本质的追寻。 二、地图,本质上或多或少的相通,也提示着我们技术之间的相互关联,当 你了解的技术越多,了解得越是深入,在你的内心,就能建立起越发清晰的技 术地图。各种知识都有一个自然、合理的位置。那么当一个老手要学习一门新技术 的时候,他其实并非在探索一个全新的、未知的领域,而是有很多脉络可寻,也 很多已知可以帮助他们快速了解未知。 三、技巧,面对同样的未知,面对同样的难题,新手们一筹莫展,而老手们 却掌握着更多的技巧和手段,帮助他们试探可能性、缩小问题的范围、迅速定位 问题、不犯明显愚蠢的错误、甚至能够列举出更具命中力的搜索关键词,而这些 技巧,都帮助老手在前进的道路上,更少跌倒,即使跌倒,也能更快的爬起来。 作为一本写给新手的入门书籍,我们希望展现给读者的,是一个老手如何 学习新技术的过程。我们相信,这样的一个学习过程,对于新手来说,是更具有 价值的。 何谓快车道 必须老老实实的承认,我吹牛了!老手虽然会比新手学习得更快一些,但 是也同样会碰到麻烦,遇到障碍,感觉头痛。如果没有真正的专家的指导,我不 可能如此迅速地将AJAX掌握到目前这样的程度,要真是让我自学三个月,然 后就写出书来的话,那真是在骗钱了。 老手能够快速学习的另一个重要的诀窍是:认识很多牛人朋友 如果没有李锟与赵泽欣的专家级指导与帮助,如果没有与李锟AJAX结对 编程的体验,如果没有三个人在MSN上无数次的长聊,我想要在短期内建立起: 对于AJAX本质的理解; 对于整个AJAX以及相关技术地图的理解; 对于AJAX编程开发所需要的很多技巧、手段的掌握; 几乎是不可能的。 如果没有(N多需要感谢的人)的(N多方面的帮助),我们这本书,也 不可能以现在这样的深度,以(N个月)内完成的速度,送到读者的面前。 希望这本书,能够对大家快速学习AJAX,有所帮助。

310

社区成员

发帖
与我相关
我的任务
社区描述
福州大学的软件工程实践-2023学年-W班
软件工程需求分析结对编程 高校 福建省·福州市
社区管理员
  • FZU_SE_teacherW
  • Pity·Monster
  • 助教张富源
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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