5、黑马头条-数据管理平台 DAY5

to b,是一个网络流行词,即 to business,即企业创业是面向企业,为企业提供服务(如设备制造商)。

项目介绍

接口文档:https://apifox.com/apidoc/shared-1b0dd84f-faa8-435d-b355-5a8a329e34a8/

总结
  1. 黑马头条-数据管理平台,是什么样网站,要完成哪些功能?
    ✓ 数据管理网站,登录后对数据进行增删改查
  2. 数据管理平台,未登录能否管理数据?
    ✓ 不能,数据是公司内部的,需账号登录后管理

项目准备



总结
  1. 为什么要按照一定的结构,管理代码文件?
    ✓ 方便以后的查找和扩展

验证码登录

// axios 公共配置
// 基地址
axios.defaults.baseURL = 'http://geek.itheima.net'

token 的介绍

token 的使用

总结

const token = localStorage.getItem('token')
if(!token) {
    location.href = '../login/index.html'
}
/**
 * 目标2:设置个人信息
 * 2.1 在 utils/request.js 设置请求拦截器,统一携带 token
 * 2.2 请求个人信息并设置到页面
 */
// 2.2 请求个人信息并设置到页面
axios({
    url:'/v1_0/user/profile'
}).then(result => {
    // console.log(result)
    // console.log(result.data.data.name)
    const username = result.data.data.name
    // console.log(username)
    document.querySelector('.nick-name').innerHTML = username
})

个人信息设置和 axios 请求拦截器



请求拦截器:https://www.axios-http.cn/docs/interceptors

总结

axios 响应拦截器和身份验证失败

优化-axios 响应结果

发布文章-富文本编辑器

富文本:带样式,多格式的文本,在前端一般使用标签配合内联样式实现
富文本编辑器:用于编写富文本内容的容器

发布文章-富文本编辑器

目标:发布文章页,富文本编辑器的集成
使用:wangEditor 插件
步骤:参考文档

  1. 引入 CSS 定义样式
  2. 定义 HTML 结构
  3. 引入 JS 创建编辑器
  4. 监听内容改变,保存在隐藏文本域(便于后期收集)

发布文章-频道列表

目标:展示频道列表,供用户选择
步骤:
1.获取频道列表数据
2.展示到下拉菜单中

/**
 * 目标1:设置频道下拉菜单
 *  1.1 获取频道列表数据
 *  1.2 展示到下拉菜单中
 */
// 1.1 获取频道列表数据
async function setChannelList() {
    const res = await axios({
        url: '/v1_0/channels'
    })
    // console.log(res)
    const htmlStr = `<option value="" selected="">请选择文章频道</option>` + res.data.channels.map(item => `<option value="${item.id}" >${item.name}</option>`).join('')
    console.log(htmlStr)
    document.querySelector('.form-select').innerHTML = htmlStr
}
// 网页运行后,默认调用一次
setChannelList()

发布文章-封面设置


/**
 * 目标2:文章封面设置
 *  2.1 准备标签结构和样式
 *  2.2 选择文件并保存在 FormData
 *  2.3 单独上传图片并得到图片 URL 网址
 *  2.4 回显并切换 img 标签展示(隐藏 + 号上传标签)
 */
// 2.1 准备标签结构和样式
// 2.2 选择文件并保存在 FormData
document.querySelector('.img-file').addEventListener('change', async e => {
    const file = e.target.files[0]
    const fd = new FormData()
    fd.append('image',file)
    // 2.3 单独上传图片并得到图片 URL 网址
    const res =  await axios({
        url: '/v1_0/upload',
        method: 'POST',
        data: fd
    })
    console.log(res)
    // 2.4 回显并切换 img 标签展示(隐藏 + 号上传标签)
    const imgUrl = res.data.url
    document.querySelector('.rounded').src = imgUrl
    document.querySelector('.rounded').classList.add('show')
    document.querySelector('.place').classList.add('hide')
})
// 优化:点击img 可以重新切换封面
// 思路:img点击 => 用JS方式触发文件元素click事件方法
document.querySelector('.rounded').addEventListener('click', e => {
    document.querySelector('.img-file').click()
})

发布文章-收集并保存


/**
 * 目标3:发布文章保存
 *  3.1 基于 form-serialize 插件收集表单数据对象
 *  3.2 基于 axios 提交到服务器保存
 *  3.3 调用 Alert 警告框反馈结果给用户
 *  3.4 重置表单并跳转到列表页
 */
// 3.1 基于 form-serialize 插件收集表单数据对象
document.querySelector('.send').addEventListener('click', async e => {
    const form = document.querySelector('.art-form')
    const data = serialize(form,{hash: true, empty: true})
    // 发布文章的时候,不需要id属性,所以可以删除调(id为了后续做编辑使用)
    delete data.id
    console.log(data)
    // 自己收集封面图片地址并保存到data对象中
    data.cover = {
        type: 1,
        images: [document.querySelector('.rounded').src]  //封面图片URL网址
    }
    //  3.2 基于 axios 提交到服务器保存
    try {
        const res = await axios({
            url: '/v1_0/mp/articles',
            method: 'POST',
            data: data
        })
        // 3.3 调用 Alert 警告框反馈结果给用户
        // console.log(res)
        myAlert(true, '发布成功')
        // 3.4 重置表单并跳转到列表页
        form.reset()
        // 封面需要手动重置
        document.querySelector('.rounded').src = ''
        document.querySelector('.rounded').classList.remove('show')
        document.querySelector('.place').classList.remove('hide')
        // 富文本编辑器也要重置
        editor.setHtml('')

        setTimeout(() => {
            location.href ='../content/index.html'
        }, 1500)
    } catch (error) {
        myAlert(false, error.response.data.message)
    }
    
})

内容管理-文章列表展示

目标:获取文章列表并展示
步骤:
1.准备查询参数对象
2.获取文章列表数据
3.展示到指定的标签结构中
在这里插入图片描述

/**
 * 目标1:获取文章列表并展示
 *  1.1 准备查询参数对象
 *  1.2 获取文章列表数据
 *  1.3 展示到指定的标签结构中
 */
// 1.1 准备查询参数对象
const queryObj = {
    status: '', //文章状态(1-待审核, 2-审核通过)空字符串-全部
    channel_id:'',  //文章频道 id, 空字符串-全部
    page: 1,  //当前页码
    per_page: 2 //当前页面条数
}
async function setArtileList() {
    // 1.2 获取文章列表数据
    const res = await axios({
        url: '/v1_0/mp/articles',
        params: queryObj
    })
    console.log(res)
    // 1.3 展示到指定的标签结构中
    const htmlStr = res.data.results.map(item => `<tr>
    <td>
    <img src="${item.cover.type === 0?`https://img2.baidu.com/it/u=2640406343,1419332367&amp;fm=253&amp;fmt=auto&amp;app=138&amp;f=JPEG?w=708&amp;h=500"`: item.cover.images[0]}" alt="">
    </td>
    <td>${item.title}</td>
    <td>
    ${item.status === 1? `<span class="badge text-bg-success">审核通过</span>`:
    `<span class="badge text-bg-primary">待审核</span>`}
    </td>
    <td>
    <span>${item.pubdate}</span>
    </td>
    <td>
    <span>${item.read_count}</span>
    </td>
    <td>
    <span>${item.comment_count}</span>
    </td>
    <td>
    <span>${item.like_count}</span>
    </td>
    <td>
    <i class="bi bi-pencil-square edit"></i>
    <i class="bi bi-trash3 del"></i>
    </td></tr>`).join('')
    console.log(htmlStr)
    document.querySelector('.art-list').innerHTML = htmlStr
}
setArtileList()

内容管理-筛选功能

目标:根据筛选条件,获取匹配数据展示
步骤:

  1. 设置频道列表数据
  2. 监听筛选条件改变,保存查询信息到查询参数对象
  3. 点击筛选时,传递查询参数对象到服务器
  4. 获取匹配数据,覆盖到页面展示
/**
 * 目标2:筛选文章列表
 *  2.1 设置频道列表数据
 *  2.2 监听筛选条件改变,保存查询信息到查询参数对象
 *  2.3 点击筛选时,传递查询参数对象到服务器
 *  2.4 获取匹配数据,覆盖到页面展示
 */
async function setChannelList() {
    const res = await axios({
        url: '/v1_0/channels'
    })
    // console.log(res)
    const htmlStr = `<option value="" selected="">请选择文章频道</option>` + res.data.channels.map(item => `<option value="${item.id}" >${item.name}</option>`).join('')
    console.log(htmlStr)
    document.querySelector('.form-select').innerHTML = htmlStr
}
// 网页运行后,默认调用一次
setChannelList()
// 2.2 监听筛选条件改变,保存查询信息到查询参数对象
// 筛选状态标记数字 -> change事件 -> 绑定到查询参数对象上
document.querySelectorAll('.form-check-input').forEach(radio => {
    radio.addEventListener('change', e => {
        console.log(e.target.value)
        queryObj.status = e.target.value
    })
})
// 筛选状态标记数字 -> change事件 -> 绑定到查询参数对象上
document.querySelector('.form-select').addEventListener('change', e => {
    queryObj.channel_id = e.target.value
})
// 2.3 点击筛选时,传递查询参数对象到服务器
document.querySelector('.sel-btn').addEventListener('click', () => {
    setArtileList()
})

内容管理-分页功能

目标:完成文章列表,分页管理功能
步骤:
1.保存并设置文章总条数
2.点击下一页,做临界值判断,并切换页码参数请求最新数据
3.点击上一页,做临界值判断,并切换页码参数请求最新数据

/**
 * 目标3:分页功能
 *  3.1 保存并设置文章总条数
 *  3.2 点击下一页,做临界值判断,并切换页码参数并请求最新数据
 *  3.3 点击上一页,做临界值判断,并切换页码参数并请求最新数据
 */
// 3.2 点击下一页,做临界值判断,并切换页码参数并请求最新数据
document.querySelector('.next').addEventListener('click', e => {
    // 当前页码小于最大的页码数
    if (queryObj.page < Math.ceil(totalCount/queryObj.per_page)) {
        queryObj.page ++
        document.querySelector('.page-now').innerHTML = `第${queryObj.page}页`
        setArtileList()
    }
})
// 3.3 点击上一页,做临界值判断,并切换页码参数并请求最新数据
document.querySelector('.last').addEventListener('click', e => {
    // 大于1的时候,才能翻到上一页
    if (queryObj.page > 1) {
        queryObj.page --
        document.querySelector('.page-now').innerHTML = `第${queryObj.page}页`
        setArtileList()
    } 
})

内容管理-删除功能

目标:完成删除文章功能
步骤:

  1. 关联文章 id 到删除图标
  2. 点击删除时,获取文章 id
  3. 调用删除接口,传递文章 id 到服务器
  4. 重新获取文章列表,并覆盖展示

内容管理-删除最后一条

目标:在删除最后一页,最后一条时有 Bug
解决:

  1. 删除成功时,判断 DOM 元素只剩一条,让当前页码 page–
  2. 注意,当前页码为 1 时不能继续向前翻页
  3. 重新设置页码数,获取最新列表展示
/**
 * 目标4:删除功能
 *  4.1 关联文章 id 到删除图标
 *  4.2 点击删除时,获取文章 id
 *  4.3 调用删除接口,传递文章 id 到服务器
 *  4.4 重新获取文章列表,并覆盖展示
 *  4.5 删除最后一页的最后一条,需要自动向前翻页
 */

// 4.2 点击删除时,获取文章 id
document.querySelector('.art-list').addEventListener('click', async e => {
    if(e.target.classList.contains('del')){
        // console.log(1);
        const delId = e.target.parentNode.dataset.id
        // console.log(delId)
        // 4.3 调用删除接口,传递文章 id 到服务器
        const res = await axios({
            url: `/v1_0/mp/articles/${delId}`,
            method: 'DELETE'
        })
        // console.log(res)
        // 4.5 删除最后一页的最后一条,需要自动向前翻页
        const children = document.querySelector('.art-list').children 
        if (children.length === 1 && queryObj.page !== 1) {
            queryObj.page --
            document.querySelector('.page-now').innerHTML = `第${queryObj.page}页`
        }
        // 4.4 重新获取文章列表,并覆盖展示
        setArtileList()
    }
})

内容管理-编辑文章-回显

内容管理-编辑文章-保存

退出登录

目标:完成退出登录效果
步骤:

  1. 绑定点击事件
  2. 清空本地缓存,跳转到登录页面
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值