大事件项目分享---实现后台操作交互---后台页面数据的增删改查

项目介绍:

实现的页面效果:

后台管理页面:

以上的静态页面,通过 HTML结构 和 CSS样式  实现  而页面的交互由 JS 来实现

练习项目的目标:

1.了解真实项目开发的架构设计

  • (1)前端三层分离的编程思想

  • (2)网络请求层单独处理的编程思想

2.培养大家的项目思维能力

  • (1)独立小功能需求分析->页面需求分析->整个项目需求分析

  • (2)熟练运用ajax+模板引擎实现页面业务逻辑功能

3.提升大家的项目经验

  • (1)项目技术难点的分析与解决方案

  • (2)各种第三方插件使用

回顾ajax发起请求和接收响应

回顾模板引擎实现数据的动态渲染

掌握token实现状态保持的前台页面实现过程

进一步的掌握和体会前台页面的交互,理解前台页面交互的处理流程

进一步的掌握ajax的其它使用方式

 

搭建后台环境:

项目之前需要使用数据可视化软件 naVicat  和 mysql数据库 将以存储的数据导入和服务器的开启  

打开大事件项目文件夹 >> 找到大事件接口文件夹 >> 找到BigEventServers文件夹 >> 找到config 下的文件 index.js 打开 根据文件内容

根据以上内容,在Navicat 中新建一个名字叫 'bignews' 的数据库  >>  然后在BigEventServers文件夹中找到 reset 文件打开 >>  在打开的该目录下打开小黑窗  >>  输入命令 node index.js 出现'搞定'两个字即数据导入成功.

打开服务器: 在BigEventServers文件夹目录下 打开小黑窗 输入命令  app.js 运行 出现:  开启成功:  http://localhost:8080   即服务器打开成功.

 

模态框的添加

原因:: 相当于弹出层,可以用于取代alert进行用户提示  

 1 <!-- 模态框做为body的直接子元素 -->
 2 <div class="modal fade" id="myModal" tabindex="-1" role="dialog">
 3     <div class="modal-dialog" role="document">
 4         <div class="modal-content">
 5             <div class="modal-header">
 6                 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
 7                                                                                                   aria-hidden="true">&times;</span></button>
 8                 <h4 class="modal-title">友情提示</h4>
 9             </div>
10             <div class="modal-body">
11                 <p class="logininfo">One fine body&hellip;</p>
12             </div>
13             <div class="modal-footer">
14                 <button type="button" class="btn btn-primary btnconfirm">确定</button>
15             </div>
16         </div>
17     </div>
18 </div>

 

注意点:   模态框的整体结构要直接做 body 的子元素, 如果嵌套在其他HTML结构中会出现模态框无法点击使用

http模块的封装

作用: 使页面的代码更简洁, 便于管理, 不易出错. 页面请求的 url 只需要引入该文件(http.js) 再调用方法即可

 1 (function (w) {
 2   var baseURL = 'http://127.0.0.1:8080/api/v1'
 3   w.itcast = {
 4     // 定义基准路径,所谓基准路径就是资源url前面那一坨
 5     baseURL: baseURL,//基地址
 6     user_login: baseURL + '/admin/user/login',//用户登录
 7     user_info: baseURL + '/admin/user/info',//用户信息
 8     user_detail: baseURL + '/admin/user/detail',//用户详情
 9     user_edit: baseURL + '/admin/user/edit',//用户编辑
10     category_list: baseURL + '/admin/category/list',//文章类别查询
11     category_add: baseURL + '/admin/category/add',//文章类别新增
12     category_search: baseURL + '/admin/category/search',//文章类别搜索
13     category_edit: baseURL + '/admin/category/edit',//文章类别编辑
14     category_delete: baseURL + '/admin/category/delete',//文章类别删除
15     article_query: baseURL + '/admin/article/query',//文章搜索
16     article_publish: baseURL + '/admin/article/publish',//文章发布
17     article_search: baseURL + '/admin/article/search',//文章信息查询
18     article_edit: baseURL + '/admin/article/edit',//文章编辑
19     article_delete: baseURL + '/admin/article/delete',//文章删除
20     comment_search: baseURL + '/admin/comment/search',//文章评论列表
21     comment_pass: baseURL + '/admin/comment/pass',//文章评论通过
22     comment_reject: baseURL + '/admin/comment/reject',//文章评论不通过
23     comment_delete: baseURL + '/admin/comment/delete',//文章评论删除
24   }
25 })(window)

 

 

后台登录页面

实现点击登录按钮, 登录到后台首页页面

 1 // 实现登陆
 2 // 1、用户登录
 3 // 请求地址:/admin/user/login
 4 // 请求方式:post
 5 $('.input_sub').on('click', function () {
 6     // serialize:获取获取指定表单中拥有name属性的表单元素的value值
 7     console.log($('.login_form').serialize())
 8     $.ajax({
 9         type: 'post',
10         url: itcast.user_login,
11         data: $('.login_form').serialize(),
12         dataType: 'json',
13         success: function (res) {
14             console.log(res)
15             $('.logininfo').text(res.msg)
16             if (res.code == 200) {
17                 // 将后台返回的token数据存储到本地
18                   localStorage.setItem('bignews_token_58', res.token)
19                 $('#myModal').modal('show')
20                 // hidden.bs.modal:在当前模态框被隐藏之后触发
21                 $('#myModal').on('hidden.bs.modal', function (e) {
22                     location.href = './index.html'
23                 })
24             } else {
25                 // alert(res.msg)
26                 $('#myModal').modal('show')
27             }
28         }
29     })
30 })
31 
32 // 单击模态框中的确定,隐藏模态框
33 $('.btnconfirm').on('click', function () {
34     $('#myModal').modal('hide')
35 })

 

因为后续的页面的操作都需要权限操作 , 即如果用户登录成功了才可以在后续的页面中使用增删改查的权限 , 那就需要给页面传一个tokan令牌,证明用户已经登录过了,即可继续操作页面,

因为后续的页面有很多请求, 如果一个个去加既麻烦还冗余, 这时候就需要一个全局函数来解决这种  

该函数可以写在页面引入的 jQuery文件 的 最后 不要加在中间或其他地方,容易更改了原代码的结构

 1 // 这里添加ajax的全局函数的配置
 2 $.ajaxSetup({
 3     // 每个请求发送之前都会经过beforeSend,可以在这个回调进行请求头的统一设置
 4     beforeSend: function (xhr) {
 5         let token = localStorage.getItem('bignews_token_58')
 6         if (token) {
 7             xhr.setRequestHeader('Authorization', token)
 8         }
 9     },
10     // 添加统一的错误处理
11     error: function (xhr, status, error) {
12         console.log(xhr, status, error)
13         if (error == 'Forbidden') {//用户未登录
14             alert('请先登录!')
15             window.location.href = './login.html';//跳转登陆页面
16         };
17     }
18 })

注意事项:

在前端页面结构中如果按钮的类型为: 'submit' 会有一个默认行为,会影响到后面的操作, 所以将登陆按钮的type属性从submit修改为button

参数获取不到,我们需要人为设置表单元素的name, 因为 serialize() 的方法会获取到表单域中带有name属性的元素的表单值  name值一定要参照后台接口

 

token的本地存储和传递

在登陆成功之后将token存储到本地

后续请求传递token

为了简化操作,使用$.ajaxSetup进行统一的处理

在登陆成功之后将token存储到本地

// 将后台返回的token数据存储到本地
localStorage.setItem('bignews_token_58', res.token)

 

首页

用户信息的动态渲染

首页主体内容页面的展示

左侧菜单的功能处理

顶部栏的个人中心和退出

用户信息的动态渲染

// 动态渲染用户信息
// 2、获取用户信息
// 请求地址:/admin/user/info
// 请求方式:get
$.ajax({
        url: allSite.user_info,
        dataType: 'json',
        // beforeSend: function (xhr) {
        //     xhr.setRequestHeader('Authorization', localStorage.getItem('token_58'))
        // },
        success: function (res) {
            console.log(res);
            if (res.code == 200) {
                $('.user_info>img').attr('src', res.data.userPic)
                $('.user_info>span').html(`欢迎&nbsp;&nbsp;${res.data.nickname}`)
                $('.user_center_link>img').attr('src', res.data.userPic)
            }
        }
    })

 

 

首页主体内容页面的展示

使用iframe浮动框架,也称为页中页

使用方式

1.添加浮动框架,为浮动框架设置name属性

2.设置超链接的target属性的值为iframe的name属性的 值

 

<!-- 右侧主体内容 -->
<div class="main" id="main_body">
    <!-- 添加一个浮动框架 -->
    <iframe class="myframe" src="./main_count.html" frameborder="0" name='main_frame'></iframe>
</div>

 

左侧菜单的功能

 1 //主页左侧导航栏功能实现
 2     $('.level01').on('click', function () {
 3         $(this).addClass('active').siblings().removeClass('active')
 4 
 5         if ($(this).next().hasClass('level02')) {
 6             $(this).next().slideToggle()
 7             $(this).find('b').toggleClass('rotate0')
 8         } else {
 9             $('.level02').slideUp()
10             $('.level02>li').removeClass('active')
11         }
12     })
13 
14     $('.level02>li').on('click', function () {
15         $(this).addClass('active').siblings().removeClass('active')
16     })

 后台首页顶部的个人中心功能:

效果: 实现点击个人中心跳转到个人中心页面,并给左侧的导航栏的个人中心导航选项添加样式

<a href="./user.html" target="main_frame" onclick='$("#user").click()'>个人中心</a>

 

后台首页顶部的退出功能:

效果: 点击退出 实现删除之前存储的token  并且跳转到登录页面

//点击退出按钮实现删除token令牌,跳转到登录页面
    $('.logout').on('click', function () {
        localStorage.removeItem('token_58')
        window.location.href = './login.html'
    })

 

 

文章列表页

主要实现功能:

  • 页面数据的渲染,让后台文章数据动态渲染到页面中
  • 数据筛选功能, 选择文章类型和状态,点击筛选, 使页面数据根据选项动态渲染
  • 分页插件, 在列表页下方生成一个分页结构,使用户点击对应键,跳转到对应的页面
  • 实现发表文章 和 编辑文章 的页面跳转

页面数据的渲染

使用模板引擎动态渲染页面会更简便

 1 <!-- 页面需要先引入模板引擎js文件 -->
 2     <script src="./libs/template-web.js"></script>
 3 -----------------------------------------------------
 4 
 5 <!-- 模板结构 -->
 6 <script type="text/template" id="articleListTemp">
 7         {{each data}}
 8             <tr>
 9                 <td>{{$value.title}}</td>
10                 <td>{{$value.author}}</td>
11                 <td>{{$value.category}}</td>
12                 <td class="text-center">{{$value.date}}</td>
13                 <td class="text-center">{{$value.state}}</td>
14                 <td class="text-center">
15                     <a href="article_edit.html" class="btn btn-default btn-xs">编辑</a>
16                     <a href="javascript:void(0);" class="btn btn-danger btn-xs delete">删除</a>
17                 </td>
18             </tr>
19         {{/each}}
20     </script>

 

实现动态渲染:

注意点: 在这里发起请求时 对应的传参需要根据服务器接口文档 所需的参数来传递 

文档所示所有的值可以为空, 则有默认值 

// 获取所有文章数据,实现文章数据的列表渲染
  // 10、文章搜索
  // 请求地址:/admin/article/query
  // 请求方式:get
$.ajax({
    url: itcast.article_query,
    data: {
        page: 1, // 当前页码
        perpage: 10 // 每页展示的数量
    },
    dataType: 'json',
    success: function (res) {
        console.log(res)
        if (res.code == 200) {
            $('tbody').html(template('articleListTemp', res.data))
        }
    }
})

 

 

数据筛选功能

难点: 下拉列表的使用 

下拉列表的基本特性

  • 如果没有设置value属性,那么后期获取到的select下拉列表的value属性值为option标签之间的值

  • 如果设置了value属性,那么后期获取到的就是value属性所绑定的值

下拉列表的使用场景

  • 展示固定选项 -- 根据后台需求和展示需要固定写死

  • 渲染动态选项 -- 实现下拉列表的动态渲染,同时要根据数据业务的处理需求设置value属性

下拉列表的动态渲// 分类数据的动态渲染

// 5、所有文章类别
// 请求地址:/admin/category/list
// 请求方式:get
  //设定全局变量 分页插件结构也会用到
    let page = 1, perpage = 10
  $.ajax({
    url: itcast.category_list,
    dataType: 'json',
    success: function (res) {
        console.log(res)
        if (res.code == 200) {
            let str = `<option value="">所有分类</option>`
            for (let i = 0; i < res.data.length; i++) {
                str += `<option value='${res.data[i].id}'>${res.data[i].name}</option>`
            }
            $('#selCategory').html(str)
        }
    }
})

 

这时候会返回的数据

数据的筛选

  • 对于所有状态,文章只有两种状态:草稿|已发布,意味着我们可以固定写死

  • 对于文章分类,它的数据是来自于后台数据库,所以需要动态渲染

  • 对于后台的处理是:如果传入的分类或状态参数,就会拼接条件,否则不拼接条件,而查询所有数据

函数的封装

因为每次筛选都会重新渲染文章列表页,所以将上面的页面渲染代码进行函数封装,这样能够使代码复用,更加简洁

function init () {
    $.ajax({
        url: itcast.article_query,
        data: {
            page: 1, // 当前页码
            perpage: 10, // 每页展示的数量
            type: $('#selCategory').val(), // 文章的分类,如果为''则查询所有分类的文章数据
            state: $('#selStatus').val() // 文章的状态,如果为''则查询所有状态的文章数据
        },
        dataType: 'json',
        success: function (res) {
            console.log(res)
            if (res.code == 200) {
                $('tbody').html(template('articleListTemp', res.data))
            }
        }
    })
}

 

实现数据的筛选

// 实现数据筛选
$('#btnSearch').on('click', function (e) {
    e.preventDefault()
    page = 1
    init()
})

 

分页插件 实现分页结构

当数据量比较大的时候,不适合在一页展示完所有数据的时候,就应该进行分页

需要用到分页插件  在Bootstrap官网中就提供了这种分页插件 

bootstrap-paginator是一款基于bootstrap的jQuery分页插件

注意点: 根据下载的文件版本  在传参数时需要注意 参数:  bootstrapMajorVersion 需要根据版本传入对应的值

参数: 红色字体为必须参数

 

页面需要引入的文件:

<link rel="stylesheet" href="./lib/bootstrap.css">
<!--使用bootstrap插件必须使用引入jquery,因为bootstrap是基于jquery开发的-->
<script src="./lib/jquery-2.1.1.min.js"></script>
<!--bootstrap插件-->
<script src="./lib/bootstrap.js"></script>
<!--分页插件-->
<script src="./lib/bootstrap-paginator.js"></script>

 

实现分页结构

 //实现分页结构的显示
    /**
     *
     * @param pageCurrent 当前所在页  因为有全局变量定义则不用传递
     * @param pageSum 总页数
     * @param callback 调用ajax   不需要触发
     */
    function setPage(pageSum) {
        $(".pagination").bootstrapPaginator({
            //设置版本号
            bootstrapMajorVersion: 3,
            // 显示第几页
            currentPage: page,
            // 总页数
            totalPages: pageSum,
            //当单击操作按钮的时候, 执行该函数, 调用ajax渲染页面
            onPageClicked: function (event, originalEvent, type, getpage) {
                // getpage 为第四个参数,获取用户点击的页码数
                console.log(getpage);
                //获取的页码赋值给全局变量
                page = getpage;
                // 再重新渲染页面,跳转到对应页数
                init()
            }
        })
    }

 

调用分页函数实现分页功能

在上面的代码进行修改

function init() {
        $.ajax({
            // 10、文章搜索
            // 请求地址:/ admin / article / query
            // 请求方式:get

            url: allSite.article_query,
            data: {
                type: $('#selCategory').val(), // 文章的分类,如果为''则查询所有分类的文章数据
                state: $('#selStatus').val(), // 文章的状态,如果为''则查询所有状态的文章数据
                page: page,
                perpage: perpage
            },
            dataType: 'json',
            success: function (res) {
                console.log(res);
      -------------------------------下面是实现的代码---------------------------
                if (res.code == 200) {
                    //将模板添加到对应位置渲染出来
                    $('tbody').html(template('articleListTemp', res.data))
                    //分页结构的渲染
                    if (res.data.data.length == 0) {
                        //当筛选文章数据时,数据为零时,分页插件会默认显示5页分页,不符合实际的需求,所以当数据为零时分页结构显示一页
                        setPage(1)
                    } else {
                        //其他情况即为有数据 则正常渲染
                        setPage(res.data.totalPage)
                    }
                }
            }
        })
    }
    init()

 

文章发布

收集后台接口需要的数据 

注意是使用 formdata 方式提交数据, 图片也是已数据传递 , 而不是简单的传递字符串

打开发布文章页面就开始渲染分类数据

这里要注意: 在页面文件中要传入封装好的 http.js 文件 即 url 对应的地址

 1 //打开发布文章,渲染页面的文章类别
 2     $.ajax({
 3         // 所有文章类别
 4         // 请求地址:/ admin / category / list
 5         // 请求方式:get
 6         url: allSite.category_list,
 7         dataType: 'json',
 8         success: function (res) {
 9             // console.log(res);
10             let str = ''
11             for (let index = 0; index < res.data.length; index++) {
12                 str += `<option value="${res.data[index].id}">${res.data[index].name}</option>`
13             }
14             $('.category').html(str)
15         }
16     })

 

实现发布文章页面的文件预览

注意事项,因为使用的是formdata 方式上传  即用户选择好图片时就实现预览但不上传文件, 这时候就需要本地预览 

URL.creatObjectUrl:它可以将指定的资源托管到内置临时服务器

 1   /*2.文件预览 */
 2     //1.给file表单元素注册onchange事件
 3     $('#inputCover').change(function () {
 4         //1.2 获取用户选择的图片 通过URL的createObjectUrl获取托管在服务器端的资源路径
 5         var file = $('#inputCover')[0].files[0];
 6         //1.3 将文件转为src路径
 7         var url = window.URL.createObjectURL(file);
 8         //1.4 将url路径赋值给img标签的src
 9         $('.article_cover').attr('src', url);
10     });

 

实现发布文章页面的时间功能

需要一个日期插件 在页面文件中需要引入css 和 js 在页面结构中还需要一个载体 建议使用文本框

引入文件

<link rel="stylesheet" href="./libs/jedate/css/jedate.css">
<script src="./libs/jedate/js/jedate.js"></script>

 

添加载体

<div class="form-group">
     <label class="col-sm-2 control-label">发布时间:</label>
     <div class="col-sm-4">
      --------添加一个文本框载体---------------   <input type="text" class="jeinput" id="testico" placeholder="YYYY-MM-DD" name='date'> </div> </div>

 

在页面的js文件中 进行日期插件的初始化

在 jeDate 中有两个参数, 第一个参数传入载体, 第二参数传的是一个对象,用于定制日期插件的功能样式, 可以不传 则有默认值,但样式会很丑.

插件获取日期值 用value方式就可以获取

  //加入日期插件
    $(function () {
jeDate("#testico", { trigger: "click", format: "YYYY-MM-DD", theme: { bgcolor: "#D91600", pnColor: "#FF6653" }, isinitVal: true }) });

 

实现发布文章页面添加富文本框插件

引入资源

<script src="./libs/tinymce/tinymce.min.js"></script>

 

添加载体

         <div class="form-group">
                    <label for="inputEmail3" class="col-sm-2 control-label">文章内容:</label>
                    <div class="col-sm-10">
            ------------------添加载体------------
            <textarea id="mytextarea"></textarea> </div> </div>

 

在页面的js文件中 进行插件的初始化

注意事项: 

  • 富文本框插件会在载体上方添加一个新的结构,用户的数据是输入在这个新结构中,意味着我们无法从文本框载体中获取数据
  • 富文本框的内容是网页结构,因为它要记录用户输入内容的格式,而html可以描述这种结构
//加入富文本框插件
    tinymce.init({
        selector: '#mytextarea',
        height: '350px',
        language: 'zh_CN',
        directionality: 'ltl',
        browser_spellcheck: true,
        contextmenu: false,
        plugins: [
            "advlist autolink lists link image charmap print preview anchor",
            "searchreplace visualblocks code fullscreen",
            "insertdatetime media table contextmenu paste imagetools wordcount",
            "code"
        ],
        toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | code",
    });

 

获取插件的内容的方法: tinymce.activeEditor.getContent()

再将数据添加到 formdata 中 

  let formdata = new FormData($('#form')[0])
    // console.log(tinymce.activeEditor.getContent())
    // 将富文本框的内容添加到formdata
    formdata.append('content', tinymce.activeEditor.getContent())

 

实现文章的新增

下面是完整的实现代码  其中没有 分类的动态渲染和插件的使用 的代码  是因为后期还需要复用到 所以封装到一个js文件中去引入使用  则在页面HTML文件中引入即可,下方有详细代码

注意事项:

  • 使用formdata方式获取数据时 会少了 富文本框的数据 和 文章状态的数据  就需要主动添加进去
  • 发布文章的图片一定要上传, 因为后台接口是固定需要不可以为空 ,不传递会报400的错误 即参数不正确
  • 图片的格式支持jpg,png,gif,扩展名要求小写
 1 $(function () {
 2     /*2.文件预览 */
 3     //1.给file表单元素注册onchange事件
 4     $('#inputCover').change(function () {
 5         //1.2 获取用户选择的图片
 6         var file = $('#inputCover')[0].files[0];
 7         //1.3 将文件转为src路径  通过URL的createObjectUrl获取托管在服务器端的资源路径
 8         var url = window.URL.createObjectURL(file);
 9         //1.4 将url路径赋值给img标签的src
10         $('.article_cover').attr('src', url);
11     });
12     //点击发布按钮,获取用户数据
13     // 11、发布文章
14     // 请求地址:/admin/article / publish
15     // 请求方式:post
16     // 请求参数:通过formData提交
17     // 由于发布按钮和草稿按钮业务逻辑相同,
18     // 只是state参数不同,可以封装一个函数,将state作为参数传递
19     $('.btn-release').on('click', function (e) {
20         //阻止默认行为
21         e.preventDefault()
22         uploadingData('已发布')
23     })
24     $('.btn-draft').on('click', function (e) {
25         //阻止默认行为
26         e.preventDefault()
27         uploadingData('草稿')
28     })
29     
30     function uploadingData(state) {
31         //创建FormData
32         let formdata = new FormData($('#form')[0])
33         //tinymce.activeEditor.getContent()获取富文本框的文本内容  获取的数据是以 HTML格式显示 ,后期渲染时需要使用html方法
34         formdata.append('content', tinymce.activeEditor.getContent())
35         //追加文章状态
36         formdata.append('state', state)
37         console.log(...formdata);
38         //实现文章发布
39         $.ajax({
40             type: 'post',
41             url: allSite.article_publish,
42             data: formdata,
43             dataType: 'json',
44             contentType: false,
45             processData: false,
46             success: function (res) {
47                 console.log(res);
48                 if (res.code == 200) {
49                     alert(res.msg)
50                     //返回文章列表页 ,给左侧列表页导航栏项添加样式
51                     $('.level02>li:eq(0)', window.parent.document).addClass('active').siblings().removeClass('active');
52                     window.location.href = './article_list.html'
53                 }
54             }
55         })
56     }
57 
58 })

 

公共代码  comment.js

 1 $(function () {
 2     //打开发布文章,渲染页面的文章类别
 3     $.ajax({
 4         // 所有文章类别
 5         // 请求地址:/ admin / category / list
 6         // 请求方式:get
 7         url: allSite.category_list,
 8         dataType: 'json',
 9         success: function (res) {
10             // console.log(res);
11             let str = ''
12             for (let index = 0; index < res.data.length; index++) {
13                 str += `<option value="${res.data[index].id}">${res.data[index].name}</option>`
14             }
15             $('.category').html(str)
16         }
17     })
18 
19     //加入日期插件
20     $(function () {
21         //或者为这样的
22         jeDate("#testico", {
23             trigger: "click",
24             format: "YYYY-MM-DD",
25             theme: { bgcolor: "#D91600", pnColor: "#FF6653" },
26             isinitVal: true
27         })
28     });
29 
30     //加入富文本框插件
31     tinymce.init({
32         selector: '#mytextarea',
33         height: '350px',
34         language: 'zh_CN',
35         directionality: 'ltl',
36         browser_spellcheck: true,
37         contextmenu: false,
38         plugins: [
39             "advlist autolink lists link image charmap print preview anchor",
40             "searchreplace visualblocks code fullscreen",
41             "insertdatetime media table contextmenu paste imagetools wordcount",
42             "code"
43         ],
44         toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | code",
45     });
46 })

 

文章删除功能

注意事项:

  • 在文章列表页面中 文章的数据时使用模板引擎动态渲染的 所有在绑定事件时 不可以直接绑定在元素上, 要通过结构中存在的父元素来绑定--事件委托的方式
  • 删除事件需要根据id来进行删除 而结构中又没有id参数传递 这时候就需要自己添加 自定义属性  data  来存储id 再去获取id

在模板结构的删除结构 添加自定义属性

 1 <script type="text/template" id="articleListTemp">
 2         {{each data}}
 3             <tr>
 4                 <td>{{$value.title}}</td>
 5                 <td>{{$value.author}}</td>
 6                 <td>{{$value.category}}</td>
 7                 <td class="text-center">{{$value.date}}</td>
 8                 <td class="text-center">{{$value.state}}</td>
 9                 <td class="text-center">
10                     <a href="article_edit.html?id={{$value.id}}" class="btn btn-default btn-xs" id="compile_btn">编辑</a>
               --------------添加自定义属性--------------------------- 11 <a href="javascript:void(0);" class="btn btn-danger btn-xs delete_btn" data-id='{{$value.id}}'>删除</a> 12 </td> 13 </tr> 14 {{/each}}

 

实现删除效果

注意获取页面传递的id

 1 //实现删除文章功能
 2     // 14、删除文章
 3     // 请求地址:/admin/article / delete
 4     // 请求方式:post
 5     $('table>tbody').on('click', '.delete_btn', function () {
 6         $.ajax({
 7             type: 'post',
 8             url: allSite.article_delete,
 9             dataType: 'json',
10             data: {
            --------------获取页面传递的id-------------
11 id: $(this).attr('data-id') 12 }, 13 success: function (res) { 14 console.log(res); 15 if (res.code == 204) { 16 alert(res.msg) 17 location.reload(); 18 } else { 19 alert(res.msg) 20 } 21 } 22 }) 23 })

 

文章编辑功能

用户点击编辑, 跳转到编辑页面 根据后台数据渲染 编辑文章页面 

渲染页面注意事项:

  • 在编辑跳转时要传递id 
  • 在编辑页接收参数id
  • 根据id查询文章详情数据
  • dom赋值

实现数据的默认展示

传递id

<script type="text/template" id="articleListTemp">
        {{each data}}
            <tr>
                <td>{{$value.title}}</td>
                <td>{{$value.author}}</td>
                <td>{{$value.category}}</td>
                <td class="text-center">{{$value.date}}</td>
                <td class="text-center">{{$value.state}}</td>
                <td class="text-center">
             -------------添加?id={{$value.id}} 用于传递id-----------------------
            <a href="article_edit.html?id={{$value.id}}" class="btn btn-default btn-xs" id="compile_btn">编辑</a> <a href="javascript:void(0);" class="btn btn-danger btn-xs delete_btn" data-id='{{$value.id}}'>删除</a> </td> </tr> {{/each}}

 在编辑页面获取id

使用 itcast.getParameter 需要在页面文件中引入一个js文件 用于把传递的参数结构为  key=value&key=value&key=value....  转换为对象

//1.获取artile_list页面传递过来的文章id
    let id = itcast.getParameter(location.search).id
    // console.log(id);

 引入的文件结构  可以创建文件再复制粘贴代码使用

 1 var itcast = {
 2     getParameter: function (str) { // ?id=7&name=jack
 3         // 删除?
 4         str = str.replace('?', '')  // id=7&name=jack
 5         // 分割字符串
 6         var arr = str.split('&')  // ["id=7","name=jack"]
 7         // 循环遍历再次分割
 8         var obj = {}
 9         for (var i = 0; i < arr.length; i++) { // 1.id=7
10             var temp = arr[i].split('=') // ["id",7]
11             // 将数据添加到对象
12             obj[temp[0]] = temp[1] // {id:7}
13         }
14         return obj
15     }
16 }

根据id查询文章详情数据

注意事项:

  • 获取id 需要定义全局变量 后面也会使用到
  • 用户不传入图片时,后台就默认不修改
  • 在给时间插件复制需要注意 因为 时间插件封装的js文件 和 页面的js文件是分开的, 却都是异步操作,所以有可能会造成文章详情数据已经成功的获取了,而分类下拉列表还没有渲染完毕,所以造成选项不能切换.
    这时候需要定时器延迟加载  // settimeout中的代码,会在其它所有代码执行完毕之后再执行
  • 富文本框的赋值    插件默认会将文本域的内容同步到富文本框插件,当插件加载完毕之后同步
 1 //根据id获取文章信息
 2     // 12、根据id获取文章信息
 3     // 请求地址:/admin/article / search
 4     // 请求方式:get
 5 
 6     //1.获取artile_list页面传递过来的文章id
 7     let id = itcast.getParameter(location.search).id
 8     // console.log(id);
 9     $.ajax({
10         url: allSite.article_search,
11         data: { id },
12         dataType: 'json',
13         success: function (res) {
14             // console.log(res);
15             if (res.code == 200) {
16                 $('#inputTitle').val(res.data.title)
17                 $('.article_cover').attr('src', res.data.cover)
            // settimeout中的代码,会在其它所有代码执行完毕之后再执行
18 setTimeout(function () { 19 $('select.category').val(res.data.categoryId) 20 }, 0) 21 $('#testico').val(res.data.date)
            //
富文本框的赋值    插件默认会将文本域的内容同步到富文本框插件,当插件加载完毕之后同步
22                 $('#mytextarea').val(res.data.content)
23             }
24         }
25     })

实现编辑功能

下面是完整代码

 1 $(function () {
 2     //根据id获取文章信息
 3     // 12、根据id获取文章信息
 4     // 请求地址:/admin/article / search
 5     // 请求方式:get
 6     //1.获取artile_list页面传递过来的文章id
 7     let id = itcast.getParameter(location.search).id
 8     // console.log(id);
 9     $.ajax({
10         url: allSite.article_search,
11         data: { id },
12         dataType: 'json',
13         success: function (res) {
14             // console.log(res);
15             if (res.code == 200) {
16                 $('#inputTitle').val(res.data.title)
17                 $('.article_cover').attr('src', res.data.cover)
18                 setTimeout(function () {
19                     $('select.category').val(res.data.categoryId)
20                 }, 0)
21                 $('#testico').val(res.data.date)
22                 $('#mytextarea').val(res.data.content)
23             }
24         }
25     })
26     // 13、文章编辑
27     // 请求地址:/admin/article / edit
28     // 请求方式:post
29     $('.btn-edit').on('click', function (e) {
30         //阻止默认行为
31         e.preventDefault()
32         uploadingData('已发布')
33     })
34     $('.btn-draft').on('click', function (e) {
35         //阻止默认行为
36         e.preventDefault()
37         uploadingData('草稿')
38     })
39 
40     function uploadingData(state) {
41         //创建FormData
42         let formdata = new FormData($('#form')[0])
43         //tinymce.activeEditor.getContent()获取富文本框的文本内容  获取的数据是以 HTML格式显示 
44         formdata.append('content', tinymce.activeEditor.getContent())
45         //追加文章状态
46         formdata.append('state', state)
47         //追加id
48         formdata.append('id', id)
49         // console.log(...formdata);
50         //实现文章发布
51         $.ajax({
52             type: 'post',
53             url: allSite.article_edit,
54             data: formdata,
55             dataType: 'json',
56             contentType: false,
57             processData: false,
58             success: function (res) {
59                 console.log(res);
60                 if (res.code == 200) {
61                     alert('修改成功')
62                     //返回文章列表页 ,给左侧列表页导航栏项添加样式
63                     $('.level02>li:eq(0)', window.parent.document).addClass('active').siblings().removeClass('active');
64                     window.location.href = './article_list.html'
65                 }
66             }
67         })
68     }
69     /*2.文件预览 */
70     //1.给file表单元素注册onchange事件
71     $('#inputCover').change(function () {
72         //1.2 获取用户选择的图片
73         var file = $('#inputCover')[0].files[0];
74         //1.3 将文件转为src路径
75         var url = window.URL.createObjectURL(file);
76         //1.4 将url路径赋值给img标签的src
77         $('.article_cover').attr('src', url);
78     });
79 })

 

 

文章类别管理

文章类别的动态渲染

资源引入

   <link rel="stylesheet" href="./libs/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/iconfont.css">
    <link rel="stylesheet" href="css/main.css">
    <script src="./libs/jquery-1.12.4.min.js"></script>
    <script src="./libs/bootstrap/js/bootstrap.min.js"></script>
    <script src="./js/http.js"></script>
    <!-- 引入模板引擎js文件 -->
    <script src="./libs/template-web.js"></script>
    <script src="./js/article_category.js"></script>

 

页面添加模板结构

 1 <!-- 模板结构 -->
 2     <script type="text/template" id="cataTemp">
 3         {{each data}}
 4             <tr>
 5                 <td>{{$value.name}}</td>
 6                 <td>{{$value.slug}}</td>
 7                 <td class="text-center">
 8                     <!-- 加入自定义属性 用于存储数据,为编辑所需的数据做准备 -->
 9                     <a href="javascript:void(0)" data-toggle="modal" class="btn btn-info btn-xs btnedit" data-id="{{$value.id}}" data-name="{{$value.name}}" data-slug="{{$value.slug}}">编辑</a>
10                     <a href="javascript:void(0)" class="btn btn-danger btn-xs btndel" data-id="{{$value.id}}">删除</a>
11                 </td>
12             </tr>
13         {{/each}}
14     </script>

 

动态渲染文章类别

 // 5、所有文章类别
    // 请求地址:/admin/category / list
    // 请求方式:get
    let paradata = []
    let id //设置全局变量 用于获取当前编辑的分类数据的id
    function init() {
        $.ajax({
            url: allSite.category_list,
            dataType: 'json',
            success: function (res) {
                // console.log(res);
                if (res.code == 200) {
                    paradata = res.data
                    $('tbody').html(template('cataTemp', res))
                }
            }
        })
    }
    init()

 

文章类别的新增

这里因为新增文章类别的信息特别的少,所以没有必要去做一个新页面来做新增,而可以选择使用 模态框  或者  在页面的某个位置单独的划出一块区域进行新增操作

模态框的添加

模态框的弹出

  • 可以使用js的方式--最终选择它来实现

  • 也可以为按钮设置属性:data-toggle data-target

 1 <!-- 模态框的添加 -->
 2     <div class="modal fade" tabindex="-1" role="dialog" id="myModal">
 3         <div class="modal-dialog" role="document">
 4             <div class="modal-content">
 5                 <div class="modal-header">
 6                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
 7                             aria-hidden="true">&times;</span></button>
 8                     <h4 class="modal-title">新增分类</h4>
 9                 </div>
10                 <div class="modal-body">
11                     <form action="" id="form">
12                         <div class="form-group">
13                             <label for="name">分类名称</label>
14                             <input type="text" class="form-control" id="name" name="name" placeholder="分类名称">
15                         </div>
16                         <div class="form-group">
17                             <label for="slug">分类别名</label>
18                             <input type="text" class="form-control" id="slug" name="slug" placeholder="分类别名">
19                         </div>
20                     </form>
21                 </div>
22                 <div class="modal-footer">
23                     <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
24                     <button type="button" class="btn btn-primary btnset">新增</button>
25                 </div>
26             </div>
27         </div>
28     </div>

 

这里需要注意 因为后台的数据对每个文章分类设置的唯一值 即每个文章分类都不能重复

实现用户数据的输入验证

验证用户输入是否重复了

  • 获取到当前的所有分类数据

  • 在用户输入失焦的时候验证用户是否存在,生成一个标记

    • 根据标记决定是否发起新增请求

思路

  • 在查询到所有的分类数据之后,将分类数据存储到变量,供后期的判断使用

  • 在每次用户输入完值之后,使用之前存储的分类数据做为参照,查询当前用户的输入是否已存在

  • 在每次判断后,设置一个标记,标记当前用户输入的值是否已存在。这个标记就是我们后期是否进行后台请求的标记

 1 //验证用户输入
 2     let flag = true  //标记当前请求是否要发送
 3     $('#name').on('blur', function () {
 4         let value = $(this).val()
 5         let temp = paradata.filter(v => {
 6             return v.name == value
 7         })[0]
 8         if (temp) {
 9             alert('分类名称重复,请重新输入')
10             flag = false
11         } else {
12             flag = true
13         }
14     })
15     $('#slug').on('blur', function () {
16         let value = $(this).val()
17         let temp = paradata.filter(v => {
18             return v.slug == value
19         })[0]
20         if (temp) {
21             alert('分类别名重复,请重新输入')
22             flag = false
23         } else {
24             flag = true
25         }
26     })

实现添加的功能

  • 如果获取的数据有文件类型的数据,那么一般使用formdata

  • 如果只是普通的键值对那么就使用serialize

  • 一个细节:name和slug都是唯一键不能重复

类别的编辑

编辑都需要完成两个功能

1.数据的默认展示

2.编辑功能

数据的默认展示

  • 如果是单独的页面实现编辑,那么就需要传递参数,获取参数,查询数据,默认展示

    • 页面跳转是get请求,get无法传递太多的数据,且传递数据的方式不安全

    • 所以这种情况下一般传递id,到编辑页面进行数据的查询,再展示

  • 如果是当前页面实现编辑操作(弹框,单独区域),一般来说编辑的数据比较的简单

    • 由于没有跳转页面,那么意味着本质上没有必须进行参数的传递

    • 所以一般情况下这种场景可以先存储数据,再获取数据进行展示

    • 如果没有特别的需要,可以考虑使用自定义属性

添加自定义属性的设置

          <td class="text-center">
                    <!-- 加入自定义属性 用于存储数据,为编辑所需的数据做准备 -->
                    <a href="javascript:void(0)" data-toggle="modal" class="btn btn-info btn-xs btnedit" data-id="{{$value.id}}" data-name="{{$value.name}}" data-slug="{{$value.slug}}">编辑</a>
                    <a href="javascript:void(0)" class="btn btn-danger btn-xs btndel" data-id="{{$value.id}}">删除</a>
                </td>

 

 在编辑事件中获取自定义属性,实现展示. 注意: 因为文章类别是使用模板结构动态渲染的, 要使用事件委托的方式来触发事件, 获取自定义属性 , 弹出模态框 ,wei元素赋值

编辑分类

  • 编辑和新增是复用同一个模态框

  • 编辑过后的新增,需要将数据,提示信息重置
  • 可以根据文本内容或者id进行判断,决定是进行编辑还是新增

  • 编辑和新增的业务是一样,可以进行业务的封装

类别的删除

给按钮绑定事件

一下是全部实现的代码

  1 $(function () {
  2     // 5、所有文章类别
  3     // 请求地址:/admin/category / list
  4     // 请求方式:get
  5     let paradata = []
  6     let id //设置全局变量 用于获取当前编辑的分类数据的id
  7     function init() {
  8         $.ajax({
  9             url: allSite.category_list,
 10             dataType: 'json',
 11             success: function (res) {
 12                 // console.log(res);
 13                 if (res.code == 200) {
 14                     paradata = res.data
 15                     $('tbody').html(template('cataTemp', res))
 16                 }
 17             }
 18         })
 19     }
 20     init()
 21 
 22     //验证用户输入
 23     let flag = true  //标记当前请求是否要发送
 24     $('#name').on('blur', function () {
 25         let value = $(this).val()
 26         let temp = paradata.filter(v => {
 27             return v.name == value
 28         })[0]
 29         if (temp) {
 30             alert('分类名称重复,请重新输入')
 31             flag = false
 32         } else {
 33             flag = true
 34         }
 35     })
 36     $('#slug').on('blur', function () {
 37         let value = $(this).val()
 38         let temp = paradata.filter(v => {
 39             return v.slug == value
 40         })[0]
 41         if (temp) {
 42             alert('分类别名重复,请重新输入')
 43             flag = false
 44         } else {
 45             flag = true
 46         }
 47     })
 48     // 6、新增文章类别
 49     // 请求地址:/admin/category / add
 50     // 请求方式:post
 51 
 52     //封装函数  因为新增功能 和 编辑功能 都需要重新渲染页面数据 ,可以用函数封装,再传递参数
 53     function operate(url, data) {
 54         $.ajax({
 55             //ajax支持三种格式的参数传递 
 56             url: url,
 57             dataType: 'json',
 58             data: data,
 59             type: 'post',
 60             success: function (res) {
 61                 // console.log(res);
 62                 if (res.code == 201 || res.code == 200) {
 63                     alert(res.msg)
 64                     $('#myModal').modal('hide')
 65                     init()
 66                 }
 67             }
 68         })
 69     }
 70 
 71 
 72 
 73     //点击新增按钮弹出模态框
 74     $('#xinzengfenlei').on('click', function () {
 75         //因为新增功能和编辑功能是共用一个模态框,所有模态框的值需要动态渲染,点击不同功能显示不同的文本信息
 76         //新增的提示信息
 77         $('.modal-title').text('新增分类')
 78         $('.btnset').text('新增')
 79         //弹出模态框
 80         $('#myModal').modal('show')
 81         //新增功能的输入框内容为空
 82         $('#name').val('')
 83         $('#slug').val('')
 84     })
 85 
 86     //编辑功能时模态框展示的数据
 87     $('tbody').on('click', '.btnedit', function () {
 88         //获取自定义的属性
 89         let obj = $(this).data()
 90         // console.log(obj);
 91         //修改模态框提示信息
 92         $('.modal-title').text('编辑分类')
 93         $('.btnset').text('编辑')
 94         //弹出模态框
 95         $('#myModal').modal('show')
 96         //编辑功能的默认值
 97         id = obj.id
 98         $('#name').val(obj.name)
 99         $('#slug').val(obj.slug)
100     })
101 
102     //这是点击模态框确认键的触发的事件
103     $('.btnset').on('click', function () {
104         if (flag = false) {
105             return
106         }
107         let obj = $('#form').serialize()
108         // console.log(obj);
109         if ($(this).text() == '新增') {
110             operate(allSite.category_add, obj)
111         } else if ($(this).text() == '编辑') {
112             operate(allSite.category_edit, obj + '&id=' + id)
113         }
114     })
115 
116     //删除文章分类
117     // 9、删除文章类别
118     // 请求地址:/admin/category / delete
119     // 请求方式:post
120 
121     //使用模态引擎动态生成的结构需要使用事件委托来触发事件
122     $('tbody').on('click', '.btndel', function () {
123         let id = $(this).data().id
124         // console.log(id);
125         $.ajax({
126             url: allSite.category_delete,
127             type: 'post',
128             dataType: 'json',
129             data: { id },
130             success: function (res) {
131                 // console.log(res);
132                 if (res.code == 204) {
133                     alert(res.msg)
134                     init()
135                 } else {
136                     alert(res.msg)
137                 }
138             }
139         })
140     })
141 
142 })

评论管理页面

评论列表的渲染

模板结构

 1 <!-- 模板结构  -->
 2   <script type="text/template" id="comTemp">
 3     {{each data}}
 4       <tr>
 5         <td>{{$value.author}}</td>
 6         <td>{{$value.content}}</td>
 7         <td>{{$value.title}}</td>
 8         <td>{{$value.date}}</td>
 9         <td>{{$value.state}}</td>
10         <td class="text-center">
11           {{if $value.state == '待审核'}}
12           <a href="#" class="btn btn-success btn-xs btnRatify" data-id="{{$value.id}}">批准</a>
13           {{else if $value.state == '已通过'}}
14           <a href="#" class="btn btn-warning btn-xs btnReject" data-id="{{$value.id}}">拒绝</a>
15           {{/if}}
16           <a href="#" class="btn btn-danger btn-xs btnDel" data-id="{{$value.id}}">删除</a>
17         </td>
18       </tr>
19     {{/each}}
20   </script>

 

评论动态渲染

评论列表的分页

添加方式跟上面一致

评论数据的操作

实现 批准 拒绝 删除  等功能

实现的全部代码

  1 $(function () {
  2 
  3     //动态渲染评论数据
  4     // 19、文章评论搜索
  5     // 请求地址:/admin/comment / search
  6     // 请求方式:get
  7     let page = 1, perpage = 10
  8     function init() {
  9         $.ajax({
 10             url: allSite.comment_search,
 11             dataType: 'json',
 12             data: {
 13                 page,
 14                 perpage
 15             },
 16             success: function (res) {
 17                 // console.log(res);
 18                 if (res.code == 200) {
 19                     $('tbody').html(template('comTemp', res.data))
 20                     //给分页函数传参 生成分页结构
 21                     setPage(res.data.totalPage)
 22                 }
 23             }
 24         })
 25     }
 26     init()
 27 
 28     //添加分页插件
 29     //实现分页结构的显示
 30     /**
 31      *
 32      * @param pageCurrent 当前所在页
 33      * @param pageSum 总页数
 34      * @param callback 调用ajax
 35      */
 36     function setPage(pageSum) {
 37         $("#pagination").bootstrapPaginator({
 38             //设置版本号
 39             bootstrapMajorVersion: 3,
 40             // 显示第几页
 41             currentPage: page,
 42             // 总页数
 43             totalPages: pageSum,
 44             //当单击操作按钮的时候, 执行该函数, 调用ajax渲染页面
 45             onPageClicked: function (event, originalEvent, type, getpage) {
 46                 // getpage 为第四个参数,获取用户点击的页码数
 47                 // console.log(getpage);
 48                 //获取的页码赋值给全局变量
 49                 page = getpage;
 50                 // 再重新渲染页面,跳转到对应页数
 51                 init()
 52             }
 53         })
 54     }
 55 
 56     //批准 拒绝 删除 评论的操作 封装函数
 57     function comopt(id, url) {
 58         $.ajax({
 59             url: url,
 60             type: 'post',
 61             dataType: 'json',
 62             data: { id },
 63             success: function (res) {
 64                 // console.log(res);
 65                 if (res.code == 200) {
 66                     alert(res.msg)
 67                     init();
 68                 }
 69             }
 70         })
 71     }
 72     //点击批准 实现审核通过
 73     // 20、评论审核通过
 74     // 请求地址:/admin/comment / pass
 75     // 请求方式:post
 76     $('tbody').on('click', '.btnRatify', function () {
 77         let id = $(this).data().id
 78         // console.log(id);
 79         comopt(id, allSite.comment_pass)
 80     })
 81 
 82     //点击拒绝 实现审核不通过
 83     // 21、评论审核不通过
 84     // 请求地址:/admin/comment / reject
 85     // 请求方式:post
 86     $('tbody').on('click', '.btnReject', function () {
 87         let id = $(this).data().id
 88         // console.log(id);
 89         comopt(id, allSite.comment_reject)
 90     })
 91 
 92     //点击删除 删除评论数据
 93     // 22、删除评论
 94     // 请求地址:/admin/comment / delete
 95     // 请求方式:post
 96 
 97     $('tbody').on('click', '.btnDel', function () {
 98         let id = $(this).data().id
 99         console.log(id);
100         if ($('tbody').find('tr').length == 1) {
101             if (page > 1) {
102                 page--
103             }
104         }
105         comopt(id, allSite.comment_delete)
106         
107     })
108 })

 

个人中心页面

动态渲染默认数据  实现编辑个人信息的功能

 1 $(function () {
 2     //当页面一加载就开始渲染页面
 3     //渲染个人中心页
 4     function init() {
 5         $.ajax({
 6             // 请求地址:/ admin / user / detail
 7             // 请求方式:get
 8             // 请求参数:无
 9             url: allSite.user_detail,
10             dataType: 'json',
11             success: function (res) {
12                 console.log(res);
13                 for (let key in res.data) {
14                     $('input.' + key).val(res.data[key])
15                 }
16                 $('.col-sm-10>.user_pic').attr('src', res.data.userPic)
17             }
18         })
19     }
20     init()
21 
22     //实现个人中心页用户上传图片预览功能
23     $('#exampleInputFile').change(function () {
24         //1.2 获取用户选择的图片
25         // var file = this.files[0];    两种方式都可以获取
26         let file = $(this)[0].files[0]  //两种方式都可以获取
27         //1.3 将文件转为src路径
28         let url = URL.createObjectURL(file);
29         //1.4 将url路径赋值给img标签的src
30         $('.user_pic').attr('src', url);
31     });
32 
33 
34     //实现个人中心页的用户编辑 点击页面修改上传修改信息
35     // 4、编辑用户信息
36     // 请求地址:/admin/user / edit
37     // 请求方式:post
38     // 请求数据:使用formData提交
39     // 当前页面所在的窗口window对象是user.html, 如果想要获取父窗口,则需要使用window.parent,这种用法一般用于获取iframe标签的父窗口。
40     //submit 上传事件
41     $('form').on('submit', function (e) {
42         e.preventDefault();
43         $.ajax({
44             url: allSite.user_edit,
45             data: new FormData(this),
46             type: 'post',
47             dataType: 'json',
48             contentType: false,
49             processData: false,
50             success: function (res) {
51                 console.log(res);
52                 // console.log(window);
53                 if (res.code == 200) {
54                     // window.parent.location.reload()
55                     alert('修改成功')
56                     window.parent.location.reload()
57                 }
58             }
59         })
60     })
61 })

 

posted @ 2020-12-12 21:01  南城北斋  阅读(2891)  评论(0编辑  收藏  举报