SpringBoot + Vue フロントエンド・バックエンド分離プロジェクト実戦 || 5: ユーザー管理機能のフォローアップ

一連の記事:
SpringBoot + Vue フロントエンドとバックエンドの分離プロジェクトの実践 || 1 つ: Vue フロントエンド設計
SpringBoot + Vue フロントエンドとフロントエンドの分離プロジェクトの実践 || 2 つ: Spring Boot バックエンドとデータベース接続
SpringBoot + Vue フロントエンドとフロントエンド分離プロジェクトの実践 || 3: Spring Boot バックエンドと Vue フロントエンド接続
SpringBoot + Vue フロントエンドとバックエンド分離プロジェクトの実践 || 4: ユーザー管理機能実装
SpringBoot + Vue フロントエンド分離プロジェクト実践 || 5: ユーザー管理機能フォローアップ

レビューと展望

前回はユーザー管理インターフェースのデータ表示について紹介しましたが、次にユーザーの追加、変更、削除を行う必要があります。
ここに画像の説明を挿入します
ここに画像の説明を挿入します

新しいユーザー機能の実装

フロントエンドの実装

user.vueポップアップ ダイアログ ボックスのコードを記述するとき、コードは Element-UI コンポーネントからも取得されます。
ここに画像の説明を挿入します

<!-- 用户信息编辑对话框 -->
<!-- :title 加了冒号就变成一个变量,属性绑定了,后面的东西需要在data中说明 -->
<el-dialog @close="clearForm" :title="title" :visible.sync="dialogFormVisible">
  <el-form :model="userForm" ref="userFormRef" :rules="rules">
    <el-form-item label="用户名" prop="username" :label-width="formLabelWidth">
      <el-input v-model="userForm.username" autocomplete="off"></el-input>
    </el-form-item>

    <el-form-item v-if="userForm.id == null || userForm.id == undefined"
      label="登录密码" prop="password" :label-width="formLabelWidth">
      <el-input type="password" v-model="userForm.password" autocomplete="off"></el-input>
    </el-form-item>

    <el-form-item label="联系电话" prop="phone" :label-width="formLabelWidth">
      <el-input v-model="userForm.phone" autocomplete="off"></el-input>
    </el-form-item>

    <el-form-item label="用户状态" :label-width="formLabelWidth">
      <el-switch v-model="userForm.status" 
        :active-value="1"
        :inactive-value="0"
        active-color="#13ce66" 
        inactive-color="#ff4949">
      </el-switch>
    </el-form-item>

    <el-form-item label="电子邮件" prop="email" :label-width="formLabelWidth">
      <el-input v-model="userForm.email" autocomplete="off"></el-input>
    </el-form-item>
  </el-form>

  <div slot="footer" class="dialog-footer">
    <el-button @click="dialogFormVisible = false">取 消</el-button>
    <el-button type="primary" @click="saveUser">确 定</el-button>
  </div>
</el-dialog>

このダイアログ ボックスには 3 つの重要なプロパティがあります。
ここに画像の説明を挿入します

  • 赤: ダイアログ ボックスを閉じる操作。ダイアログ ボックスを閉じた後、フォームをクリアし、フォームの入力規則をクリアする必要があります。コードのこの部分は次のように記述されていますmethods
    ここに画像の説明を挿入します
  • オレンジ: ポップアップ ダイアログ ボックスのタイトルです。ここでは、新規ダイアログ ボックスと編集ダイアログ ボックスが同じになるように設定します。操作が異なると、異なる名前が表示されます。変数な
    ここに画像の説明を挿入します
    ここに画像の説明を挿入します
    ので:title、登録されること。
    ここに画像の説明を挿入します
  • 白: ポップアップウィンドウを表示するかどうかを変更します。実際にはポップアップウィンドウは常に存在します。ボタンをクリックした後にのみ表示され、閉じると非表示になります。また、変数として登録する必要があるため、まず非表示にしてください。
    ここに画像の説明を挿入します

フォームの 3 つのプロパティ
ここに画像の説明を挿入します

  • 赤: フォーム データの第 1 レベルの変数名。 内のデータにアクセスする場合userForm.username、これは input 内のフィールドですv-model。このフィールドはバックエンド エンティティ クラス名と一致している必要があります。同時に、アイテム内のフィールドpropもバックエンドと一致します。

  • オレンジ:前のセクションで使用したref、フォーム検証に使用される変数名clearForm

  • Bai: フォーム検証ルールを定義します。次のコードはElement-UI公式 Web サイトにあります。コードはメソッドではなくエリアdataに記述されています。return
    ここに画像の説明を挿入します

    rules:{
          
             // 表单校验
         username: [
           {
          
           required: true, message: '请输入用户名', trigger: 'blur' },
           {
          
           min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
         ],
         password: [
           {
          
           required: true, message: '请输入初始密码', trigger: 'blur' },
           {
          
           min: 6, max: 16, message: '长度在 6 到 16 个字符', trigger: 'blur' }
         ],
         email: [
           {
          
           required: true, message: '请输入电子邮件', trigger: 'blur' },
           {
          
           validator: checkEmail, trigger: 'blur' }
         ],
         phone: [
           {
          
           validator: checkPhone, trigger: 'blur' }
         ],
       },
    

    ここに画像の説明を挿入します

    ルール検証には 2 つのカスタム ルール検証があります: checkEmailcheckPhone、これら 2 つは正規表現です。Baidu で電子メールと電話の検証ルールを検索できます。ここで直接使用できます。これら 2 つの検証ルールは ではなく で書かれていることに注意してくださいdatadata\return
    ここに画像の説明を挿入します

     var checkEmail = (rule, value, callback) => {
          
          
       var reg = /^([a-zA-Z\d][\w-]{2,})@(\w{2,})\.([a-z]{2,})(\.[a-z]{2,})?$/
       if (!reg.test(value)) {
          
          
         return callback(new Error('邮箱格式错误'));
       }
       callback();   // 效验成功
     };
    
     var checkPhone = (rule, value, callback) => {
          
          
       var reg = /^[1]+\d{10}$/
       if (!reg.test(value)) {
          
          
         return callback(new Error('请输入正确的手机号码'));
       }
       callback();    // 效验成功
     };
    

下の写真の赤い部分がフォーム全体です
ここに画像の説明を挿入します

  • オレンジ: バックエンド データベース エンティティ クラスと一致する、フォーム受信フィールドの変数名です。
  • 白: ユーザー情報を変更する場合、パスワードを変更する機会を与えません。ただし、新規ユーザーを追加する場合は初期パスワードが設定されるため、判断が必要です。ユーザーを変更する場合、ユーザーには ID が必要です。ID がuserForm.id存在する場合は、ユーザーを変更していることを意味します。ユーザーの情報が表示され、変更されます。
    注: エンティティ クラスのすべての属性はバックエンドから渡され、userForm もすべての属性を受け取ります。名前、電子メールなどのみが表示されます。残りの属性は表示されず、引き続きアクセスできます。

送信ボタン
ここに画像の説明を挿入します

  • オレンジ:取消ボタンをクリックすると、ダイアログ ボックスの表示プロパティがfalse非表示に設定されます。
  • 白:保存ボタンをクリックするとトリガーされる機能: saveUser、この機能の操作プロセスはコメントで説明されています
    ここに画像の説明を挿入します
    saveUser(){
          
          
       // 触发表单验证
       this.$refs.userFormRef.validate((valid) => {
          
          
         if (valid) {
          
            // 验证通过
           // 数据传给后端
           userApi.saveUser(this.userForm).then(response=>{
          
          
             // 提交成功后的操作
    
             // 插入数据成功提示
             this.$message({
          
          
               message: response.message,
               type: 'success'
             });
    
             // 关闭对话框,清除表单数据
             this.dialogFormVisible = false;
             this.clearForm();
    
             // 刷新表格
             this.getUserList();
    
           });
         } else {
          
            // 验证失败
           console.log('error submit!!');
           return false;
         }
       });
     },
    

すべてのダイアログ フォームの vue コードは次のとおりです。

<!-- 用户信息编辑对话框 -->
<!-- :title 加了冒号就变成一个变量,属性绑定了,后面的东西需要在data中说明 -->
<el-dialog @close="clearForm" :title="title" :visible.sync="dialogFormVisible">
  <el-form :model="userForm" ref="userFormRef" :rules="rules">
    <el-form-item label="用户名" prop="username" :label-width="formLabelWidth">
      <el-input v-model="userForm.username" autocomplete="off"></el-input>
    </el-form-item>

    <el-form-item v-if="userForm.id == null || userForm.id == undefined"
      label="登录密码" prop="password" :label-width="formLabelWidth">
      <el-input type="password" v-model="userForm.password" autocomplete="off"></el-input>
    </el-form-item>

    <el-form-item label="联系电话" prop="phone" :label-width="formLabelWidth">
      <el-input v-model="userForm.phone" autocomplete="off"></el-input>
    </el-form-item>

    <el-form-item label="用户状态" :label-width="formLabelWidth">
      <el-switch v-model="userForm.status" 
        :active-value="1"
        :inactive-value="0"
        active-color="#13ce66" 
        inactive-color="#ff4949">
      </el-switch>
    </el-form-item>

    <el-form-item label="电子邮件" prop="email" :label-width="formLabelWidth">
      <el-input v-model="userForm.email" autocomplete="off"></el-input>
    </el-form-item>
  </el-form>

  <div slot="footer" class="dialog-footer">
    <el-button @click="dialogFormVisible = false">取 消</el-button>
    <el-button type="primary" @click="saveUser">确 定</el-button>
  </div>
</el-dialog>

フロントエンドインターフェースの実装

フロントエンド インターフェイスのファイルは path にありますsrc\api\userManage.js。追加、削除、変更、確認に対応するメソッドはpost/ delete/ put/であることに注意してください。get

import request from '@/utils/request'


export default{
    
    
  getUserList(searchModel){
    
    
    return request({
    
    
      url:'/user/list',
      method:'get',
      params:{
    
        // 传给后端的参数,对应后端的 @RequestParam
        pageNo: searchModel.pageNo,
        pageSize: searchModel.pageSize,
        username: searchModel.username,
        phone: searchModel.phone,
      }

    });
  },

  addUser(user){
    
    
    return request({
    
    
      url:'/user',
      method:'post',
      data:user   // 传回后端的实体数据
    });
  },

  saveUser(user){
    
    
    if(user.id == null || user.id == undefined){
    
    
      return this.addUser(user);
    }else{
    
    
      return this.updateUser(user);
    }
  },

  updateUser(user){
    
    
    return request({
    
    
      url:'/user',
      method:'put',
      data:user
    });
  },

  getUserById(id){
    
    
    return request({
    
    
      // url:'/user/' + id,   // 写法一
      url:`/user/${
      
      id}`,    // 写法二 ,对应后端的 @PathVariable
      method:'get'
    });
  },

  deleteUserById(id){
    
    
    return request({
    
    
      url:`/user/${
      
      id}`,    // 对应后端的 @PathVariable
      method:'delete'
    });
  },


}

バックエンドの実装

バックエンドコードはUserController.java次のとおりです

新しい利用者

ここに画像の説明を挿入します

	 // 前端addUser方法的url就是"/user" 故此处无url
    @PostMapping
    public Result<?> addUser(@RequestBody User user){
    
    
        // @RequestBody 用于json转为实体对象

        // 做了加盐处理
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userService.save(user);
        return Result.success("新增用户成功");
    }

対応するフロントエンドは次のとおりです。
ここに画像の説明を挿入します

暗号化操作:
新しいユーザーにはパスワード暗号化機能があり、ユーザーのパスワードがデータベースに書き込まれるとき、以下に示すように暗号化され、ソルトが適用されます。パスワードの平文は次のとおりです。123456
ここに画像の説明を挿入します

(ソルティング: 同じパスワードの組み合わせでも、暗号文も異なります)

依存関係を以下に追加しますpom.xml

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
</dependency>

スタートアップクラスに登録するBean
ここに画像の説明を挿入します

@Bean
public PasswordEncoder passwordEncoder(){
    
    
    // 密码加密的工具类,来自依赖spring-security-core
    return new BCryptPasswordEncoder();
}

UserController変数を登録します
ここに画像の説明を挿入します

ログイン
ロジックを変更します。パスワードが暗号化されると、ログイン時にデータベース パスワードと単純に照合することはできません。復号化照合プロセスが必要です。バック
エンド ファイルを変更します。service\impl\UserServiceImpl

@Override
public Map<String, Object> login(User user) {
    
    
    // 根据用户名查询
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(User::getUsername, user.getUsername());
    User loginUser = this.baseMapper.selectOne(wrapper);

    // 结果不为空,并且密码与数据库解密后的密码匹配,生成token,将用户信息存入redis
    if (loginUser != null &&
            passwordEncoder.matches(user.getPassword(), loginUser.getPassword())    // 匹配加密密码
    ) {
    
    
        // 用UUID,终极方案是jwt
        String key = "user:" + UUID.randomUUID();

        // 存入redis
        loginUser.setPassword(null);    // 设置密码为空,密码没必要放入
        redisTemplate.opsForValue().set(key, loginUser,10, TimeUnit.MINUTES);   // timeout为登录时间

        // 返回数据
        Map<String, Object> data = new HashMap<>();
        data.put("token",key);
        return data;
    }

    // 结果不为空,生成token,前后端分离,前端无法使用session,可以使用token
    // 并将用户信息存入redis
    return null;
}

この時点で、新しいユーザー関数が完了します。


ユーザーの変更

ここに画像の説明を挿入します

	@PutMapping
    public Result<?> updateUser(@RequestBody User user){
    
    
        // @RequestBody 用于json转为实体对象

        user.setPassword(null);
        userService.updateById(user);
        return Result.success("修改用户成功");
    }

対応するフロントエンドは次のとおりです。
ここに画像の説明を挿入します

ユーザーを削除する

ここに画像の説明を挿入します

	@DeleteMapping("/{id}")
    public Result<?> deleteUserById(@PathVariable("id") Integer id){
    
    
        userService.removeById(id);
        return Result.success("删除用户成功");
    }

フロントエンドは次のとおりです。
ここに画像の説明を挿入します

企業のプロジェクト管理では、実際にデータベース内のレコードを削除するのではなく、データテーブル内のフィールドをマークとして設定する論理削除が一般的に使用されますdeleted0は削除されていないことを意味し、1は削除されたことを意味します
ここに画像の説明を挿入します

resources\application.ymlに設定を追加

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除的实体字段名,与数据库的字段名一致
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

このようにして、Spring はクエリ時に SQL ステートメントを自動的に結合します。WHERE deleted = 0
ここに画像の説明を挿入します

構成後、删除oioi用户前データベース
ここに画像の説明を挿入します
ここに画像の説明を挿入します
ここに画像の説明を挿入します
が削除されると、最後のフィールドは 1 になります。


IDに基づいてユーザーを検索し、変更フォームにデータを表示します

ここに画像の説明を挿入します

	@GetMapping("/{id}")
    public Result<User> getUserById(@PathVariable("id") Integer id){
    
    
        User user = userService.getById(id);
        return Result.success(user);
    }

対応するフロントエンドは次のとおりです。
ここに画像の説明を挿入します

お花を広げ終わりました!

おすすめ

転載: blog.csdn.net/qq_56039091/article/details/131429258