Web コース設計のための学生の成績管理システム

Webコース設計に基づいた生徒の成績管理システム

1. 実験テーマ

学生の成績管理システム

2. 実験の目的

Webアプリケーション技術のコースデザインは、コンピュータソフトウェア工学専攻向けの総合実践学習プログラミングリンクであり、「インターネットとWebプログラミング」コースを学んだ後の総合演習です。コンピュータソフトウェア設計知識の見直しと定着を促進し、ソフトウェア設計手法、ソフトウェア設計手法、設計思想についての理解を深め、学んだソフトウェア設計知識とウェブエンジニアリング技術を活用して総合的なソフトウェア設計を行うことを目的としています。デザインコースでは、ソフトウェア設計の手法とオブジェクト指向設計の基礎技術を習得し、ソフトウェア開発における総合的な応用能力を向上させることができます。

このコースの設計を通じて、フロントエンド フレームワーク vue、vue デスクトップ コンポーネント ライブラリ elementui、バックエンド フレームワーク ssm の応用と学習をさらに習得し、学んだフレームワークの知識を実践に応用します。

本システムの設計に関して、筆者は以下の点を検討した結果、最終的に学生成績管理システムとして設計課題を決定した。

すべての学校には、生徒情報の追加・削除・修正・確認、生徒の成績の入力・閲覧、表のエクスポート、個人成績やクラス成績の分析、データ表示などができる教育管理システムがあり、教師が理解できる教育管理システムとなっています。したがって、生徒のパフォーマンス管理システムは非常に重要な応用価値があり、システムの使用自体は悪意のある操作を避けるために指定された担当者のログインを必要とします。今回の実験における管理システムはまさに上記の点を考慮し、生徒成績管理システムに必要な価値や機能を検討し、さらなる開発・設計を行っていくものであり、拡張機能はあるものの、まだ不十分な点もある。システム設計プロセスの詳細な分析。

3.全体のデザイン

3.1 実験要件:

1. 学生機能を追加します: 名前、学籍番号、性別、生年月日。(学生番号は自動的に生成され、一意です)。

2. 生徒の成績機能の追加: 全員が数学、Java、英語、体育の 4 つのコースを持ち、コースごとに成績を入力できます。

3. 学生 ID に基づいて学生の成績を検索する機能: 名前、学生 ID、成績をインターフェイスに表示し、学生 ID が存在しない場合はプロンプト メッセージを表示します。

4. 生徒の名前に基づいて生徒の成績を検索する機能 (あいまい一致をサポート): インターフェースに名前、生徒番号、成績を表示します。同じ名前の生徒が複数いる場合は、それらも一緒に表示されます。名前が存在しない場合は、プロンプトメッセージが表示されます。

5. 一人の生徒の科目ごとのヒストグラム分布図の作成をサポートします。

6. 学生情報の変更・削除機能:学生IDは変更できません。

7. 生徒の学習レポートレポートを作成する機能: レポートには、生徒番号、名前、各科目の成績とその科目の対応するクラス平均、合計成績とクラス合計成績の平均、およびソート結果が含まれます。 Excelファイルに出力されます。

システム機能の概念モデル:

ここに画像の説明を挿入

3.2 このシステムで使用されるテクノロジースタック:

プロジェクト管理ツール: Maven

バージョン管理システム:Git

フロントエンド技術: html、css、javascript、vue、elementui、Echarts

フロントエンドおよびバックエンド通信テクノロジー: axios

Webアプリケーションサーバー:Tomcat

データベーステクノロジー: MySql

バックエンドテクノロジー: Spring、SpringMVC、Mybatis、JavaBean、EasyExcel

3.3 このシステムで使用するプログラミングツール

コード作成: IntelliJ IDEA 2020.1

グラフィカルデータベース管理ツール: Navicat for MySQL

データベース モデリング ツール: PowerDesigner

Webアプリケーションサーバー:Tomcat7.0

プロジェクト管理ツール: Maven

コードホスティングサービス: gitee

3.4 コア技術の紹介

Vue: Vue.js は、ユーザー インターフェイスを構築するための進歩的なフレームワークです。他の重量級フレームワークとは異なり、Vue はボトムアップで段階的に開発されるように設計されています。Vue のコア ライブラリはビュー レイヤーのみに焦点を当てています。

Axios: Axios は、ブラウザーおよび Nodejs 用のPromiseに基づく HTTP クライアントです

Spring: Spring は、ビジネス ロジック層とエンタープライズ レベルのアプリケーション開発の他の層の間の結合問題を解決するために設計された軽量の Java 開発フレームワークです。

SpringMVC: SpringMVC はSpring フレームワークのモジュールであり、mvc に基づく Web フレームワーク モジュールです。MVC は、Web 側サービスのアーキテクチャ パターン、つまり、model -view-controller です。

MyBatis: MyBatis は、カスタム SQL、ストアド プロシージャ、および高度なマッピングをサポートする優れた永続層フレームワークです。MyBatis は、ほぼすべての JDBC コードと、パラメータの設定と結果セットの取得の作業を排除します。MyBatis は、単純な XML または注釈を通じて、プリミティブ型、インターフェイス、および JavaPOJO をデータベース内のレコードとして構成およびマッピングできます。

Echarts: PC およびモバイル デバイス上でスムーズに実行できる純粋な Javascript グラフ作成ライブラリであり、最新のブラウザと互換性があります。直感的、鮮明、インタラクティブ、そして高度にカスタマイズ可能なデータ視覚化チャートを提供します。

EasyExcel: EasyExcel は、Excel の読み取りと書き込みを行うための、シンプルな Java ベースのメモリ節約型オープン ソース プロジェクトです。メモリを極力節約した場合、100メガバイトのExcelの読み書きに対応します。

3.5 モジュールの紹介

データベースの概念的なデータ モデルの設計:

ここに画像の説明を挿入

データベーステーブルの設計:

ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

ログインモジュール:
ここに画像の説明を挿入

ホームモジュール:
ここに画像の説明を挿入
学生情報照会モジュール:

ここに画像の説明を挿入

生徒の成績照会モジュール:

ここに画像の説明を挿入
生徒のパフォーマンス分析モジュール:
ここに画像の説明を挿入

新しい生徒情報の作成、生徒の成績の入力、生徒の成績の表示、生徒情報の編集などを行うためのモーダル ボックス モジュール:

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

3.6 設計手順

1. Maven プロジェクトを作成し、パブリック静的ファイルを追加し、web.xml などのコア構成ファイルを作成します。

2. ssm 構成ファイルを作成し、Mybatis リバース エンジニアリングを使用してマッパー ファイルとエンティティ クラスを生成し、マッパー構成ファイルを変更して、成績を含む学生情報をクエリするメソッドを追加します。

3. vue および elementui コンポーネント ライブラリ ファイルを導入し、フロントエンド ページの全体的なフレームワークを設計し、PageHelper を使用してバックエンド コントローラー コントロール層のページング コードを記述し、通常どおり JSON データを返します。

4. 学生情報をページ単位で照会し、トップページに表示する機能を実現。

5. 生徒情報の追加・削除機能を実現。

6. 生徒情報の修正機能を実現 編集ボタンをクリックすると編集モーダルボックスにバックグラウンドデータが反映され、データ検証を行って即時情報を提供することができます。

7. 生徒情報照会ページで生徒の成績入力と生徒の個人成績確認機能を実現。そして、生徒の成績を変更できる、生徒の成績を照会するページを実現します。

8. クラス内の生徒の成績と各科目の平均点を分析し、生徒の成績のヒストグラムを生成するという共通機能を実現し、クラス内の各科目の平均点を更新するコードを関数にカプセル化し、動作を完成させます。クラスの平均スコアの変更が含まれる可能性があります。コードでは avg_grade データベースを使用します。

9. フロントエンドインターフェイスを美しくし、ログインと登録の機能を実現し、ユーザーがログインせずにシステムにアクセスできないようにインターセプターを設計します。

10. 生徒の成績分析ページで問い合わせたクラスの生徒の学習状況の表示を実現 クラスの生徒の平均合計点を、成績表に応じて優、良、中、合格、不合格の5段階に分けて表示します。各段階の得点基準を示し、各学年の生徒数の分布を円グラフでトップページに表示します。

11. システムを終了する機能を実現します。システムの終了をクリックすると、Web サイトのセッション データが削除され、現在のページが更新されてログイン インターフェイスに入ります。ユーザーはシステムにアクセスし続けるためにログインする必要があります。 。

12. 生徒の成績を含む生徒情報を Excel ファイルにエクスポートします。

4. 詳細設計

4.1 プロジェクト リソース ディレクトリの概要:

ここに画像の説明を挿入

ここに画像の説明を挿入

4.2 キーコードの紹介

4.2.1 Maven プロジェクトを作成し、関連する jar パッケージの依存関係をインポートする

① ssm フレームワーク関連の jar パッケージの依存関係: spring-webmvc、spring-jdbc、spring-aspects、mybatis、mybatis-spring

②データベース接続ドライバー関連のjarパッケージの依存関係:c3p0、mysql

③ サーバープラグインの依存関係: tomcat7-maven-plugin

④ その他のjarパッケージの依存関係: jstl、servlet-api、junit

⑤ フォローアップで使用する必要がある jar パッケージの依存関係: mybatis-generator-core (mybatis リバース エンジニアリング)、pagehelper (ページング プラグイン)、spring-test、jackson-databind (返す json 文字列をサポート)、hibernate -validator (JSR303 データ検証サポート)、log4j (log4j ログ ファイル)、easyexcel (Excel フォームのエクスポート)。

4.2.2 spring、springmvc、mybatis 設定ファイルの書き込み

① web.xml ファイルを記述する

Spring コンテナーを開始し、applicationContext.xml ファイルを作成するコードを記述します (主に構成とビジネス ロジックに関連します)。springmvc のフロント コントローラーを設定し、dispatcherServlet-servlet.xml ファイルを作成します。文字エンコードフィルターを設定します。

② springmvcの設定

dispatcherServlet-servlet.xml で springmvc (Web サイトジャンプロジックの制御を含む) を設定します。

<!--    扫描控制器组件-->
    <context:component-scan base-package="com.shenshang" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

③スプリングを設定する

applicationContext.xml で Spring を構成します。主な構成はビジネス ロジックに関連します。データ ソースの構成、mybatis との統合の構成、スキャナーの構成、トランザクション マネージャーの構成、および注釈ベースのトランザクションの有効化。

④mybatisの設定

公式ドキュメント内の対応する構成テンプレートをコピーし、キャメルケースの命名規則を含むグローバル構成ファイルを作成し、typeAliases タグを使用して Java 型のエイリアスを作成します。

4.2.3 mybatis リバースエンジニアリングを使用してマッパー設定ファイルを変更する

MyBatis Generator: 略して MBG は、MyBatis フレームワーク ユーザー向けに特別にカスタマイズされたコード ジェネレーターであり、テーブルに従って対応するマッピング ファイル、インターフェイス、Bean クラスを迅速に生成できます。基本的な追加、削除、変更、クエリ、および QBC スタイルの条件付きクエリをサポートします。ただし、テーブル接続やストアドプロシージャなどの複雑なSQLの定義は手動で記述する必要があります。

PowerDesigner を使用してデータベース概念モデルの ER 図を設計し、それを SQL ステートメント ファイルとしてエクスポートし、navicat で実行して外部キー関係を自動的に作成するテーブルを生成します。

mybatis 公式 Web サイトの mybatis リバース エンジニアリングの使用例を参照し、メイン プロジェクトに mbg.xml ファイルを作成し、サンプル コードを mbg.xml にコピーし、mbg.xml ファイルを変更し、データベース接続を設定し、場所を指定します。 JavagBeanが生成される場所を指定し、sql Mapを指定します。 マッパーファイルが生成される場所を指定し、daoインターフェースが生成される場所を指定し、各テーブルの生成戦略を指定します。mybatis 公式 Web サイトの「Running MyBatis Generator」で Java プログラムを見つけ、テスト フォルダー test に MBGTest.java を作成し、このコードを実行し、リバース エンジニアリングして指定されたファイルを生成します。

複雑な接続クエリ SQL ステートメントは手動で記述する必要があるため、マッパー ファイルを変更して接続テーブルの SQL ステートメントを記述します。これにより、ビジネス ロジック メソッドを作成するときにメソッドを直接呼び出して、単一の生徒の情報をクエリできるようになります。成績と生徒のリスト。マッパーファイルを修正した後、テストフォルダーtest内にMapperTest.javaを作成し、実装クラスの操作データベースメソッドをテストするためのインターフェースを作成し、バグがないか観察し、さらにコードを修正・改善します。

4.2.4 静的ファイルとコンポーネント ライブラリ ファイルをインポートし、json データを返すようにテストします。

webapp パッケージ内にプラグインと静的パッケージを作成し、vue、elementui、jquery、axios などのコンポーネント ライブラリ ファイルを導入します。Controller パッケージに stuInfoController.java ファイルを作成し、PageHelper ページング プラグインを使用して、JSON データを返せるかどうかをテストします。

@ResponseBody
@RequestMapping("/findPage")
public Msg getPageInfoWithJson(@RequestParam(value = "pn",defaultValue = "1")Integer pn){
    
    
    PageHelper.startPage(pn,5);
    List<Student> studentList = stuInfoService.getStudentList();
    PageInfo pageInfo = new PageInfo(studentList,5);
    return Msg.success().add("pageInfo",pageInfo);
}

4.2.5 フロントエンドページにページングして表示することで学生情報を照会する機能を実現

フロントエンドページのコードを記述し、elementui公式ドキュメントを参照し、コンポーネントを追加し、入力ボックスのコンポーネントラベル内でv-modelを使用して、クエリ入力ボックス、入力ボックスのコンテンツの入力、フロントなどの双方向のデータバインディングを実現します。 -end v-model データ バインディング その後、post リクエストが axios を通じて送信され、コントローラー層はパラメーター マッピングに @RequestBody アノテーションを使用し、フロントエンド パラメーターを取得し、Service インターフェイスと Service 実装クラスを作成し、Service エンティティ クラスを作成します。オブジェクトを取得し、エンティティクラスの内部メソッドを呼び出してデータベースを操作し、学生情報リストを問い合わせ、全体の情報とデータをPageResultにカプセル化してController層に返し、フロントエンドに戻ります。

学生情報を取得する Service インターフェイスは、クラス メソッド getStudentList() を実装します。

public PageResult getStudentList(Integer currentPage, Integer pageSize, String queryString){
    
    
//        截取查询条件
    String[] queryList = queryString.split("-");
//        正则表达式判断字符串是否为数字
    Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
    StudentExample studentExample = new StudentExample();
    StudentExample.Criteria criteria = studentExample.createCriteria();
    for (int i = 0; i < queryList.length; i++) {
    
    
        if (pattern.matcher(queryList[i]).matches() && !queryList[i].equals("")&& Integer.parseInt(queryList[i] <= 7)){
    
    //字符串是数字且不为空且不小于7
            int classId = Integer.parseInt(queryList[i]);//将该字符串转换成数字
            criteria = criteria.andClassidEqualTo(classId);//将班级id拼接到查询条件中
        }else if (!queryList[i].equals("")){
    
    
            criteria = criteria.andNameLike("%"+queryList[i]+"%");//将姓名拼接到查询条件
        }
    }
        PageHelper.startPage(currentPage,pageSize);
//        Page<Student> page = (Page<Student>) studentMapper.selectByExample(studentExample);
    Page<Student> page = (Page<Student>) studentMapper.selectByExampleWithGrade(studentExample);
    return new PageResult(page.getTotal(),page.getResult());
}

フロントエンドは axios リクエストを送信してバックエンド データを取得し、パラメーターを割り当てます。

//分页查询学生信息
searchBtn(){
    
    
    // 使得查询按钮点下时都是从第一页开始显示数据
    this.pagination.currentPage = 1;
    //分页参数
    let param = {
    
    
        currentPage:this.pagination.currentPage,
        pageSize:this.pagination.pageSize,
        queryString:this.queryString.queryName+'-'+this.queryString.classSelected
    };
    // axios请求后台获取数据
    axios.post("/stuInfo/findPage",param).then((response)=>{
    
    
        // 为模型数据赋值,通过vue的双向数据绑定输出到页面
        this.tableData = response.data.rows;
        this.pagination.total = response.data.total;
    })
},

注: PageResult エンティティ クラスを作成する目的は、ページング結果クラスをカプセル化し、クエリ データとページング バー情報を一緒にフロント エンドに返すことです。

4.2.6 生徒情報追加機能の実現

全体的なロジックはクエリ ロジックと似ています。[追加] ボタンをクリックした後、ポップアップ モーダル ボックス内でフォームをリセットする必要があることに注意してください。それ以外の場合、フォームは最後に残ったデータと検証情報を保持したままになります。ユーザーに不快な体験を与える入力。さらに、新しいモーダル ボックス内の [OK] ボタンをクリックすると、axios リクエストが送信され、フロント エンドによって渡されるパラメーターには、生徒の名前、性別、クラス、誕生日などの情報が含まれます。 @RequestBody アノテーションを使用して json を配置します データは、対応するエンティティ クラスに自動的に変換されます。フロント エンドによって渡されるパラメータは、エンティティ クラスの対応する属性名と同じである必要があります。それ以外の場合、バックエンドによって受け取られるパラメータは空。新しい学生情報のService実装クラスメソッド本体のデータベースで性別と誕生日が統一されたデータ型に変換された後、studentMapperを通じてinsertSelective()メソッドが呼び出され、データベースのデータが挿入されます。

新しい生徒情報の Service インターフェイス実装クラス メソッド add():

public void add(Student student) {
    
    
//        随机生成学号
    Random random = new Random();
    int sId = random.nextInt(5000) + 7;//学号
    student.setId(sId);
//        把参数中学生性别进行转换
    if (student.getSex().equals("1")){
    
    
        student.setSex("男");
    }else{
    
    
        student.setSex("女");
    }
//        设置学生生日格式为"xxx年xx月xx日"
    String birthday = student.getBirthday();
    String[] birthdaySplitList = birthday.split("-");
    student.setBirthday(birthdaySplitList[0]+"年"+birthdaySplitList[1]+"月"+birthdaySplitList[2]+"日");
//        调用函数新增学生信息
    studentMapper.insertSelective(student);
}

なお、フロントエンドではフォーム検証を行う必要があり、フォーム検証が確認ボタンを通過できない場合は、プロンプトメッセージが表示され、axios リクエストを送信できません。確認ボタンをクリックすると、通話終了メソッドの後にaxiosリクエストが送信されます。

フロントエンドに学生情報モーダルボックスフォーム検証ルールを追加しました。

rules:{
    
    //学生信息表单校验规则
    stuName:[
        {
    
     required: true, message: '请输入姓名', trigger: 'blur' },
        {
    
     min :2,max :5,message: '输入姓名长度在2到5个字符' },
    ],
    stuSex:[
        {
    
     required: true, message: '性别必须选择', trigger: 'blur'}
    ],
    stuClass:[
        {
    
     required: true, message: '班级必须选择', trigger: 'blur'}
    ],
    stuBorn: [
        {
    
     required: true, message: '请输入出生日期', trigger: 'blur' },
    ]
},

フロントエンドリセットフォームデータと検証情報メソッド:

// 重置表单数据和表单校验信息
resetForm(){
    
    
    // 把模态框表单中数据清空
    this.modalBox.form = {
    
    
        // stuId: '',
        stuName: '',
        stuSex: '1',
        stuClass: '',
        stuBorn:''
    };
    // 清除上次校验效果
    this.$nextTick(()=>{
    
    //Dom没有加载完成,导致获取不到refs元素
        // 方法作用是当数据被修改后使用这个方法,会回调获取更新后的dom再渲染出来
        this.$refs['modalBox.form'].clearValidate(['stuName','stuSex','stuClass','stuBorn']);
    })
},

「OK」ボタンをクリックして、フォーム入力情報が検証ルールを満たしているかどうかを確認します。満たされていない場合は、「フォームデータの検証に失敗しました」というプロンプトメッセージが表示されます。満たされている場合は、axios リクエストが送信され、キーが送信されます。コードは後続の同様の操作で与えられます。

4.2.7 生徒情報削除機能の実現

まず注意すべき点は、成績テーブルと学生テーブルの外部キー関係が正しく確立されていないと、学生情報を削除する際にバグが発生するということです。削除ボタンをクリックすると、学生IDがxxxの学生情報を削除するかどうかを確認するメッセージが表示され、OKをクリックすると、指定した学生IDの学生情報が削除されます。 「キャンセル」をクリックすると、操作は実行されません。さらに、ユーザーが [OK] ボタンをクリックすると、axios リクエストは 1 つのパラメータ (学生番号) だけで送信されますが、作成者は削除関数を作成するときに長い間行き詰まっていました。フォアグラウンドでは生徒番号のパラメータを送信し、バックグラウンドでも @RequestBody アノテーションを使用してパラメータを受信して​​いるため、バックグラウンドで取得されたデータには余分な等号が付いており、不可解です。データ バインディングをスクリーニングした結果、バインドされていないことがわかりました 大量のデータを収集した結果、フロント エンドとバック エンドの間でデータ送信の種類が異なることが原因であることがわかりました。多くの情報を収集した結果、フロントエンドが axios リクエストを送信するとき、デフォルトのリクエスト ヘッダー内の Content-Type はキーである application/x-www-form-urlencoded;charset=UTF-8 であることがわかりました。 -value ペアデータ構造、送信処理中に json がキーとみなされ、値が null 値とみなされ、バックエンドに送信されるときに余分な等号が発生します。この問題を解決するには、axiosリクエスト送信時にリクエストヘッダ情報を設定し、バックエンドが受信するデータエンコーディングをフロントエンドの設定と統一する必要があります。

フロントエンド コードが削除ボタンをクリックしたときに実行されるメソッド コード:

// 删除按钮,点击删除单行数据
handleDelete(row) {
    
    
    this.$confirm('确定删除学号为'+row.id+'的学生信息吗?', '提示', {
    
    
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    }).then(() => {
    
    
       // 发送ajax请求,请求后台删除指定学号的学生信息
        axios.post("stuInfo/delete",row.id,{
    
    
            headers: {
    
    
                'Content-Type':'application/json'
            }
        }).then((response)=>{
    
    
            if (response.data.flag){
    
    
                // 删除成功
                this.$message({
    
    
                    message: response.data.message,
                    type: 'success'
                })
            }else{
    
    
                // 删除失败
                this.$message.error(response.data.message);
            }
        }).finally(()=>{
    
    
            // 重新获取删除后的分页数据
            this.searchBtn();
        })
    });
},

バックエンドのコントローラー層がパラメーターを受信するときは、受信したデータの形式も指定する必要があります。

@RequestMapping(value = "/delete",produces = "application/json;charset=UTF-8")//指定接收数据的格式
public Result deleteStuInfo(@RequestBody String id){
    
    
    try {
    
    
        int sid = Integer.parseInt(id);
        stuInfoService.deleteById(sid);
    }catch (Exception e){
    
    
        e.printStackTrace();
        return new Result(false , MessageConstant.DELETE_STU_FAIL);
    }
    return new Result(true , MessageConstant.DELETE_STU_SUCCESS);
}

次に、Service インターフェイス実装クラスの StudentMapper エンティティ クラスを使用して、deleteByPrimaryKey() メソッドを呼び出し、指定された学生番号の学生情報をデータベースから削除します。

4.2.8 学生情報変更機能の実現

他の機能との違いは、編集ボタンをクリックすると編集モーダルボックスがポップアップし、編集モーダルボックスフォームに生徒の情報をエコーアウトする必要があることです。フロントエンドとバックエンドのデータ保存形式を変換します。データ形式を変換するには、編集モーダルボックスフォーム内のデータも検証する必要があります。形式が間違っている場合は、検証を求めるメッセージが表示されます。検証が完了した場合のみ、合格した場合、変更は成功し、データベース内の指定された学生番号が更新されます。フロントエンドの編集ボタンをクリックし、dialogFormVisibleEdit の値を true に変更してモーダルボックスの表示を実現し、axios を送信して背景データをリクエストします。この時点ではまだ学生 ID のパラメータが渡されていることに注意してください。リクエストヘッダー情報を設定する必要があり、バックエンドが受信するデータエンコーディングをフロントエンドの設定と統一し​​ます。

フロントエンドが編集ボタンをクリックした後に実行されるエコー データ メソッド コード:

// 表格中的编辑按钮
handleUpdate(row){
    
    
    // alert(row.id);
    // 发送请求获取目前行学生信息
    axios.post("/stuInfo/findById",row.id,{
    
    
        headers:{
    
    
            'Content-Type':'application/json'
        }
    }).then((response)=>{
    
    
        if (response.data.flag){
    
    
            // 显示出编辑模态框
            this.modalBox.dialogFormVisibleEdit = true;
            // 将数据回显到编辑模态框的表单中
            this.modalBox.editForm.stuId = response.data.data.id;
            this.modalBox.editForm.stuName = response.data.data.name;
            this.modalBox.editForm.stuSex = response.data.data.sex == "男"? '1':'0';
            this.modalBox.editForm.stuClass = response.data.data.classid;
            this.modalBox.editForm.stuBorn = response.data.data.birthday;
        }else{
    
    
            this.$message.error(response.data.message);
        }
    })
},

フロントエンドの取得または受信はデータベースに格納されるデータ形式と異なるため、バックエンドのServiceインタフェース実装クラスのfindById()メソッドで、データベースの学生情報データの形式を変換する必要があることに注意してください。クエリされたデータベースで指定された学生番号を取得し、フロントエンドの表示に戻ります。

public Student findById(Integer id) {
    
    
    Student student = studentMapper.selectByPrimaryKey(id);
//            把xx年xx月xx日格式的字符串转变成xx-xx-xx格式的字符串,便于在前端赋值给日期选择器
//            2014年01月10日
    String year = student.getBirthday().substring(0,4);
    String mouth = student.getBirthday().substring(5,7);
    String day = student.getBirthday().substring(8,10);
//            重新设置student类的birthday属性遵循xx-xx-xx的格式
    student.setBirthday(year+"-"+mouth+"-"+day);
    return student;
}

編集モーダル ボックスの [OK] ボタンをクリックすると、最初にフォーム データを検証する必要があります。入力ボックスの入力情報が検証ルールを満たしていない場合は送信できず、変更しない場合でもプロンプト メッセージが表示されます。学生情報に変更が加えられると、更新メソッドは引き続きバックグラウンドで実行されますが、学生情報は元の情報に更新されます (つまり、変更は行われません)。フロントエンド フォーム検証メソッドのコードは次のとおりです。ここに投稿されており、使用する必要がある他の確認コードはここと同じです。

//编辑模态框中的确定更新按钮
handleEdit() {
    
    
    let param = {
    
    
        id:this.modalBox.editForm.stuId,
        name:this.modalBox.editForm.stuName,
        sex:this.modalBox.editForm.stuSex,
        classid:this.modalBox.editForm.stuClass,
        birthday: this.modalBox.editForm.stuBorn
    }
    // 校验表单数据
    this.$refs['modalBox.editForm'].validate((valid)=>{
    
    
        if (valid){
    
    
            // 校验成功,发送axios请求
            axios.post("stuInfo/update",param).then((response)=>{
    
    
                // 隐藏编辑模态框
                this.modalBox.dialogFormVisibleEdit = false;
                if (response.data.flag){
    
    
                    // 更新数据成功
                    this.$message({
    
    
                        message: response.data.message,
                        type: 'success'
                    });
                }else{
    
    
                    // 更新数据失败
                    this.$message.error(response.data.message);
                }
            }).finally(()=>{
    
    
                // 展示更新后的表格数据
                this.searchBtn();
            })
        }else{
    
    
            // 校验失败
            this.$message.error('表单校验数据失败');
            return false;
        }
    })
},

4.2.9 学生情報管理ページでの学生成績の入力と閲覧機能を実現

この機能を実現するために注意すべき点は、フロントエンドページの表に操作欄があり、その操作欄に入力と閲覧の2つのボタンがあり、成績を入力していない場合は入力ボタンが表示されます。はクリックできますが、表示ボタンはクリックできません。生徒の成績を入力した後、表示ボタンをクリックすると生徒の成績が表示され、入力ボタンは繰り返しの入力を避けるため、または成績の確認を避けるためにクリックできないように設定されています。空になること。この操作の実装は、主にデータベース s_stu テーブルのフラグ値に基づいて行われます。生徒の成績が入力されていない場合 (新しい生徒情報を作成した後)、フラグの値は null になります。このとき、入力ボタンがフラグ値が null の場合、クリック可能な状態に設定されます。表示ボタンをクリックできない状態に設定します。生徒の成績が入力されている場合は、フラグの値を 1 に設定します。入力ボタンがフラグの値が 1 であることを検出した場合、フラグの値を 1 に設定します。入力ボタンをクリックできない状態にし、表示ボタンをクリックできる状態にします。フロントエンドの 2 つのボタンのコードは次のとおりです。

<el-button slot="reference" type="text" size="small" :disabled="scope.row.flag == 1? false:true">查看</el-button>
<el-button type="text" size="small" @click="gradeInput(scope.row)" :disabled="scope.row.flag == 1? true:false">录入</el-button>

入力ボタンをクリックすると、成績入力用のモーダルボックスが表示され、フォームデータと認証情報がリセットされ、取得した学生IDがフォーム内のstuIdに割り当てられ、後のデータ引き継ぎが容易になります。入力モーダル ボックスの [OK] ボタンをクリックすると、フォームの入力内容を検証する必要があり、入力結果が検証ルールを満たし、学生のフラグ値が指定された場合にのみ axios リクエストを送信できます。学生番号はサービス インターフェイス実装クラス 1 に設定され、学生の成績を s_grade テーブルに挿入します。

バックエンドサービスインターフェース実装クラスのメソッドコード:

public void inputGrade(Grade grade) {
    
    
//        计算出该学生的总成绩
    Integer sum = grade.getMath()+grade.getJava()+grade.getEnglish()+grade.getPe();
    grade.setGradenum(sum);
//        把指定学号的学生信息的flag值置为1,表示该学生的成绩已经录入了
    Student student = studentMapper.selectByPrimaryKey(grade.getId());
    student.setFlag(1);
//        将数据更新到数据库中
    studentMapper.updateByPrimaryKeySelective(student);
    gradeMapper.insertSelective(grade);
}

生徒の成績を入力すると、フロントエンドの表示ボタンがクリック可能な状態になり、このとき表示ボタンをクリックすると、生徒の個人成績を表示するメッセージプロンプトボックスがポップアップ表示されます。ロジックの実装は主に、Elementui のタグを使用したフロントエンド コードによって実装されます。ページ分割されたデータを表示するためにバックエンド実装クラス メソッドで使用されるクエリ メソッドは、成績を持つ学生のリストをクエリすることであるため、フロントエンドデータで生徒の成績を表示するときにバックエンドをリクエストし、フロントエンドパラメータ値を直接表示するだけです。

フロントエンドで結果を表示するコードは次のとおりです。

<el-table-column label="成绩" width="185">
    <template slot-scope="scope">
        <el-popover placement="right" width="200" trigger="click">
            <el-tag>学号:{
    
    {
    
    scope.row.id}}</el-tag>
            <el-tag type="success">姓名:{
    
    {
    
    scope.row.name}}</el-tag>
            <p><el-tag type="warning">数学成绩:{
    
    {
    
    scope.row.grade.math}}</el-tag></p>
            <p><el-tag type="warning">java成绩:{
    
    {
    
    scope.row.grade.java}}</el-tag></p>
            <p><el-tag type="warning">英语成绩:{
    
    {
    
    scope.row.grade.english}}</el-tag></p>
            <p><el-tag type="warning">体育成绩:{
    
    {
    
    scope.row.grade.pe}}</el-tag></p>
            <p><el-tag type="danger">总成绩:{
    
    {
    
    scope.row.grade.gradenum}}</el-tag></p>
            <el-button slot="reference" type="text" size="small" :disabled="scope.row.flag == 1? false:true">查看</el-button>
        </el-popover>
        <el-button type="text" size="small" @click="gradeInput(scope.row)" :disabled="scope.row.flag == 1? true:false">录入</el-button>
    </template>
</el-table-column>

4.2.10 生徒の成績の照会と指定された生徒の成績の変更機能の実現

GradeSearch.html ファイルを作成し、フロントエンド コンポーネントを追加します。ここでのクエリ関数は、学生情報のクエリ関数と似ています。フロント エンドとバック エンドの両方でクエリ条件のスプライシングを使用します。学生番号、名前、とクラス、およびフロントエンドがクエリ条件を結合し、中央の「-」記号を使用して接続します。データがバックエンドに送信されるときに、split() メソッドを使用して文字列を切り取り、文字列配列を走査します。切り取って生成し、学籍番号とクラス文字列を数値に変換し、SQL文につなぎ合わせてデータベースを操作します。ここでは、SQL文のつなぎ合わせで生徒番号とクラス番号を処理していますが、クラス番号と生徒番号は数値に変換できるため、文字列配列単位の値が生徒番号なのかクラスなのかを判断する必要があります。ここでの規則は、生徒番号は 7 より大きくなければならず、クラス番号は 7 より大きくてはいけないため、それに応じて判断してください。

バックエンド Service インターフェイスのクラス メソッドを実装するコードは次のとおりです。

public PageResult getStudentList(Integer currentPage, Integer pageSize, String queryString){
    
    
//        截取查询条件
    String[] queryList = queryString.split("-");
//        正则表达式判断字符串是否为数字
    Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
    StudentExample studentExample = new StudentExample();
    StudentExample.Criteria criteria = studentExample.createCriteria();
    for (int i = 0; i < queryList.length; i++) {
    
    
        if (pattern.matcher(queryList[i]).matches() && !queryList[i].equals("")){
    
    //字符串是数字且不为空
            int tmp = Integer.parseInt(queryList[i]);
            if (tmp > 7){
    
    //说明tmp是学号
                int stuId = tmp;//把中间值赋值给学号
                criteria = criteria.andIdEqualTo(stuId);//把学号拼接到查询条件中
            }else{
    
    //说明tmp是班级号
                int classId = Integer.parseInt(queryList[i]);//将该字符串转换成数字
                criteria = criteria.andClassidEqualTo(classId);//将班级id拼接到查询条件中
            }
        }else if (!queryList[i].equals("")){
    
    
            criteria = criteria.andNameEqualTo(queryList[i]);//将姓名拼接到查询条件
        }
    }
    PageHelper.startPage(currentPage,pageSize);
    Page<Student> page = (Page<Student>) studentMapper.selectByExampleWithGrade(studentExample);
    return new PageResult(page.getTotal(),page.getResult());
}

GradeSearch.html のフロントエンド ページでは、各科目の指定した学生の成績を変更できます。編集ボタンをクリックして、成績編集モーダル ボックスをポップアップ表示します。モーダル ボックスをポップアップ表示する前に、フォームをクリアする必要がありますデータを取得してフォーム検証情報をリセットすることも必要です。フォーム データがエコーされて検証され、指定された検証ルールを満たすデータをバックエンドに送信できます。検証ルールを満たさないフォーム データは送信できません。 「OK」ボタンをクリックするとプロンプトメッセージが表示されます。なお、編集ボタンもs_stuテーブルのフラグ値を判定して編集ボタンがクリックできるかどうかを判断し、スコアを入力していない生徒(フラグ値がnull)のスコア編集ボタンを「スコア編集ボタン」に設定します。クリックできない状態。

バックエンド サービス インターフェイスの実装クラス メソッドは、指定された学生の成績を更新します。

public void update(Grade grade) {
    
    
    int sum = grade.getMath()+grade.getJava()+grade.getEnglish()+grade.getPe();
    grade.setGradenum(sum);
    gradeMapper.updateByPrimaryKey(grade);
//        根据学生学号查询出该学生所在班级
    Integer sid = grade.getId();
    Student student = studentMapper.selectByPrimaryKey(sid);
    Integer classid = student.getClassid();
    updateAvgClassGrade.updateAvgGrade(classid);
}

4.2.11 クラス内の生徒の成績と各科目の平均点の分析を実現し、ヒストグラムを生成する

html ファイルにフロントエンド コンポーネントを追加すると、このページには生徒番号を指定して生徒の成績を分析する機能のみが実装されます。生徒番号が重複しないようにすることができるため、名前が重複する現象がある場合は、分析することは不可能です。同じ名前の生徒の成績ヒストグラムをクエリして分析します。つまり、ヒストグラムの数が不確実であり、名前を介して同じ名前の生徒をクエリするためフロントエンド ページが引き伸ばされるため、生徒の成績だけを確認できます。学生番号を照会して分析し、対応するヒストグラムを生成します ここでは Javascript のアイコン ライブラリを使用します。クエリボタンをクリック後、入力ボックスに入力された学生番号が空の場合は何も実行されず、入力内容が空でない場合は入力された学生番号をリクエストパラメータとしてaxiosリクエストが送信されます。今回は、リクエスト ヘッダーのヘッダー情報を設定し、バックエンドによって受信されるデータ エンコーディングをフロントエンドの設定と統一する必要があることに注意してください。学生番号がバックエンドに送信された後、バックエンドは指定された学生番号と成績を持つ 1 人の学生の情報をクエリしてフロントエンドに返します。フロントエンドによって取得されたデータが空の場合、クエリされた学生番号が返されていることを意味します。は存在しないため、 idIsNull を true に割り当て、学生番号が存在しないことを示すプロンプト メッセージを表示し、学生のクラス内の各科目の平均成績を取得するためのリクエストがこれ以上送信されないことを示します (学生が存在しない場合、クラスは存在してはなりません); フロントエンドによって取得されたデータが空でない場合は、フロントエンドの双方向バインディングのパラメーターに値を割り当てて、縦棒グラフに縦棒を生成します。次に axios リクエストを再度送信して、学生のクラス内の各科目の平均成績を取得します (idIsNull 値が false の場合、学生番号が存在することを示します)。入力パラメータはバックエンド後の学生のクラス番号です。パラメータを取得し、エンティティ クラス avgGradeMapper を作成して挿入し、avgGradeMapper エンティティ クラスを介して selectByPrimaryKey() メソッドを呼び出し、avg_grade テーブル内の指定されたクラスの各科目の平均成績をクエリします。クエリ結果は先頭に返されます。 -end を指定すると、フロントエンドが双方向バインディング データを割り当てて、縦棒グラフにポリラインを生成します。ここのコードは改善および更新されています。ここの第 1 世代バージョンは、生徒のクラス番号を通じてこのクラスの成績を持つすべての生徒のリストをクエリし、クラス内の各科目の平均と合計成績の平均を計算します。生徒情報の新規作成時や成績の入力時、生徒の成績の修正時、生徒情報の削除時に、各科目の平均値やクラスの成績の平均値が表示される場合があることを考えた結果、最初のバージョンのコードでは avg_grade テーブルがまったく役に立たないため、作成者はクラス内の各科目の平均値と合計点の平均点を計算するコードをメソッドに個別にカプセル化し、クラススコアに影響を与える可能性のあるサーブ

バックエンドによってカプセル化されたクラスの成績を計算するためのメソッド コード:

public void updateAvgGrade(int classId) {
    
    
    //更新该学生班级的各科平均成绩
    Integer mathSum = 0,javaSum = 0,englishSum = 0,peSum = 0,gradeNumSum = 0;
    StudentExample studentExample = new StudentExample();
    StudentExample.Criteria criteria = studentExample.createCriteria();
    criteria.andClassidEqualTo(classId);
    List<Student> students = studentMapper.selectByExampleWithGrade(studentExample);
//        循环遍历这个班级的每个学生,算出各科平均分
    for(Student stu : students) {
    
    //因为存在没录入成绩的学生,所以不能直接累加
        if (stu.getGrade().getMath() != null) mathSum += stu.getGrade().getMath();
        if (stu.getGrade().getJava() != null) javaSum += stu.getGrade().getJava();
        if (stu.getGrade().getEnglish() != null) englishSum += stu.getGrade().getEnglish();
        if (stu.getGrade().getPe() != null) peSum += stu.getGrade().getPe();
        if (stu.getGrade().getGradenum() != null) gradeNumSum += stu.getGrade().getGradenum();
    }
    int studentSize = students.size();//班级的学生总数
    float math = (float)mathSum / studentSize;//班级的数学成绩平均分
    float java = (float)javaSum / studentSize;//班级的java成绩平均分
    float english = (float)englishSum / studentSize;//班级的英语成绩平均分
    float pe = (float)peSum / studentSize;//班级的体育成绩平均分
    float gradeNum = (float)gradeNumSum / studentSize;//班级的总成绩平均分
//        把班级平均数封装成对象
    avgGrade gradeAvgClass = new avgGrade(classId,math,java,english,pe,gradeNum);
    avgGradeMapper.updateByPrimaryKey(gradeAvgClass);
}

なお、入力された学生IDが空ではなく、入力された学生IDが存在する場合、フロントエンドはaxiosリクエストを2回連続して送信しますが、連続送信と同時送信の区別が必要です。 2 番目の axios リクエストはパラメータとして学生のクラス番号を取るため、クエリは 2 番目の axios リクエストを送信する前に取得する必要があります。一部の入力値が空であったり、学生 ID が存在しなかったりするその他の状況については上で説明したため、ここでは繰り返しません。

フロントエンドがクエリ ボタンをクリックした後に実行されるメソッド コード:

gradeAnalysis(){
    
    
    if (this.queryStr.queryId == undefined || this.queryStr.queryId == null || this.queryStr.queryId == '') return false;
    axios.post("stuAnalysis/searchById",this.queryStr.queryId,{
    
    //发送请求根据学生学号查询其成绩
        headers:{
    
    
            'Content-Type':'application/json'
        }
    }).then((response)=>{
    
    
        this.showOutPutBtn = true;
        if (response.data.flag){
    
    
            if (response.data.data == null){
    
    
                this.idIsNull = true;//该学号不存在,设置标志值以至于判断是否发送第二个请求
                this.$message.error('学号不存在');
                // 清空柱状图数据
                this.resetCharts();
                this.initCharts();//初始化图表
                return false;//终止请求
            }else{
    
    
                this.queryResult.stuId = response.data.data.id + "";
                this.queryResult.stuName = response.data.data.name + "";
                this.queryResult.stuClass = response.data.data.classid + "";
                this.queryResult.gradeMath = response.data.data.grade.math + "";
                this.queryResult.gradeJava = response.data.data.grade.java + "";
                this.queryResult.gradeEnglish = response.data.data.grade.english + "";
                this.queryResult.gradePE = response.data.data.grade.pe + "";
                this.queryResult.gradeNum = response.data.data.grade.gradenum + "";
                this.$message({
    
    
                    message: response.data.message,
                    type: 'success',
                })
            }
        }else{
    
    
            this.$message.error(response.data.message);
        }
    }).then(()=>{
    
    
        if (this.idIsNull == true){
    
    //如果学号为空
            this.idIsNull = false;//重新赋值,方便下次查询
        }else{
    
    
            // 发送axios请求查询该学生所在班级的各科平均分
            axios.post("stuAnalysis/avgByClassId",this.queryResult.stuClass,{
    
    
                headers:{
    
    
                    'Content-Type':'application/json'
                }
            }).then((response)=>{
    
    
                this.showOutPutBtn = !response.data.flag;
                this.queryResult.avgMath = response.data.data.avgMath + "";
                this.queryResult.avgJava = response.data.data.avgJava + "";
                this.queryResult.avgPE = response.data.data.avgPe + "";
                this.queryResult.avgEnglish = response.data.data.avgEnglish + "";
                this.queryResult.avgGradeNum = response.data.data.avgNumber + "";
            }).finally(()=>{
    
    
                this.initCharts();//初始化柱状图表
                this.initPieCharts();//初始化饼状图表
            })
        }
    })
},

なお、フロントエンドコードでは Javascirpt のアイコンライブラリである Echarts を使用していますが、この技術については本レポートで簡単に紹介するだけであり、Echarts の基本的な使い方も含まれるため、詳細は省略します。フロントエンドは、生徒の各科目の成績と生徒のクラスの平均成績を取得した後、双方向バインドされたデータを割り当て、最後にヒストグラムの初期化を実行します。ヒストグラムの指定されたボックス div を取得して myChart data を初期化した後、縦棒グラフの構成項目とデータを指定し、指定した構成項目とデータを使用してグラフに表示します。

フロントエンドで棒グラフを初期化するための initCharts() メソッドのコード:

initCharts(){
    
    
    this.myChart = echarts.init(document.getElementById('chartBox'));

    // 指定柱状图表的配置项和数据
    let option = {
    
    
        title: {
    
    
            text: this.queryResult.stuClass + '班的' + this.queryResult.stuName + '成绩分析柱状图',
        },
        tooltip: {
    
    },
        legend: {
    
    
            data: ['分数','班级平均分'],
        },
        xAxis: {
    
    
            data: ['数学', 'Java', '英语', '体育'],
        },
        yAxis: [
            {
    
    
                name: '分值',
                min: 0,
                max: 100,
            },
        ],
        series: [
            {
    
    
                name: '分数',
                type: 'bar',
                data: [
                    this.queryResult.gradeMath,
                    this.queryResult.gradeJava,
                    this.queryResult.gradeEnglish,
                    this.queryResult.gradePE,
                ],
                itemStyle: {
    
    
                    normal: {
    
    
                        color: '#4ad2ff',
                    }
                }
            },
            {
    
    
                name: '班级平均分',
                type: 'line',
                data: [
                    this.queryResult.avgMath,
                    this.queryResult.avgJava,
                    this.queryResult.avgEnglish,
                    this.queryResult.avgPE,
                ],
                itemStyle: {
    
    
                    normal: {
    
    
                        color: '#ffa500',
                    }
                }
            }
        ]
    };
    // 使用刚指定的配置项和数据显示图表
    this.myChart.setOption(option);
},

4.2.12 フロントエンドインターフェースの美化とインターセプターによるログイン・登録機能の実現

初期段階では、著者は主にフロントエンドとバックエンドのビジネス ロジックの実現に重点を置き、ページ要素を過度に美化せず、必要なコンポーネントのみを追加しました。その後、作者はページの美化に関するアップデートを行い、インターセプターを介したログインと登録機能を実装しました。フロントエンド ページを美化するために、作者は主にロゴ アーティファクト Web サイトを使用してプロジェクト ロゴを生成し、カラースペース Web ページを使用してより美しいグラデーション カラーを生成し、コンポーネントを追加して右上にユーザー名のアバターを作成します。 Web ページの隅にあるをクリックすると、ドロップダウン メニューがポップアップ表示されます。ログインと登録の美しいフロントエンド コードを見つけてインポートして変更し、好みのテーマに置き換えます。ここから、ログインと登録のフロントエンド ページ、Web ページ全体の色調、および美しいインターフェイスはすべて事前に完成しています。

login.html ファイルで、ログイン ボタンをクリックしてログイン メソッドを実行し、axios リクエストを送信します。渡されるパラメータは、ユーザーが入力したユーザー名です。バックエンド サービス インターフェイスの実装クラス メソッドでは、selectByPrimaryKey()メソッドは、データベース内のキーを見つけるために、loginUserMapper を通じて呼び出されます。ユーザー名に対応するパスワードが空の場合、ユーザー名またはパスワードが存在しないことを意味します。見つかったパスワードがユーザーが入力したパスワードと一致しない場合、これは、ユーザーが間違ったパスワードを入力したことを意味します。それ以外の場合は、システムにログインするための正しいパスワードです。.open('http://localhost:81/main.html','_self'); ステートメントは、メイン ファイルを開きます。現在のウィンドウの .html ページ。

フロントエンドのログインボタンをクリックして実行されるログインメソッドコード:

login(){
    
    
   let param = {
    
    
      username: this.user.userName,
      password: this.user.passWord,
   }
   axios.post("/login/checkPwd" , param).then((response)=>{
    
    
      if (response.data.flag){
    
    //登录成功
         this.$message({
    
    
            message: response.data.message,
            type: 'success'
         });
         location.reload();//刷新当前页面
      }else {
    
    //账号或密码错误
         this.$message.error( response.data.message );
      }
   })
},

これまでは、ログイン成功後の単純なページジャンプのみを実現していましたが、実際には、ログインおよび登録ページを直接スキップすることもできます。システムにログインしていない場合は、main.html URL を直接入力してシス​​テムにアクセスし、そのため、現時点でのログインおよび登録機能は完全に失われますが、その意味は、ログインおよび登録機能をさらに改善するためにインターセプターを使用する必要があります。

インターセプタ機能:ユーザーがシステムにログインせず、ログイン登録ページをスキップしてシステムに直接アクセスしたい場合、ユーザーがmain.htmlの特定のURLを入力しても、main.htmlのリソースにはアクセスできません。をクリックしてログイン登録ページにアクセスすると、システムが自動的にジャンプします。インターセプタ パッケージを作成し、パッケージ内に新しい LoginInterceptor.java ファイルを作成します。このインターセプタ エンティティ クラスは、HandlerInterceptor インターフェイスを実装し、インターフェイス メソッド preHandle() を実装する必要があります。このメソッドは、インターセプトする必要があるページがアクセスされる前に実行されます。 、メソッド本体内のリクエストを通じてセッションを取得します。ドメイン、セッションドメインの「user」に相当する値が空の場合、ユーザーはログインしていないことを意味します。このとき、ログインを除くすべてのページが登録ページと一部の静的リソースがインターセプトされ、セッション ドメインで取得された「ユーザー」が「対応する値が空ではなく、ユーザーがすでにログインしていることを示し、ユーザーのログインのセッション値がシステムに保存されている場合、この時点ではページはインターセプトされません。このとき、ログインコントローラ層のメソッドでログイン成功と判断した後、setAttribute()メソッドでセッションドメインにログインしたことを示すキーと値のペアの形でユーザーを格納します。

バックエンドインターセプターメソッドコード:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
    HttpSession session = request.getSession();
    if (session.getAttribute("user") != null){
    
    
        //用户已登录不拦截
        return true;
    }else {
    
    
//            拦截后进入登录页面
        response.sendRedirect(request.getContextPath() + "/login.html");
        return false;
    }
}

さらに、dispatcherServlet-servlet.xml (springmvc 設定ファイル) でインターセプターを設定し、インターセプトする必要があるファイルとインターセプトする必要のないファイルを指定し、インターセプターのエンティティ クラス マッピングを実行する必要があります。設定ファイルで設定すると、インターセプターが実際に動作できるようになります。

dispatcherServlet-servlet.xml ファイル内のインターセプターの構成:

<mvc:interceptors>
    <mvc:interceptor>
<!--            拦截所有mvc控制器-->
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/login.html"/>
        <mvc:exclude-mapping path="/static/**"/>
        <mvc:exclude-mapping path="/plugins/**"/>
        <mvc:exclude-mapping path="/login/**"/>
        <bean class="com.shenshang.manager.interceptor.LoginInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

4.2.13 クラス内の生徒の成績を分析する円グラフ機能を実現

筆者は、クラス内の生徒の個人成績と各科目の平均成績を含む単一のヒストグラムでは、クラス内の生徒全体の成績の傾きを示すことはできないと考えています。生徒のクラスを表示およびクエリする機能を拡張および実現するために、Echarts の使用にさらに習熟します。 生徒の学習状況の円グラフ、円グラフの機能: 生徒の平均合計スコア。このクラスは各段階の得点基準に応じて優、優、中、合格、不合格の5段階に分けられ、各学年の成績の生徒数の分布がトップページに形で表示されます。円グラフの。フロントエンドのビジネス ロジックは、ヒストグラムを生成するビジネス ロジックに似ています。ここでは詳細については説明しません。フロントエンド コードには、バックグラウンド データを取得するための axios リクエストの送信、値の割り当て、およびページに表示する円グラフを初期化する フロントエンドで注意する必要があるのは、クエリボタンをクリックしたときに、円グラフとヒストグラムを分析するメソッドが最初に実行されることです。同時に、フロントエンドのクエリ ボタンで 2 つの同時実行メソッド間を @click="gradeAnalogy(),classAnalysis()" としてカンマで結合します。classAnalysis() メソッドで axios リクエストを送信するときに渡されるパラメーターは、入力された学生 ID です。バックエンドのサービスインターフェイス実装クラスメソッドでフロントエンドの生徒の生徒番号を取得した後、まず生徒番号に対応する個々の生徒情報を照会し、生徒が所属しているクラスを取得し、成績を持つすべての生徒を照会します。このクラスは、クラス番号リストを通じて各レベルのカウンターを定義して初期化した後、生徒のリストを横断し、各生徒の合計成績の平均点を計算し、合計の平均点に従って生徒がどの学年範囲にあるかを判断します。最後に、取得したカウンターの値がコンストラクターを通じてインスタンス化され、フロントエンドに返されます。フロントエンドがデータを取得すると、それは双方向バインドされたデータに割り当てられ、円グラフの形式で表示されます。

バックエンド サービス インターフェイス実装クラスのメソッド コード:

public GradeRank rankById(String id) {
    
    
    Integer excellent = 0, good = 0, middle = 0, passed = 0, unPass = 0;
    int sid = Integer.parseInt(id);
    Student student = studentMapper.selectByPrimaryKey(sid);
    if (student == null) return null;
    Integer classid = student.getClassid();
    StudentExample studentExample = new StudentExample();
    StudentExample.Criteria criteria = studentExample.createCriteria();
    criteria.andClassidEqualTo(classid);
    List<Student> students = studentMapper.selectByExampleWithGrade(studentExample);
    for (Student stu : students) {
    
    
        if (stu.getFlag() == null) continue;
        float avgGradeNum = (float)stu.getGrade().getGradenum() / 4;//学生总分平均分
        if (avgGradeNum >= 60 && avgGradeNum < 70) passed++;//及格人数自增1
        else if(avgGradeNum >= 70 && avgGradeNum < 80) middle++;//中等人数自增1
        else if(avgGradeNum >=80 && avgGradeNum < 90) good++;//良好人数自增1
        else if(avgGradeNum >= 90 && avgGradeNum <= 100) excellent++;//优秀人数自增1
        else unPass++;//不及格人数自增1
    }
    return new GradeRank(excellent , good , middle , passed , unPass);
}

4.2.14 システム終了機能の実現

ユーザーがクリックしてシステムを終了すると、Web サイトのセッション ドメインのデータが削除され、現在のページが更新されます。インターセプターは現在のセッション ドメインにユーザーのログイン データがないことを検出するため、更新後、ページでは、main.html ページをインターセプトし、ログインを入力します。登録ページでは、システム リソースにアクセスする前に、ユーザーはログインして登録する必要があります。ユーザーがシステム終了ボタンをクリックすると、フロントエンドは handleComment() メソッドを実行します。このメソッドは、elementui のドロップダウン ボックス ラベルの組み込みメソッドです。このメソッドをクリックすると、クリックされたラベルのコマンド値が表示されます。を取得し、取得した時点でメソッド本体を判定し、コマンドの値が「b」と等しい場合(システム終了に相当するコマンドの値は「b」)、axiosリクエストを送信し、セッションを使用する既存システムのコントローラー層で .removeAttribute() ステートメントを使用して、セッション ドメインに保存されているユーザー ログイン情報をクリアします。正常にクリアされた後、フロントエンド メソッドの本体は window.open('http://localhost:81/login.html'); ステートメントを使用してログイン ページにジャンプし、テストして URL を入力できます。 main.html にアクセスし、アクセス システムが内部リソースであることが判明した場合でも、自動的に login.html にジャンプし、インターセプタが有効になります。

システムのコントローラー層メソッド本体コードを終了します。

@RequestMapping("/exitSystem")
public Result exitSystem(@RequestBody Integer id , HttpSession session){
    
    
    try{
    
    
        session.removeAttribute("user");
        return new Result( true , MessageConstant.EXIT_SYSTEM_SUCCESS );
    }catch (Exception e){
    
    
        e.printStackTrace();
        return new Result( false , MessageConstant.EXIT_SYSTEM_FAIL );
    }
}

4.2.15 成績付き生徒情報のExcelファイルへのエクスポートを実現

まず、EasyExcel の関連依存関係を pom.xml ファイルにインポートする必要があります。レポートのエクスポート ボタンをクリックした後、フロント エンドは axios リクエストを送信し、受信パラメータはクエリ結果のセットです。コントローラー層が受信するパラメータは、受信データ型と同じオブジェクト属性を持つエンティティ クラス OutPutExcel です。エンティティ クラスの各属性の前に @ExcelProperty 属性を追加します。この属性の値は生成された Excel テーブルのヘッダー名に対応し、アノテーションのインデックス値は出現順序の指定に使用されます。ヘッダー名の中で、小さいインデックスが最初に、大きいインデックスが後に続きます。コントローラー層では、stuAnalysisService を通じてインターフェイス エンティティ クラスのメソッドを呼び出し、Service インターフェイス エンティティ クラスのメソッドに Excel ファイルをエクスポートするパスを指定し、受け取ったパラメーター outPutExcel を配列に格納して、その配列を Excel ファイルに書き込みます。

バックエンド Service インターフェイスのクラス メソッドを実装するコードは次のとおりです。

public void pushExcel(OutPutExcel outPutExcel) {
    
    
//        指定导出excel文件的路径
    String fileName = filename;//此处的filename要换成指定的文件路径
//        存放对象的数组
    List<OutPutExcel> gradeCharts = new ArrayList<OutPutExcel>();
    gradeCharts.add(outPutExcel);
//        将数组写入到excel表格中去
    EasyExcel.write(fileName , OutPutExcel.class).sheet("个人成绩报表").doWrite(gradeCharts);
}

ここのフロントエンド コードで注意する必要があるのは、レポートをエクスポートするボタンは、結果がクエリされた後でのみクリック可能な状態に設定されるということです。情報がクエリされない場合、レポートをエクスポートするボタンはクリック可能状態に設定されません。クリック可能であること。

5. 実験結果と解析

最終的にプロジェクトは具体化しました。生徒の成績管理システムにはバグは見つかりませんでした。プロジェクトはタスクガイドの基本的な機能をすべて実現しました。さらに、著者はこのプロジェクトの追加点として多くの機能を拡張しました。しかし、このプロジェクトには欠点もあるので、ここで一緒に分析します。

プロジェクト機能の革新と拡張ポイント:

①学生情報を追加するモーダルボックスフォームは、ラジオボックス、複数選択ボックス、日付セレクターなどの各種入力ボックスを使用しており、入力可能な入力ボックスのみを使用するフォームに比べて、ユーザーの入力をより制約することができます。たとえば、日付ピッカー (Elementui の組み込み日付ピッカー タイプの入力ボックス) を使用すると、カレンダーで選択できる時刻が変更され、作成者がフロントエンドでそれを処理するため、日付が日付よりも大きくなります。当日は選択できません。システムの日付が変わると日付ピッカーも変わり、複雑で煩雑なバックグラウンド検証コードが軽減されます。

②学生情報照会ページのテーブルには、管理者が学生の成績を入力・閲覧できる操作欄があり、また、学生の成績の入力の有無に応じて入力・閲覧ボタンがクリック可能・非クリックに設定されているため、管理者が生徒の情報を繰り返し入力することを回避するため、また、生徒の成績を表示するときに管理者が空白のプロンプト ボックスを表示することを防ぎます。ここに設置される入力ボタンは、従来の名前入力や成績入力とは異なり、主に管理者が成績未記入の学生を確認するためのものであり、成績入力後は学生情報ページで直接学生の成績を確認することができます。 .エラーです。これまでのところ、学生の成績照会ページは冗長に見えますが(学生の成績はすでに学生情報照会ページで取得できるため)、成績照会ページでは複数の学生の成績をまとめて表示でき、クラスに入った後はそのまま表示されます。クラス内の複数の生徒の成績を表示し、異なる生徒の成績を直感的に比較できるほか、生徒の成績照会ページには生徒の成績を修正する機能もあります。成績が間違っている生徒については、このページを使用して、学生の成績を直接変更できます。学生の成績クエリ ページは冗長ではありませんが、2 つのページは相互に影響し、関連していることがわかります。

③ 学生情報照会ページと学力照会ページの編集ボタンをクリックすると、同様のモーダルボックスがポップアップ表示されます。このモーダルボックスにはデータがエコーされています。データのエコーがなければ、結果は何も表示されません。元情報の参照データは修正ミスが発生しやすいです。

④生徒情報照会ページ、生徒成績照会ページともにクラス番号を検索条件としており、クラス番号を入力することで指定したクラスの全生徒情報および全生徒成績を照会することを目的としています。この点はタスクガイドでは必須ではありませんが、これによりユーザーがクエリ範囲をプロフェッショナル範囲からクラス範囲に絞り込むオプションを提供できると考え、この機能を拡張しました。

⑤生徒の成績分析ページでレポートのエクスポートボタンを加工しましたが、バックグラウンドで返却データがある前提でのみレポートのエクスポートボタンがクリック可能となり、生徒が学籍番号を入力しても照会できなくなることを防いでいます。エクスポート ボタンをクリックしても応答がなく、クリック時にエラーが報告され、生成された Excel テーブルのヘッダー列の値が空になります。

⑥生徒の成績分析ページでは、バックエンドが生徒番号と成績を指定して生徒情報をクエリした後、フロントエンドが生徒のクラス番号を取得し、そのクラス番号を2番目のaxiosリクエストのパラメータとして渡します。再びバックグラウンドで使用されます クラス内の各科目の平均成績を計算してフロントエンドに送信し、折れ線グラフの形式で表示します。折れ線グラフと縦棒グラフが1つのグラフに表示され、便利です管理者が生徒とクラスの各科目の平均点を比較すると、生徒がクラスの平均点を下げた科目を簡単に見つけることができます。

⑦生徒の成績分析ページでは、生徒番号を入力してクエリボタンをクリックすると、生徒の成績のヒストグラム分析方法と授業成績の円グラフ分析方法が同時に実行されます。円グラフは、クラス内の生徒の全体的なレベルを反映することが難しく、クラス内の生徒の傾きを判断することが不可能である(つまり、クラス内の生徒が多いかどうかを知ることができない)と考えられます。学習が得意な生徒が少ない、学習が中程度の生徒が多い、失敗している生徒が何人いるかなど) 円グラフの機能は、クラス内の生徒の勾配状況をよく反映し、フィードすることができます。クラス全体の学習雰囲気について管理者に返信します。

⑧ログインと登録機能を実装しました。この機能はタスク ガイドでは必須ではありません。著者は、優れたシステムにはログインと登録機能が必要であると考えています。ログインしていないユーザーが URL を入力してシス​​テム リソースにアクセスできる場合、システムは最低限の機密性とセキュリティを失います。ログインと登録は、システム セキュリティの防御の最前線です。

⑨タスクガイドでは必須ではないシステム終了機能を実現しましたが、システム終了機能を実装することで、ユーザーの再ログインやログインアカウントの切り替えが容易になります。実現すると、次回インターセプタが有効になります。唯一のオプションはブラウザのキャッシュをクリアするかサーバーを再起動することですが、これはユーザー エクスペリエンスにとって良くなく、ユーザー アカウントの機密性も保証できません。

プロジェクト機能の欠点:

① 生徒の成績分析ページで、生徒の成績分析ヒストグラムとクラス成績の円グラフをクエリした後、この時点でレポートのエクスポート ボタンをクリックできます。ボタンをクリックすると、「生徒の成績レポートが正常にエクスポートされました」というプロンプト メッセージが表示されます。指定された Excel ファイルの保存パスはプロジェクト内ですでに指定されています。これはユーザー エクスペリエンスにとってあまり良いことではありません。ファイルを保存するパスをユーザーが指定できるようにした方がよいでしょう。

② ログイン登録ページで登録ボタンをクリックすると、ユーザー名と新しいパスワードを入力するだけで登録が完了し、検証ルールを満たすユーザー名とパスワードがデータベーステーブルに挿入されます。新しいパスワードを再入力するための入力ボックスが表示されないため、ユーザーがアカウントを登録する際に間違ったパスワードを押してしまい、ログイン時にログインできなくなるという問題が発生します。実際、バックグラウンド検証が完了し、フロントエンド プロンプト情報が提供されている限り、パスワードを再入力するロジックは非常に簡単です。

③システムにはパスワードを変更する機能が実装されていません。この機能はプロジェクトの編集ボタンのロジックと非常によく似ていると作者は考えています。改めて書く必要はないと思うので、パスワードを変更する機能はユーザーが登録したメールアドレスまたは携帯電話番号を入力し、アカウント登録やパスワード変更を行うと、ユーザーのメールボックスに送信されるか、テキストメッセージが送信されるため、より安全です。

④ データベーステーブルを構築する際、ログインテーブル s_login にはユーザー名やパスワードなどの単純な情報しか含まれておらず、これが少なすぎるため、エコーできるユーザーに関するデータが少なすぎるため、パーソナルセンターがデータベーステーブルを構築することができません。 (アカウント番号とパスワードのみ) アカウント番号とパスワードをエコーする必要はありません。実際、テーブルを作成するときに、管理者が入力を選択できる情報 (アバター、性別、年齢、パーソナルセンターを統合できるようにする機能を作成した後、アバターなどを修正することもできます。

⑤著者はフロントエンドページをできる限り美しくしようと努めていますが、フロントエンドページはまだあまり美しくないように感じます。さらに、導入される可能性のある elementui のバージョンが低すぎるため、現在のバージョンの elementui コンポーネント ライブラリの一部のアイコンが使用できなくなります。

以上が、本コースデザインのプロジェクト全体をレビューした上での筆者の自己評価であり、多くの工夫や不備はあるものの、タスクガイドにある基本的な機能はすべて実現されている。その後、アイデアがあれば、さらなる拡張機能や革新点に気づき、欠点を改善していきます。

6. まとめと経験

このコース設計では、vue+ssm テクノロジーを使用して、シンプルなフロントエンドとバックエンドの分離プロジェクトと学生のパフォーマンス管理システムを実現しました。このシステムは比較的伝統的な昔ながらのプロジェクトではありますが、このプロジェクトの実現は非常に意義があり、また、データベースのデータの追加、削除、変更、クエリについての思考力を訓練することができ、また、データベースのデータを統合することもできます。 SSM フレームワークの知識を習得し、フロントエンドとバックエンドの分離の利点をよく理解します。また、JavaScript、jsp、jquery、サーブレットなどを直接記述するよりも、フロントエンドやバックエンドのフレームワークの方がはるかに便利であることを生徒に認識させ、フレームワークを使用する便利さを実感させることができます。

コース設計の過程で、タスクガイドでは必須ではなかった拡張機能を作者が実現したことが分かりますが、ユーザーの視点で更新システムを改善する方法を考えてください。そして、このシステムにはいくつかの不完全性もありますが、これはプロジェクトではよくあることであり、プロジェクトは常に洗練されています。コース設計の終了はプロジェクトの終了を意味するものではなく、今後もアイデアがあればシステムは常に更新されます。

さらに、以前は、著者はデモを通じてオンライン クラス ビデオを視聴することで新しい知識ポイントの学習を定着させることに熱心でしたが、多くの場合、結果は最小限であることがわかりました。教師に従ってプロジェクトを段階的に実行する過程で、その時点では特定の知識ポイントについて明確にしていましたが、プロジェクトの完了から 2 週間後には、再びプロジェクトに非常に慣れていないように感じることがあります。これは、プロジェクトで使用された知識ポイントを習得していないことを示しています。そして、このコース設計は完全に私自身で行われています。一行ずつ入力したコードだけが、知識ポイントを長く頭の中に留めることができることに気づきました。すぐに忘れてください。コードを書いて開始するのに長い時間がかかるかもしれません一人でプロジェクトを進めていますが、このプロセスは問題を発見し修正するプロセスであり、急速に進歩するプロセスでもあります。プロジェクトの実際的な問題を解決する際、デモを完成させるために全力を尽くしましたが、本当に理解できませんでした。分からない場合はソースコードを確認して学ぶことができ、それでも理解できない場合はオンラインコースを利用して理解することができます。

このコース設計では、著者は確かに vue および ssm フレームワークの使用に習熟しており、フレームワーク実装の基礎となるロジックを少し理解していますが、まだ十分に深くはありません。フレームワークは詳細である必要があり、ssm フレームワークはテンプレート フレームワークを学習した後、就職後に独自の技術フレームワークを持つ可能性があります。ssm フレームワークの基礎となるロジックに習熟していることを前提として、会社のフレームワークの学習に移行しやすくなります。

以上が、このコース設計の概要と経験です。書いていて感じたのですが、ロジスティクス思考をもっと練習し、実践力にもっと注意を払う必要があります。心に留めておいてください: 紙の上で行われていることは常に表面的なものであり、それがわかっている場合は自分で行う必要があります。

Supongo que te gusta

Origin blog.csdn.net/qq_54162207/article/details/125219175
Recomendado
Clasificación