zoukankan      html  css  js  c++  java
  • 前后端项目接口联调

    1.联调准备

    1.1 运行后台项目

    • clean 清空项目的编译文件
    • compile 重新编译项目
    • 将项目部署到 tomcat
      • 项目名为: lagou_edu_home
      • 端口号: 8080
    • 部署图片上传路径为 webapps目录下的 upload目录

    1.2 运行前端项目

    1. 首先导入前端项目到 VSCode
    2. 运行项目.

    2.课程管理首页

    2.1 获取课程列表

    JS部分

    export default {
      name: "Courses",
      title: "课程管理",
      //定义数据部分
      data() {
        return {
          filter: { course_name: "", status: "" }, //查询对象
          courses: [], //课程信息集合
          loading: false //是否弹出加载
        };
      },
      //钩子函数
      created() {
        this.loadCourses();
      },
      methods: {
        //方法1: 获取课程列表
        loadCourses() {
          this.loading = true;
          //请求后台查询课程列表接口
          return axios
            .get("/course", {
              params: {
                methodName: "findCourseList"
              }
            })
            .then(resp => {
              console.log(resp);
              this.loading = false; //关闭加载
              this.courses = resp.data; //取出数据
            })
            .catch(error => {
              this.$message.error("数据获取失败! ! !");
            });
        },
      }
    };
    </script>
    

    2.2 条件查询课程信息

    JS部分

    //方法2: 条件查询课程信息
        filterQuery() {
          this.loading = true;
          //定义查询条件对象
          const search = {};
          //保存用户输入的条件
          if (this.filter.course_name) search.course_name = this.filter.course_name;
          if (this.filter.status) search.status = this.filter.status;
          //请求后台条件查询接口
          return axios
            .get("/course", {
              //准备参数
              params: {
                methodName: "findByCourseNameAndStatus",
                course_name: search.course_name,
                status: search.status
              }
            })
            .then(resp => {
              console.log(resp);
              this.loading = false;
              //将响应数据保存到 courses
              this.courses = resp.data;
            })
            .catch(error => {
              this.$message.error("数据获取失败! ! !");
            });
        },
    

    2.3 跳转到添加课程

    JS部分

    //方法3: 添加课程跳转方法 
        addCourse() {
          //路由跳转到 CourseItem.vue组件
          this.$router.push({ name: "CourseItem", params: { courseId: "new" } });
        },
    

    2.4 修改课程状态

    JS部分

    //方法4: 修改课程状态
        updateStatus(item) {
          //item 表示选中的数据 = Course对象
          axios
            .get("/course", {
              params: {
                methodName: "updateCourseStatus",
                id: item.id
              }
            })
            .then(res => {
              console.log(res);
              //将返回的状态字段,封装到对象中
              Object.assign(item, res.data);
              //重新加载页面
              window.location.reload;
            });
        },
    

    2.5 跳转课程营销或内容管理

    JS部分

    //方法5: 根据路由名称, 导航到对应组件  
        handleNavigate(name, id) {
          this.$router.push({ name, params: { courseId: id } });
        },
    

    3.新建&修改课程

    3.1 Course组件中的跳转方法

    <!-- 营销信息按钮 -->
    <el-button
         size="mini"
         @click="handleNavigate('CourseItem', scope.row.id)"
         >营销信息</el-button>
    
    //方法3: 添加课程跳转方法
        addCourse() {
          //路由跳转到 CourseItem.vue组件
          this.$router.push({ name: "CourseItem", params: { courseId: "new" } });
        },
    

    3.2 router.js 路由

    找到name为: CourseItem的路由

    //添加课程的路由
    {
        path: "/courses/:courseId", //路径,携带参数: 课程ID
        name: "CourseItem",
        //路由导航到的组件
        component: () =>
        import(/* webpackChunkName: 'courses' */ "../views/CourseItem.vue")
    },
    

    3.3 CourseItem组件

    3.3.1JS部分

    data() {
        //数据
        return {
          rules, //规则
          course: {}, //课程
          loading: false,
          params: {} //参数对象
        };
      },
      //钩子函数
      created() {
        //1.获取路由传递的参数
        const id = this.$route.params.courseId;
        //2.判断id是否有值,没有值跳转到 错误页面
        if (!id) return this.redirectToError();
        //3.判断 是new 还是具体的id 
        if (id === "new") {
          //new 代表新增,添加一个新增课程标题
          this.course.title = "新增课程";
        } else {
          //否则就是修改,调用loadCourse方法进行回显
          this.loadCourse(id);
        }
      },
    

    3.3.2 图片上传分析

    页面部分

    <!-- 上传图片部分 -->
    <el-form-item label="分享小图" prop="share_image_title">
        <el-input v-model="course.share_image_title" type="text">
            <!-- :auto-upload="false",取消自动上传, :on-change="onchange" 调用onchange
    进行处理 -->
            <el-upload
                       slot="prepend"
                       :auto-upload="false"
                       :on-change="onchange"
                       action
                       :limit="1"
                       >
                <el-button size="small" type="primary">点击上传</el-button>
            </el-upload>
        </el-input>
    </el-form-item>
    

    JS部分

    FormData的主要用途有两个

    1. 将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。
    2. 异步上传文件
    3. 创建FormData对象
    //通过FormData构造函数创建一个空对象
    var formdata=new FormData();
    //可以通过append()方法来追加数据
    formdata.append("name","laotie");
    //通过get方法对值进行读取
    console.log(formdata.get("name"));//laotie
    //通过set方法对值进行设置
    formdata.set("name","laoliu");
    console.log(formdata.get("name"));//laoliu
    data中创建FormData
        //5.创建FormData对象,将图片与表单一同上传
        this.params = new FormData();
    methods添加方法
        //文件上传 
        onchange(file) {
          //判断文件不为空
           if(file != null){
            // 将文件信息,保存到FormData对象中
            // 参数1:表示是文件上传项,参数2:文件上传的二进制数据,参数3:表示文件名
            this.params.append("file",file.raw,file.name);
          }
        },
    

    3.3.3 新建课程信息

    JS 部分

    //保存和修改课程信息
        handleSave() {
          //检查是否拿到了正确的需要验证的form
          this.$refs.form.validate(valid => {
            if (!valid) return false;
            //1.设置Content-Type为 多部件上传
            let config = {
              headers: {
                "Content-Type": "multipart/form-data"
              }
            };
            //2.获取表单中的数据,保存到params (params 就是 FromData对象)
            for (let key in this.course) {
              //debugger
              console.log(key + "---" + this.course[key]);
              this.params.append(key, this.course[key]);
            }
            //3.保存课程信息
            axios
              .post("/courseSalesInfo", this.params, config)
              .then(res => {
                //debugger
                if (res.data.status == 0) {
                  //保存成功,跳转到首页
                  this.$router.back();
                } else if (res.data.status == 1) {
                  this.$message({
                    type: "error",
                    message: res.data.msg
                  });
                }
              })
              .catch(err => {
                this.$message.error("保存失败! ! !");
              });
          });
          },
    

    3.3.4 修改课程信息

    //方法2: 根据ID 回显课程信
        loadCourse(id) {
          this.loading = true;
          axios
            .get("/course", {
              params: {
                methodName: "findCourseById",
                id: id
              }
            })
            .then(res => {
              this.loading = false;
              this.course = res.data;
            })
            .catch(() => {
              this.$message.error("回显数据失败! ! !");
            });
        },
    

    4.内容管理

    4.1 Course组件中的跳转方法

    <!-- 内容管理按钮 -->
    <el-button
          size="mini"
          @click="handleNavigate('CourseTasks', scope.row.id)">内容管理</el-button>
    
    //方法5: 根据路由名称, 导航到对应组件
    handleNavigate(name, id) {
        this.$router.push({ name, params: { courseId: id } });
    },
    

    4.2 router.js 路由

    //内容管理的路由
    {
        path: "/courses/:courseId/tasks",
        name: "CourseTasks",
        meta: { requireAuth: true },
        component: () =>
        import(/* webpackChunkName: 'courses' */ "../views/CourseTasks.vue")
    }
    

    4.3 CourseTasks组件

    4.3.1 树形控件测试

    1. 打开我们之前编写的VueCLI项目
    2. 在component目录下,添加一个组件, TestTree.vue
    <template>
    </template>
    <script>
    export default {
     
    }
    </script>
    <style scoped>
    </style>
    
    1. 在Index.vue组件中的导航菜单位置添加一个 树形控件导航.

    注意:要设置index的路径为 /tree

    <el-submenu index="1">
        <template slot="title">
            <i class="el-icon-location"></i>
            <span>导航菜单</span>
        </template>
        <el-menu-item-group>
            <!-- 修改 index的路由地址 -->
            <el-menu-item index="/course">
                <i class="el-icon-menu"></i>课程管理
            </el-menu-item>
            <el-menu-item index="/tree">
                <i class="el-icon-menu"></i>树形控件
            </el-menu-item>
        </el-menu-item-group>
    </el-submenu>
    
    1. 在index.js 路由文件中进行配置,在布局路由中再添加一个子路由
    //导入树形控件组件
    import TestTree from "@/components/TestTree";
    //布局路由
      {
        path: "/index",
        name: "index",
        component: Index,
        //添加子路由,使用 children属性 来表示子路由
        children: [
          //课程信息子路由
          {
            path: "/course",
            name: "course",
            component: Course,
            },
          //Tree控件测试路由
          {
            path: "/tree",
            name: "tree",
            component: TestTree,
          },
        ],
      },
    
    1. 在ElementUI官网中查找树形控件

    1. 先来查看基础用法,赋值代码到 TestTree.vue
    <template>
      <el-tree :data="data" :props="defaultProps" ></el-tree>
    </template>
    <script>
    export default {
      data() {
        return {
          data: [
            {
              label: "一级 1",
              children: [
                {
                  label: "二级 1-1",
                  children: [
                    {
                      label: "三级 1-1-1"
                    }
                  ]
                }
              ]
            },
            {
              label: "一级 2",
              children: [
                {
                  label: "二级 2-1",
                  children: [
                    {
                      label: "三级 2-1-1"
                    }
                  ]
                },
                {
                  label: "二级 2-2",
                  children: [
                    {
                      label: "三级 2-2-1"
                      }
                  ]
                }
              ]
            },
            {
              label: "一级 3",
              children: [
                {
                  label: "二级 3-1",
                  children: [
                    {
                      label: "三级 3-1-1"
                    }
                  ]
                },
                {
                  label: "二级 3-2",
                  children: [
                    {
                      label: "三级 3-2-1"
                    }
                  ]
                }
              ]
            }
          ],
          defaultProps: {
            children: "children",
            label: "label"
          }
        };
      }
    };
    </script>
    
    1. Tree组件属性分析
    • data: 展示数据
    • props : 配置树形结构
      • label : 设置节点名称
      • children: 指定生成子树的属性名称
    1. 自定义树节点内容:
    • data: 数据对象
    • node: 节点对象
    <el-tree :data="data" :props="defaultProps">
        <span class="custom-tree-node" slot-scope="{ node, data }">
          <span>{{ data.label}}</span>
          <span>级别: {{node.level}}</span>
        </span>
      </el-tree>
    
    1. 展示树形结构章节与课时
    <template>
      <el-tree :data="data" :props="defaultProps">
        <span class="custom-tree-node" slot-scope="{ node, data }">
          <span>{{ data.section_name || data.theme}}</span>
          <span>级别: {{node.level}}</span>
        </span>
      </el-tree>
    </template>
    <script>
    export default {
      data() {
        return {
          data: [
            {
              id: 5,
              course_id: 10,
              section_name: "麻式太极",
              description: "麻式太极拳,你动我试试",
              orderNum: 0,
              status: 2,
              create_time: "2019-07-11 10:55:10.0",
              update_time: "2019-10-09 12:43:01.0",
              isDel: 0,
              lessonList: [
                {
                  id: 32,
                  course_id: 10,
                  section_id: 5,
                  theme: "第一讲:如何给自己洗脑",
                  duration: 10,
                  is_free: 1,
                  order_num: 1,
                  status: 2,
                  create_time: "2019-01-23 20:37:02.0",
                  update_time: "2020-02-24 18:37:34.0",
                  isDel: 0
                },
                {
                  id: 33,
                  course_id: 10,
                  section_id: 5,
                  theme: "第二讲:如何给别人洗脑",
                  duration: 10,
                  is_free: 1,
                  order_num: 1,
                  status: 2,
                  create_time: "2019-01-23 20:37:02.0",
                  update_time: "2020-02-24 18:37:34.0",
                  isDel: 0
                }
              ]
            }
          ],
          defaultProps: {
            children: "lessonList",
            label: item => {
            return item.section_name || item.theme;
            }
          }
        };
      }
    };
    </script>
    

    4.3.2 显示当前课程的名称

    1. 显示当前课程名称
    <el-page-header
            @back="() => this.$router.back()"
            :content="addSectionForm.course_name"
          />
    
    1. data数据
    data() {
        //定义章节信息
        const addSectionForm = {
          course_id: undefined,
          course_name: "",
          section_name: "",
          description: "",
          order_num: 0
        };
        //章节与课时信息,树形结构
        const treeProps = {
          label: item => {
            return item.section_name || item.theme;
          },
          children: "lessonList"
        };
        //定义章节状态信息
        const statusMapping = {
          0: "已隐藏",
          1: "待更新",
          2: "已更新"
        };
        const statusForm = {
          status: 0
        };
        return {
          addSectionForm,
          treeProps,
          sections: [],
          statusForm, //状态表单
          statusMapping,
          loading: false, //树形控件
          showAddSection: false, //添加或修改章节
          showStatusForm: false //状态修改
        };
      },
    
    1. 加载课程信息
    created() {
        //1.显示当前页面在网站中的位置
        this.$breadcrumbs = [
          { name: "Courses", text: "课程管理" },
          { text: "课程结构" }
        ];
        //2. 从路由中获取传递的参数, 课程id
        const id = this.$route.params.courseId;
        if (!id) return this.redirectToError();
        //3.加载课程信息
        this.loadCourse(id);
         
        //4.加载课程对应的章节与课时
        this.loadChildren(id);
      },
          
      methods: {
        //方法1: 加载课程信息
        loadCourse(id) {
          axios
            .get("/courseContent", {
              params: {
                methodName: "findCourseById",
                course_id: id
              }
            })
            .then(res => {
              console.log(res.data);
              //将数据保存到表单对象中
              this.addSectionForm.course_id = res.data.id;
              this.addSectionForm.course_name = res.data.course_name;
            })
            .catch(error => {
              this.$message.error("数据获取失败! ! !");
            });
        },
    

    4.3.3 加载章节与课时信息

    JS部分

    //方法2: 加载树(章节与课程)
        loadChildren(id) {
          this.loading = true;
          axios
            .get("/courseContent", {
            params: {
                methodName: "findSectionAndLessonByCourseId",
                course_id: id
              }
            })
            .then(resp => {
              //获取章节数据,保存到sections
              this.sections = resp.data;
              this.loading = false;
            })
            .catch(error => {
              this.loading = false;
              this.$message.error("数据获取失败! ! !");
            });
        },
    

    HTML

    • el-tree ElementUI树形控件
      • :data 列表数据
      • :props 配置选项
    <!-- 树形控件,展示课程对应的章节信息 -->
        <el-tree
          :data="sections"
          :props="treeProps"
          v-loading="loading"
          element-loading-text="数据加载中..."
        >
          <!-- slot-scope:代表当前树节点内容,有两个参数 data表示当前树节点, node表示当前节点
    状态 -->
          <div class="inner" slot-scope="{ data, node }">
            <span>{{ data.section_name || data.theme }}</span>
    
    • :props 配置选项
      • label : 指定节点标签为节点对象的某个属性值
      • children : 指定子树为节点对象的某个属性值
    //章节与课时信息,树形结构
        const treeProps = {
          label: item => {
            return item.section_name || item.theme;
          },
          children: "lessonList"
        };  
        //children: "lessonList" 就是返回的JSON数据中的lessonList集合
    
    • 操作按钮显示
      • node.level 获取当前节点的级别
      • @click.stop 事件冒泡,点击哪个元素,就执行哪个元素绑定的事件
    <span class="actions">
        <!-- 编辑章节  @click.stop 阻止事件冒泡 -->
        <el-button
                   v-if="node.level == 1"
                   size="small"
                   @click.stop="handleEditSection(data)"
                   >编辑</el-button>
        <!-- 修改章节状态 -->
        <el-button
                   v-if="node.level == 1"
                   size="small"
                   @click.stop="handleShowToggleStatus(data)"
                   >{{ statusMapping[data.status] }}</el-button>
    </span>
    

    4.3.4 回显信息

    HTML

    <el-button type="primary" icon="el-icon-plus" @click="handleShowAddSection">添加章节</el-button>
    

    JS 部分

    //方法3: 显示添加章节表单,回显课程信息
        handleShowAddSection() {
          //显示表单
          this.showAddSection = true;
        },
    

    4.3.5 添加章节

    HTML

    <el-button type="primary" @click="handleAddSection">确 定</el-button>
    

    JS

    //方法4: 添加&修改章节操作
        handleAddSection() {
          axios
            .post("/courseContent", {
              methodName: "saveOrUpdateSection",
              section: this.addSectionForm
            })
            .then(resp => {
              //debugger;
              this.showAddSection = false;
              //重新加载列表
              return this.loadChildren(this.addSectionForm.course_id);
            })
            .then(() => {
            //reset 重置表单
              this.addSectionForm.section_name = "";
              this.addSectionForm.description = "";
              this.addSectionForm.order_num = 0;
            })
            .catch(error => {
              this.showAddSection = false;
              this.$message.error("操作执行失败! ! !");
            });
        },
    

    4.3.6 后台接口问题解决

    • BaseServlet中代码修改
    if("application/json;charset=utf-8".equals(contentType))
        
    修改为:
    if("application/json;charset=utf-8".equalsIgnoreCase(contentType))
    
    • CourseContentServlet中的saveOrUpdateSection方法修改
    //3.使用BeanUtils的 copyProperties方法,将map中的数据封装到section对象里
     BeanUtils.copyProperties(section,map.get("section"));
    

    4.3.7 修改章节

    HTML

    <el-button v-if="node.level == 1" size="small" 
    @click.stop="handleEditSection(data)">编辑</el-button>
    

    JS 回显示方法

    //方法5: 修改章节回显方法
        handleEditSection(section) {
          //对象拷贝
          Object.assign(this.addSectionForm, section);
          this.showAddSection = true;
        },
    
    • 事件冒泡:当点击子元素的事件。如果父元素也有同样的事件的话。他就会一并的触发。
    • 解决冒泡事件的方法: @click.stop
    <body>
        <!-- 事件冒泡: 解决方案 @click.stop -->
        <div id="app" @click="log('div点击事件')">
          <button @click="log('button点击事件')">事件冒泡</button>
        </div>
      </body>
      <script src="./js/vue.min.js"></script>
      <script>
        var VM = new Vue({
        el: "#app",
          methods: {
            log(t) {
              alert(t);
            },
          },
        });
      </script>
    

    4.3.8 章节状态回显

    HTML

    <!-- 修改章节状态 -->
     <el-button
     v-if="node.level == 1"
     size="small"
     @click.stop="showStatus(data)"
     >{{ statusMapping[data.status] }}</el-button>
    

    JS

    //data函数中定义的章节状态
    const statusMapping = {
        0: "已隐藏",
        1: "待更新",
        2: "已更新"
    };
    
    //方法6: 章节状态修改
    showStatus(data) {
        this.statusForm.id = data.id;
        this.statusForm.status = data.status.toString();
        this.statusForm.data = data;
        this.showStatusForm = true;//显示状态表单
    },
    

    4.3.9 Select选择器

    1. 打开我们之前编写的VueCLI项目
    2. 在component目录下,添加一个组件, TestSelect.vue
    <template></template>
    <script>
        export default {};
    </script>
    <style scoped>
    </style>
    
    1. 在Index.vue组件中的导航菜单位置添加一个 Select选择器 导航.

    注意:要设置index的路径为 /select

    <el-menu-item index="/select">
        <i class="el-icon-menu"></i>Select选择器
     </el-menu-item>
    
    1. 在index.js 路由文件中进行配置,在布局路由中再添加一个子路由
    {
        path: "/select",
        name: "select",
        component: Select,
    },
    
    1. 在ElementUI官网中查找Select选择器

    1. 查看基础用法,将代码复制到 TestSelect.vue中
    <template>
      <el-select v-model="value" placeholder="请选择">
        <el-option v-for="item in options" :key="item.value" :label="item.label" 
    :value="item.value"></el-option>
      </el-select>
    </template>
    <script>
    export default {
      data() {
        return {
          options: [
            {
              value: "选项1",
              label: "黄金糕"
            },
            {
              value: "选项2",
              label: "双皮奶"
            },
            {
              value: "选项3",
              label: "蚵仔煎"
            },
            {
              value: "选项4",
              label: "龙须面"
            },
            {
              value: "选项5",
              label: "北京烤鸭"
            }
          ],
          value: ""
        };
      }
    };
    </script>
    
    1. select 选择器属性分析
    • v-model: 的值为当前被选中的el-option的 value 属性值
    • el-option : 选项
      • label 选项的标签名
      • value 选择的值
    1. 使用Select选择器展示状态信息
    <template>
      <el-select v-model="status" placeholder="请选择">
        <el-option
          v-for="index in Object.keys(statusMappings)"
          :key="index"
          :label="statusMappings[index]"
          :value="index"
        ></el-option>
      </el-select>
    </template>
    <script>
    export default {
      data() {
        return {
          statusMappings: {
            0: "已隐藏",
            1: "待更新",
            2: "已更新"
          },
          status:0
        };
      }
    };
    </script>
    
    • Object.keys()
    var obj = { 0: 'a', 1: 'b', 2: 'c' };
    console.log(Object.keys(obj)); // console: ['0', '1', '2']
    

    4.4.10 章节状态修改

    HTML

    <el-button type="primary" @click="updateStatus">确 定</el-button>
    

    JS部分

    //方法7: 修改章节状态
        updateStatus(statusForm) {
          axios
            .get("/courseContent", {
              params: {
                methodName: "updateSectionStatus",
                status: this.statusForm.status,
                id: this.statusForm.id
              }
            })
            .then(resp => {
              this.statusForm.data.status = this.statusForm.status;
              this.statusForm = {};
              this.showStatusForm = false;
            })
            .catch(error => {
              this.showStatusForm = false;
              this.$message.error("修改状态失败! ! !");
            });
        },
    
    • v-for里面数据层次太多, 修改过数据变了,页面没有重新渲染,需手动强制刷新。
    @change="$forceUpdate()" 强制刷新
    

    本文来自博客园,作者:寒露凝珠,转载请注明原文链接:https://www.cnblogs.com/china-soldier/p/15341695.html

  • 相关阅读:
    VS Code的常用备忘
    Echarts圆环,初始化时进度条效果
    nodejs 复制文件到 另一路径下 。可以在npm库看下mv 和 mvdir 有一点区别
    nginx启动报错(1113: No mapping for the Unicode character exists in the target multi-byte code page
    Echarts dataZome 横向移动动态显示数据
    flex布局时,会有兼容性问题,所以能少用flex布局的地方还是要避免下
    python 搭建 flask 和 orator框架开发
    直播 小测试
    对高并发的理解
    MySQL 中文分词原理
  • 原文地址:https://www.cnblogs.com/china-soldier/p/15341695.html
Copyright © 2011-2022 走看看