免费建立一个个人网站,网站建设便宜,网站没有icp备案,网站平台建设实训总结黑马程序员视频地址#xff1a;
黑马程序员——数据管理平台 前言 功能#xff1a; 1.登录和权限判断 2.查看文章内容列表#xff08;筛选#xff0c;分页#xff09; 3.编辑文章#xff08;数据回显#xff09; 4.删除文章 5.发布文章#xff08;图片上传#xff0…黑马程序员视频地址
黑马程序员——数据管理平台 前言 功能 1.登录和权限判断 2.查看文章内容列表筛选分页 3.编辑文章数据回显 4.删除文章 5.发布文章图片上传富文本编辑器 技术 1.基于Bootstrap 搭建网站标签和样式 2.集成wangEditor 插件实现富文本编辑器 3.使用原生JS 完成增删改查等业务 4.基于axios 与黑马头条线上接口交互 5.使用axios 拦截器进行权限判断 项目准备 准备配套的素材代码 包含htmlcssjs静态图片第三方插件等等 数据管理平台模板代码.zip文件大小13.5 M|https://user-a001.lanzouv.com/ijtSu2mp9i9ghttps://user-a001.lanzouv.com/ijtSu2mp9i9ghttps://user-a001.lanzouv.com/ijtSu2mp9i9ghttps://user-a001.lanzouv.com/ijtSu2mp9i9ghttps://user-a001.lanzouv.com/ijtSu2mp9i9ghttps://user-a001.lanzouv.com/ijtSu2mp9i9ghttps://user-a001.lanzouv.com/ijtSu2mp9i9g 接口文档 欢迎使用 - B站-AJAX和黑马头条-数据管理平台 目录管理 • assets资源文件夹图片字体等 • lib资料文件夹第三方插件例如form-serialize • page页面文件夹 • utils实用程序文件夹工具插件 验证码登录 1.在utils/request.js中配置基地址 // axios 公共配置
// 基地址
axios.defaults.baseURL http://geek.itheima.net 2.登录按钮代码 document.querySelector(.btn).addEventListener(click, () {const form document.querySelector(.login-form)const data serialize(form, {hash: true, empty: true})axios({url: /v1_0/authorizations,method: POST,data}).then(result {myAlert(true, 登录成功)}).catch(error {myAlert(false, error.response.data.message)})
}) token
token 的介绍 token 的使用 1. 在utils/auth.js 中判断无 token 令牌字符串则强制跳转到登录页手动修改地址栏测试 /*** 目标1访问权限控制* 1.1 判断无 token 令牌字符串则强制跳转到登录页* 1.2 登录成功后保存 token 令牌字符串到本地并跳转到内容列表页面*/
const token localStorage.getItem(token)
if(!token)
{alert(请先登录)setTimeout(() {location.href ../login/index.html}, 1500)
} 2. 在登录成功后保存token 令牌字符串到本地再跳转到首页手动修改地址栏测试 then(result {//存入tokenlocalStorage.setItem(token, result.data.data.token)//提示框myAlert(true, 登录成功)//1.5s后跳转新页面setTimeout(() {location.href ../content/index.html}, 1500)}) axios 请求拦截器和个人信息设置 1. 什么是axios 请求拦截器 ✓ 发起请求之前调用的一个函数对请求参数进行设置 2. axios 请求拦截器什么时候使用 ✓ 有公共配置和设置时统一设置在请求拦截器中 官方文档 拦截器 | Axios中文文档 | Axios中文网https://www.axios-http.cn/docs/interceptorshttps://www.axios-http.cn/docs/interceptorshttps://www.axios-http.cn/docs/interceptorshttps://www.axios-http.cn/docs/interceptorshttps://www.axios-http.cn/docs/interceptorshttps://www.axios-http.cn/docs/interceptorshttps://www.axios-http.cn/docs/interceptors 1.在utils/request.js文件中配置 // 添加请求拦截器
axios.interceptors.request.use(function (config) {// 在发送请求之前做些什么const token localStorage.getItem(token)token (config.headers.Authorization Bearer ${token})return config
}, function (error) {// 对请求错误做些什么return Promise.reject(error);
}) 2.在utils/auth.js 中请求个人信息并设置到页面 /*** 目标2设置个人信息* 2.1 在 utils/request.js 设置请求拦截器统一携带 token* 2.2 请求个人信息并设置到页面*/
axios({url: /v1_0/user/profile
}).then(result {const username result.data.data.namedocument.querySelector(.nick-name).innerText username
}).catch(error {console.log(error)
}) axios 响应拦截器和身份验证失败 1. 什么是axios 响应拦截器 ✓ 响应回到then/catch 之前触发的拦截函数对响应结果统一处理 2. axios 响应拦截器什么时候触发成功/失败的回调函数 ✓ 状态为2xx触发成功回调其他则触发失败的回调函数 // 添加响应拦截器
axios.interceptors.response.use(function (response) {// 2xx 范围内的状态码都会触发该函数。// 对响应数据做点什么response response.data //⭐️数据优化得到的response是服务器数据axios修饰后的代码//而response.data是服务器返回的数据将服务器返回的数据直接返回给then中//如上文代码中的result.data.data.name如果此处返回response则调用result.data.data.name//如果此处返回response.data则调用result.data.namereturn response //⭐️response会传进.then(result {})中由result接收
}, function (error) {// 超出 2xx 范围的状态码都会触发该函数。// 对响应错误做点什么⭐️if(error?.response?.status 401){alert(身份验证过期请重新登录)localStorage.clear()location.href ../login/index.html}return Promise.reject(error) //⭐️error会传进.catch(error {})中由error接收
}) 发布文章
富文本编辑器 官方手册 wangEditor 5https://www.wangeditor.com/v5/getting-started.htmlhttps://www.wangeditor.com/v5/getting-started.htmlhttps://www.wangeditor.com/v5/getting-started.htmlhttps://www.wangeditor.com/v5/getting-started.htmlhttps://www.wangeditor.com/v5/getting-started.htmlhttps://www.wangeditor.com/v5/getting-started.htmlhttps://www.wangeditor.com/v5/getting-started.html手册中有完整步骤 1.引入CSS在相应页面publish/index.css引入CSS /* 富文本编辑器 */
#editor—wrapper {border: 1px solid #ccc;z-index: 100; /* 按需定义 */}#toolbar-container {border-bottom: 1px solid #ccc;}#editor-container {height: 500px;} 2.定义HTML在需要部署的页面publish/index.html放置HTML代码 !-- 富文本编辑器位置 --
div ideditor—wrapperdiv idtoolbar-container!-- 工具栏 --/divdiv ideditor-container!-- 编辑器 --/div
/div
!-- 记录富文本内容-用于表单收集 --
textarea namecontent classpublish-content hidden/textarea 3.引入 JS 创建编辑器在utils/editor.js中放入代码 // 富文本编辑器
// 创建编辑器函数创建工具栏函数
const { createEditor, createToolbar } window.wangEditor// 编辑器配置对象
const editorConfig {// 占位提示文字placeholder: 发布文章内容...,// 编辑器变化时回调函数onChange(editor) {// 获取富文本内容const html editor.getHtml()// 也可以同步到 textarea// 为了后续快速收集整个表单内容做铺垫document.querySelector(.publish-content).value html}
}// 创建编辑器
const editor createEditor({// 创建位置selector: #editor-container,// 默认内容html: pbr/p,// 配置项config: editorConfig,// 配置集成模式default 全部simple 简洁mode: default, // or simple
})// 工具栏配置对象
const toolbarConfig {}// 创建工具栏
const toolbar createToolbar({// 为指定编辑器创建工具栏editor,// 工具栏创建的位置selector: #toolbar-container,// 工具栏配置对象config: toolbarConfig,// 配置集成模式mode: default, // or simple
}) 4.引入文件在publish/index.html中引入script黑马程序员已经帮我们引入过了 !--引入 CSS 定义样式--
linkhrefhttps://unpkg.com/wangeditor/editorlatest/dist/css/style.cssrelstylesheet
/!--引入 JS 创建编辑器--
script srchttps://unpkg.com/wangeditor/editorlatest/dist/index.js/script 频道列表 目标1设置频道下拉菜单 1.1 获取频道列表数据 1.2 展示到下拉菜单中 //publish/index.jsasync function getChannels()
{//请求数据const channelsData await axios({url: /v1_0/channels})//拼接数据const channelsHTML option value selected请选择文章频道/option channelsData.data.data.channels.map(item option value${item.id} ${item.name}/option).join()//渲染数据document.querySelector(.form-select).innerHTML channelsHTML
}
getChannels() 封面设置 目标2文章封面设置 2.1 准备标签结构和样式 2.2 选择文件并保存在 FormData 2.3 单独上传图片并得到图片 URL 网址 2.4 回显并切换 img 标签展示隐藏 号上传标签 document.querySelector(.img-file).addEventListener(change, async e {//获取本地上传照片数据const file e.target.files[0]//实例化表单对象const fd new FormData()//添加image属性并放入图片数据fd.append(image, file)//上传数据返回照片地址const res await axios({url: /v1_0/upload,method: POST,data: fd})const imgUrl res.data.data.url//渲染到本地document.querySelector(.rounded).src imgUrl //照片回显document.querySelector(.rounded).classList.add(show) //显示照片盒子document.querySelector(.place).classList.add(hide) //隐藏加号盒子
})//⭐️点击图片模拟点击上传图片按钮从而再次调用代码
document.querySelector(.rounded).addEventListener(click, () {document.querySelector(.img-file).click()
}) 收集并保存 目标3发布文章保存 3.1 基于 form-serialize 插件收集表单数据对象 3.2 基于 axios 提交到服务器保存 3.3 调用 Alert 警告框反馈结果给用户 3.4 重置表单并跳转到列表页 document.querySelector(.send).addEventListener(click, async e {//⭐️编辑功能留空1//获取表单const form document.querySelector(.art-form)//获取表单数据const data serialize(form, {hash: true, empty: true})//⭐️删除id字段数据delete data.id//获取图片数据data.cover {type: 1, images: [document.querySelector(.rounded).src]}//上传数据try{const result await axios({url: /v1_0/mp/articles,method: POST, data})//调用 Alert 警告框反馈结果给用户myAlert(true, 发布成功)//清除表单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){//调用 Alert 警告框反馈结果给用户myAlert(false, error.response.data.message)}}) 内容管理
文章列表展示 目标1获取文章列表并展示 1.1 准备查询参数对象 1.2 获取文章列表数据 1.3 展示到指定的标签结构中 标⭐️为代码留空区域在对应功能模块编写时会添加 // 1.准备查询参数对象
const queryObj {status: , // 文章状态1-待审核2-审核通过空字符串-全部channel_id: , // 文章频道 id空字符串-全部page: 1, // 当前页码per_page: 10 // 当前页面条数
}//⭐️分页功能留空1async function getArtileList() {//2.获取文章列表数据const res await axios({url: /v1_0/mp/articles,params: queryObj})//3.展示到指定的标签结构中const htmlStr res.data.data.results.map(item trtdimg src${item.cover.type 0 ? https://img2.baidu.com/it/u2640406343,1419332367amp;fm253amp;fmtautoamp;app138amp;fJPEG?w708amp;h500: item.cover.images[0]} alt/tdtd${item.title}/tdtd${item.status 1 ? span classbadge text-bg-primary待审核/span : span classbadge text-bg-success审核通过/span}/tdtdspan${item.pubdate}/span/tdtdspan${item.read_count}/span/tdtdspan${item.comment_count}/span/tdtdspan${item.like_count}/span/tdtd ⭐️删除功能留空1i classbi bi-pencil-square edit/ii classbi bi-trash3 del/i/td
/tr).join()document.querySelector(.art-list).innerHTML htmlStr//⭐️分页功能留空2}
getArtileList() 筛选功能 目标2筛选文章列表 2.1 设置频道列表数据 2.2 监听筛选条件改变保存查询信息到查询参数对象 2.3 点击筛选时传递查询参数对象到服务器 2.4 获取匹配数据覆盖到页面展示 //1.设置频道列表数据
async function getChannels()
{//请求数据const channelsData await axios({url: /v1_0/channels})//拼接数据const channelsHTML option value selected请选择文章频道/option channelsData.data.data.channels.map(item option value${item.id} ${item.name}/option).join()//渲染数据document.querySelector(.form-select).innerHTML channelsHTML
}
getChannels()//2.监听筛选条件改变保存查询信息到查询参数对象
//状态
document.querySelectorAll(.form-check).forEach(item {item.addEventListener(change, e {queryObj.status e.target.value})
})//频道
document.querySelector(.form-select).addEventListener(change, e {queryObj.channel_id e.target.value
})
//3.点击筛选时传递查询参数对象到服务器,并获取匹配数据覆盖到页面展示
document.querySelector(.sel-btn).addEventListener(click, () {getArtileList()
}) 分页功能 目标3分页功能 3.1 保存并设置文章总条数 3.2 点击下一页做临界值判断并切换页码参数并请求最新数据 3.3 点击上一页做临界值判断并切换页码参数并请求最新数据 //————————————————————————1.代码写在文章列表展示中——————————————————————————————//1.1保存文章总条数对应留空1let totalCount 0 //1.2获取文章总条数对应留空2totalCount res.data.total_countdocument.querySelector(.total-count).innerHTML 共 ${totalCount} 条
//————————————————————————————————————————————————————————————————————————————//2.点击下一页
document.querySelector(.next).addEventListener(click, () {//判断是否可以进行下一页当前页码小于总页码总页码(总条数/每一页最大条数)向上取整if(queryObj.page Math.ceil(totalCount / queryObj.per_page)){ //页码自增queryObj.page //页面显示当前页码document.querySelector(.page-now).innerHTML 第 ${queryObj.page} 页 //更新数据getArtileList() }
})//3.点击上一页
document.querySelector(.last).addEventListener(click, e {// 大于 1 的时候才能翻到上一页if (queryObj.page 1) {//页码自减queryObj.page--//页面显示当前页码document.querySelector(.page-now).innerHTML 第 ${queryObj.page} 页//更新数据getArtileList()}
}) 删除功能 目标4删除功能 4.1 关联文章 id 到删除图标 4.2 点击删除时获取文章 id 4.3 调用删除接口传递文章 id 到服务器 4.4 删除最后一页的最后一条需要自动向前翻页 4.5 重新获取文章列表并覆盖展示 //————————————————————————1.关联文章 id————————————————————————//留空1补自定义属性data-id${item.id}//——————————————————————————————————————————————————————————————————————
//2.点击删除时获取文章 id
document.querySelector(.art-list).addEventListener(click, async e {if(e.target.classList.contains(del)){//2.获取idconst delId e.target.parentNode.dataset.id//3.调用删除接口传递文章 id 到服务器const res await axios({url: /v1_0/mp/articles/${delId},method: DELETE})//4.删除最后一页的最后一条需要自动向前翻页//获取子元素数组const children document.querySelector(.art-list).children//判断子元素数组长度等于1并且当前页码数不等于1if(children.length 1 queryObj.page ! 1){//页码自减queryObj.page--//页面显示当前页码document.querySelector(.page-now).innerHTML 第 ${queryObj.page} 页}//5.重新获取并渲染数据getArtileList()}
}) 编辑功能
回显文章 目标4编辑-回显文章 4.1 页面跳转传参URL 查询参数方式 4.2 发布文章页面接收参数判断共用同一套表单 4.3 修改标题和按钮文字 4.4 获取文章详情数据并回显表单 //content/index.js//1.点击编辑时获取文章 id跳转到发布文章页面传递文章 id 过去
document.querySelector(.art-list).addEventListener(click, e {//判断是否点击编辑按钮if(e.target.classList.contains(edit)){//获取idconst editId e.target.parentNode.dataset.id//跳转到发布页面并传递idlocation.href ../publish/index.html?id${editId}}})
//publish/index.js
//使用立即执行函数(IIFE)创建一个独立的作用域避免变量污染全局作用域
;(function(){//⭐️获取网页中携带的参数const paramsStr location.search//⭐️实例化内置对象用来处理?后面内容的对象const params new URLSearchParams(paramsStr)params.forEach(async (value, key) {//判断是否含有id参数if(key id){//修改页面文字document.querySelector(.title span).innerHTML 修改文章document.querySelector(.send).innerHTML 修改//获取文章详情const res await axios({url: /v1_0/mp/articles/${value}})//整理需要用的值//方法一解构// const {channel_id, title, cover:{images:[image]}, content, id} res.data.data//方法二创立新对象挨个赋值本篇选择此方法const dataObj {channel_id: res.data.data.channel_id,title: res.data.data.title,image: res.data.data.cover.images[0],content: res.data.data.content,id: res.data.data.id}console.log(dataObj)//数据渲染Object.keys(dataObj).forEach(key {if(key image){document.querySelector(.rounded).src dataObj[key] //照片回显document.querySelector(.rounded).classList.add(show) //显示照片盒子document.querySelector(.place).classList.add(hide) //隐藏加号盒子}else if(key content){//设置富文本编辑框内容editor.setHtml(dataObj[key])}else{//利用name选择器赋值document.querySelector([name${key}]).value dataObj[key]}}) }})
})(); 保存文章 目标5编辑-保存文章 5.1 判断按钮文字区分业务因为共用一套表单 5.2 调用编辑文章接口保存信息到服务器 5.3 基于 Alert 反馈结果消息给用户 //区分发布按钮与修改按钮
//——————————————————————发布文章/收集并保存中的留空1代码————————————————————————————//判断是否为发布按钮if(e.target.innerHTML ! 发布) return
//————————————————————————————————————————————————————————————————————————————————
document.querySelector(.send).addEventListener(click, async e {//判断是否为修改按钮if(e.target.innerHTML ! 修改) return//获取表单对象const form document.querySelector(.art-form)//使用serialize插件获取表单数据const data serialize(form, {hash: true, empty: true})//提交数据try{const res await axios({url: /v1_0/mp/articles/${data.id},method: PUT,data:{...data,cover:{type: document.querySelector(.rounded).src ? 1 : 0,images: [document.querySelector(.rounded).src]}}})//成功弹窗myAlert(true, 修改成功)//返回内容管理页面setTimeout(() {location.href ../content/index.html}, 1500)}catch(error){//异常弹窗myAlert(false, error.response.data.message)}
}) 退出登录 目标3退出登录 3.1 绑定点击事件 3.2 清空本地缓存跳转到登录页面 //utils/auth.js//绑定事件
document.querySelector(.quit).addEventListener(click, () {//清空本地缓存localStorage.clear()//提示框myAlert(true, 退出成功即将返回登陆页面)//跳转登录页面setTimeout(() {location.href ../login/index.html}, 1500)
}) 文章转载自: http://www.morning.xltwg.cn.gov.cn.xltwg.cn http://www.morning.hdrrk.cn.gov.cn.hdrrk.cn http://www.morning.pszw.cn.gov.cn.pszw.cn http://www.morning.bpptt.cn.gov.cn.bpptt.cn http://www.morning.bxyzr.cn.gov.cn.bxyzr.cn http://www.morning.kwdfn.cn.gov.cn.kwdfn.cn http://www.morning.tsflw.cn.gov.cn.tsflw.cn http://www.morning.ndpwg.cn.gov.cn.ndpwg.cn http://www.morning.smdkk.cn.gov.cn.smdkk.cn http://www.morning.jpnfm.cn.gov.cn.jpnfm.cn http://www.morning.tqpr.cn.gov.cn.tqpr.cn http://www.morning.wyjpt.cn.gov.cn.wyjpt.cn http://www.morning.wkkqw.cn.gov.cn.wkkqw.cn http://www.morning.pqkgb.cn.gov.cn.pqkgb.cn http://www.morning.wrwcf.cn.gov.cn.wrwcf.cn http://www.morning.qpnmd.cn.gov.cn.qpnmd.cn http://www.morning.rwmp.cn.gov.cn.rwmp.cn http://www.morning.fycjx.cn.gov.cn.fycjx.cn http://www.morning.jlxld.cn.gov.cn.jlxld.cn http://www.morning.cjxqx.cn.gov.cn.cjxqx.cn http://www.morning.lzrpy.cn.gov.cn.lzrpy.cn http://www.morning.cbmqq.cn.gov.cn.cbmqq.cn http://www.morning.dxsyp.cn.gov.cn.dxsyp.cn http://www.morning.dfkby.cn.gov.cn.dfkby.cn http://www.morning.fbbpj.cn.gov.cn.fbbpj.cn http://www.morning.fcpjq.cn.gov.cn.fcpjq.cn http://www.morning.yxnfd.cn.gov.cn.yxnfd.cn http://www.morning.sfsjh.cn.gov.cn.sfsjh.cn http://www.morning.lgsqy.cn.gov.cn.lgsqy.cn http://www.morning.smxrx.cn.gov.cn.smxrx.cn http://www.morning.wcgfy.cn.gov.cn.wcgfy.cn http://www.morning.xhsxj.cn.gov.cn.xhsxj.cn http://www.morning.zcxjg.cn.gov.cn.zcxjg.cn http://www.morning.rqwwm.cn.gov.cn.rqwwm.cn http://www.morning.gxcym.cn.gov.cn.gxcym.cn http://www.morning.tqwcm.cn.gov.cn.tqwcm.cn http://www.morning.pjtw.cn.gov.cn.pjtw.cn http://www.morning.sloxdub.cn.gov.cn.sloxdub.cn http://www.morning.znpyw.cn.gov.cn.znpyw.cn http://www.morning.gbnsq.cn.gov.cn.gbnsq.cn http://www.morning.wjlhp.cn.gov.cn.wjlhp.cn http://www.morning.bfbl.cn.gov.cn.bfbl.cn http://www.morning.ydryk.cn.gov.cn.ydryk.cn http://www.morning.pljxz.cn.gov.cn.pljxz.cn http://www.morning.flxqm.cn.gov.cn.flxqm.cn http://www.morning.kpzrf.cn.gov.cn.kpzrf.cn http://www.morning.wqbhx.cn.gov.cn.wqbhx.cn http://www.morning.snlxb.cn.gov.cn.snlxb.cn http://www.morning.nqgds.cn.gov.cn.nqgds.cn http://www.morning.npbgj.cn.gov.cn.npbgj.cn http://www.morning.nqgjn.cn.gov.cn.nqgjn.cn http://www.morning.kstlm.cn.gov.cn.kstlm.cn http://www.morning.kpnpd.cn.gov.cn.kpnpd.cn http://www.morning.grzpc.cn.gov.cn.grzpc.cn http://www.morning.nzdks.cn.gov.cn.nzdks.cn http://www.morning.lmmyl.cn.gov.cn.lmmyl.cn http://www.morning.ckwrn.cn.gov.cn.ckwrn.cn http://www.morning.qichetc.com.gov.cn.qichetc.com http://www.morning.tsqpd.cn.gov.cn.tsqpd.cn http://www.morning.qczpf.cn.gov.cn.qczpf.cn http://www.morning.fkwp.cn.gov.cn.fkwp.cn http://www.morning.sxjmz.cn.gov.cn.sxjmz.cn http://www.morning.yxwrr.cn.gov.cn.yxwrr.cn http://www.morning.krdxz.cn.gov.cn.krdxz.cn http://www.morning.fgtls.cn.gov.cn.fgtls.cn http://www.morning.tqpds.cn.gov.cn.tqpds.cn http://www.morning.ppllj.cn.gov.cn.ppllj.cn http://www.morning.pjtw.cn.gov.cn.pjtw.cn http://www.morning.cnfxr.cn.gov.cn.cnfxr.cn http://www.morning.xjqkh.cn.gov.cn.xjqkh.cn http://www.morning.yesidu.com.gov.cn.yesidu.com http://www.morning.nkyqh.cn.gov.cn.nkyqh.cn http://www.morning.wjlhp.cn.gov.cn.wjlhp.cn http://www.morning.ai-wang.cn.gov.cn.ai-wang.cn http://www.morning.lxmks.cn.gov.cn.lxmks.cn http://www.morning.hrzhg.cn.gov.cn.hrzhg.cn http://www.morning.rqnml.cn.gov.cn.rqnml.cn http://www.morning.nkqnn.cn.gov.cn.nkqnn.cn http://www.morning.ydryk.cn.gov.cn.ydryk.cn http://www.morning.dkqyg.cn.gov.cn.dkqyg.cn