数据管理平台

数据管理平台项目

文章目录

  • 数据管理平台项目
      • 业务1-登录验证
          • 代码步骤:
      • token 技术
          • token的使用
          • 代码步骤
      • axios 请求拦截器
          • 语法
          • 代码示例
      • axios响应拦截器
      • 优化axios响应结果
      • 发布文章-富文本编辑器
      • 发布文章-频道列表
      • 发布文章-封面设置
      • 发布文章-收集并保存
      • 内容管理-文章列表展示
          • 代码示例
      • 内容管理-筛选功能
          • 代码示例
      • 内容管理-分页功能
      • 内容管理-删除功能
      • 内容管理-编辑文章
      • 内容管理-编辑-保存文章
      • 退出登录

业务1-登录验证


功能: 完成验证码登录,后端设置验证码默认为:246810

代码步骤:
  1. 在utils/request.js配置 axios 请求基地址,提取公共前缀地址,配置后axios请求时都会baseURL + url。
  2. 收集手机号码验证数据
  3. 基于axios调用验证码登录接口
  4. 使用Bootstrap的Alert警告框反馈结果给用户.

##### 业务代码
  1. 在utils/request.js配置 axios 请求基地址,提取公共前缀地址,配置后axios请求时都会baseURL + url。
// axios 公共配置
// 基地址
axios.defaults.baseURL = 'http://geek.itheima.net'
  1. 收集手机号码验证数据
document.querySelector('.btn').addEventListener('click', () => {const form = document.querySelector('.login-form')const data = serialize(form ,{hash: true, empty: true})console.log(data)
  1. 基于axios调用验证码登录接口
    // 1.3 基于 axios 调用验证码登录接口axios({url: '/v1_0/authorizations',method: 'POST',data}).then(result => {console.log(result)//  1.4 使用 Bootstrap 的 Alert 警告框反馈结果给用户// 自己封装好了一个弹框插件,直接调用即可myAlert(true,'登录成功')}).catch(error => {console.dir(error.response.data.message)myAlert(false,error.response.data.message)})
})
  1. 自己封装好的弹框插件
// 弹窗插件
// 需要先准备 alert 样式相关的 DOM
/*** BS 的 Alert 警告框函数,2秒后自动消失* @param {*} isSuccess 成功 true,失败 false* @param {*} msg 提示消息*/
function myAlert(isSuccess, msg) {const myAlert = document.querySelector('.alert')myAlert.classList.add(isSuccess ? 'alert-success' : 'alert-danger')myAlert.innerHTML = msgmyAlert.classList.add('show')setTimeout(() => {myAlert.classList.remove(isSuccess ? 'alert-success' : 'alert-danger')myAlert.innerHTML = ''myAlert.classList.remove('show')}, 2000)
}

验证码登录流程
  1. 输入手机号,点击发送验证码。
  2. 携带手机号,调用服务器发送短信验证码接口
  3. 为此手机号生成验证码,记录生成的时间,并存在服务器
  4. 服务器携带手机号,验证码调用运营商接口
  5. 运营商通过基站给指定的手机号,发送验证码短信
  6. 运营商返回结果响应给服务端发送成功
  7. 服务端在将响应的结果返回给前端
  8. 根据手机短信填入验证码
  9. 在此携带手机号,验证码,调用验证码登录接口
  10. 服务器接收手机号和验证码,与之前用户输入的的记录对比,并且判断是否在有效期内。从而得出是否能够登录成功。

token 技术


token(访问权限的令牌),本质上是一串字符串

创建: 在正确的登录后,由后端签发并返回。

作用:判断是否有登录状态,控制访问权限。


token的使用

在登录状态时,是否能够访问内容页面

目标1:访问权限控制

代码步骤
  1. 判断无 token 令牌字符串,则强制跳转到登录页·
const token = localStorage.getItem('token')
if(!token) {location.href = '../login/index.html'
}

  1. 登录成功后,保存 token 令牌字符串到本地,并跳转到内容列表页面
localStorage.setItem('token',result.data.data.token)

然后通过令牌跳转页面

// 延迟时间跳转,停留提示后
setTimeout(() => {
// 登录成功能够通过令牌权限后,进行跳转到内容页location.href = '../content/index.html'},1500)

axios 请求拦截器


axios请求拦截器:在发起请求之前,触发的配置函数,对请求参数进行额外的配置。

语法

问题:很多接口都需要携带 token 令牌字符串。

解决:在请求拦截器统一设置公共样式headers选项。

axios({//因为我们给axios配置了基地址url: '目标资源路径',headers: {Authorization:`Bearer${localStorage.getItem('token')}`}
})

代码示例
// 添加请求拦截器
axios.interceptors.request.use(function (config) {// 在发送请求之前做些什么// 统一携带  token  令牌字符串在请求头上const token = localStorage.getItem('token')// 本地有token的话,则在配置对象中配置token令牌权限token && (config.headers.Authorization = `Bearer ${token}`)return config;}, function (error) {// 对请求错误做些什么return Promise.reject(error);}); 

axios响应拦截器


axios 响应拦截器:响应回到then / catch之前, 触发的拦截函数,对响应结果统一处理


例如身份验证失败,统一做出判断并处理(身份验证失败,我们就直接就将关闭权限)


// 添加响应拦截器
axios.interceptors.response.use(function (response) {// 2xx 范围内的状态码都会触发该函数。// 对响应数据做点什么return response;
}, function (error) {// 超出 2xx 范围的状态码都会触发该函数。// 对响应错误做点什么,例如401 身份验证失败情况做出处理console.dir(error)if (error?.response?.status === 401) {alert('身份验证失败,请重新登录')localStorage.clear()location.href = '../login/index.html'}return Promise.reject(error);
});

对响应的结果做出处理


优化axios响应结果


axios直接接受服务器返回的响应结果

    // 2xx 范围内的状态码都会触发该函数。// 对响应数据做点什么.例如:直接返回服务器的响应结果对象const result = response.datareturn result;

这样result === response.data 我们再写的时候可以省略这部分。


发布文章-富文本编辑器


富文本:带样式,多格式的文本,在前端一般使用标签配合内联样式实现。

  1. 准备HTML标签结构
                <!-- 富文本编辑器位置 --><div id="editor—wrapper"><div id="toolbar-container"><!-- 工具栏 --></div><div id="editor-container"><!-- 编辑器 --></div></div><!-- 记录富文本内容-用于表单收集 --><textarea name="content" class="publish-content" hidden></textarea>
  1. 引入对应的js和css的插件
  2. 在准备相应的样式
  3. 根据文档引入核心的js代码

文档:https://www.wangeditor.com/


发布文章-频道列表


步骤

  1. 获取频道列表数据
  2. 展示到下拉菜单中

代码示例

// 1.1 获取频道列表数据
async function setChannleList() {const res = await axios({url: '/v1_0/channels'})console.log(res)// 1.2 展示到下拉菜单中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
}
setChannleList()

事先考虑是否需要复用,需要则使用函数配和async和await来修饰。


发布文章-封面设置


步骤:

  1. 准备标签结构样式
  2. 选择文件并保存在FormData
  3. 单独好上传图片并得到图片url地址
  4. 回显并切换img标签展示(隐藏 + 号 上传标签)

注意:图片地址临时存储在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.urldocument.querySelector('.rounded').src = imgURL// 显示图片,添加showdocument.querySelector('.rounded').classList.add('show')// 隐藏基础的 + 号 上传标签 添加hide类document.querySelector('.place').classList.add('hide')
})// 优化:点击 img 可以重新切换封面
// 思路:img 点击  => 用 js 方式触发文件选择元素  click  事件方法
document.querySelector('.rounded ').addEventListener('click', () => {// 调用click()方法可以模拟用户触发该类绑定的点击事件。通过调用click()方法,就相当于以编程方式触发了与该类相关联的点击事件。document.querySelector('.img-file').click()
})

发布文章-收集并保存


步骤:

  1. 基于 form-serialize 插件收集表单数据对象
  2. 基于 axios 提交到服务器保存
  3. 调用 Alert 警告框反馈结果给用户
  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.idconsole.log(data)// 自己收集封面图片地址,并保存到  data  对象中data.cover = {type: 1,images: [document.querySelector('.rounded').src]}// 3.2 基于 axios 提交到服务器保存try {const result = await axios({url: '/v1_0/mp/articles',method: 'POST',data})// 3.3 调用 Alert 警告框反馈结果给用户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.1 准备查询参数对象

* 1.2 获取文章列表数据

* 1.3 展示到指定的标签结构中

注意:查询参数不能封装到函数里面,因为他不是永远固定的,然后再将获取和渲染封装到函数里面,后面很多操作都需要使用到获取和渲染,方便我们操作,下次直接调用函数即可。

代码示例
// 1.1 准备查询参数对象
const queryObj = {status: '',   //文章的状态    (1-待审核   2-通过审核   )  空字符串全部channel_id: '',  //文章频道, id  空字符串全部page: 1,   //当前页码per_page: 2     //当前页面的条数
}
// 1.2 获取文章列表数据
async function setArtileList() {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('')document.querySelector('.art-list').innerHTML = htmlStr
}
setArtileList()

内容管理-筛选功能


  1. * 2.1 设置频道列表数据

    * 2.2 监听筛选条件改变,保存查询信息到查询参数对象

    * 2.3 点击筛选时,传递查询参数对象到服务器

    * 2.4 获取匹配数据,覆盖到页面展示

代码示例
// 2.1 设置频道列表数据
async function setChannleList() {const res = await axios({url: '/v1_0/channels'})console.log(res)// 1.2 展示到下拉菜单中 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
}
setChannleList()// 2.2 监听筛选条件改变,保存查询信息到查询参数对象
// 筛选状态标记数字 -> change 事件   -> 绑定到查询参数对象上
document.querySelectorAll('.form-check-input').forEach(radio => {radio.addEventListener('change', e => {queryObj.status = e.target.value})
})
// 筛选频道的 id  -> change 事件 -> 绑定到查询参数对象上
document.querySelector('.form-select').addEventListener('change', e => {queryObj.channel_id = e.target.value
})// 2.3 点击筛选时,传递查询参数对象到服务器
document.querySelector('.sel-btn').addEventListener('click', () => {// 2.4 获取匹配数据,覆盖到页面展示setArtileList()
})

内容管理-分页功能


* 3.1 保存并设置文章总条数

* 3.2 点击下一页,做临界值判断,并切换页码参数并请求最新数据

* 3.3 点击上一页,做临界值判断,并切换页码参数并请求最新数据

* 3.1 保存并设置文章总条数

let totalCount = 0   //保存文章总条数  
// 3.1 保存并设置文章总条数const totalStr = totalCount = res.data.total_count// 将获取到的返回数据个数插入到页面中document.querySelector('.total-count').innerHTML = `${totalStr}`
// 3.1 保存并设置文章总条数//  3.2 点击下一页,做临界值判断,并切换页码参数并请求最新数据
document.querySelector('.next').addEventListener('click', () => {// 当前页码小于最大页码数才能翻页if (queryObj.page < Math.ceil(totalCount / queryObj.per_page)) {// 当前页增加queryObj.page++document.querySelector('.page-now').innerHTML = `${queryObj.page}`// 调用函数,渲染最新数据setArtileList()}
})
//  3.3 点击上一页,做临界值判断,并切换页码参数并请求最新数据
document.querySelector('.page-link').addEventListener('click', () => {// 判断当前页码大于1的时候才能够执行if (queryObj.page > 1) {queryObj.page--document.querySelector('.page-now').innerHTML = `${queryObj.page}`// 调用函数,渲染最新数据setArtileList()}
})

内容管理-删除功能


  • 4.1 关联文章 id 到删除图标
  • 4.2 点击删除时,获取文章 id
  • 4.3 调用删除接口,传递文章 id 到服务器
  • 4.4 重新获取文章列表,并覆盖展示
  • 4.5 删除最后一页的最后一条,需要自动向前翻页
// 4.1 关联文章 id 到删除图标<td data-id="${item.id}"><i class="bi bi-pencil-square edit"></i><i class="bi bi-trash3 del"></i></td>
//  4.2 点击删除时,获取文章 id
document.querySelector('.art-list').addEventListener('click',async e => {//判断点击的是否为删除元素if (e.target.classList.contains('del')) {const delId = e.target.parentNode.dataset.idconsole.log(delId)// 4.3 调用删除接口,传递文章 id 到服务器const res = await axios({url: `/v1_0/mp/articles/${delId}`,method: 'DELETE',})// 4.5 删除最后一页的最后一条,需要自动向前翻页const children = document.querySelector('.art-list').childrenif (children.length === 1 && queryObj.page !== 1) {queryObj.page--document.querySelector('.page-now').innerHTML = `${queryObj.page}`}// 4.4 重新获取文章列表,并覆盖展示setArtileList()}})

内容管理-编辑文章


\* 4.1 页面跳转传参(URL 查询参数方式)

* 4.2 发布文章页面接收参数判断(共用同一套表单)

* 4.3 修改标题和按钮文字

* 4.4 获取文章详情数据并回显表单


//跨页面传参  传递id值// 点击编辑时,获取文章 id,跳转到发布文章页面传递文章 id 过去(使用事件委托)
document.querySelector('.art-list').addEventListener('click', e => {// 判断用户点击的是哪一个标签对象if (e.target.classList.contains('edit')) {// 拿到事件对象父级中的自定义属性 id值const artId = e.target.parentNode.dataset.idlocation.href = `../publish/index.html?id=${artId}`}
})
// 4.1 页面跳转传参(URL 查询参数方式)     立即执行函数,自己调用自己,防止变量污染
;(function () {// console.log(location.search)//查看查询参数字符串,就是?号后面的// 4.2 发布文章页面接收参数判断(共用同一套表单)const paramsStr = location.searchconst params = new URLSearchParams(paramsStr)       //分隔网址后面的查询参数params.forEach(async (value,key) => {// console.log(value,key)// 4.3 修改标题和按钮文字if (key === 'id') {// 当前有要编辑的文章 id 被传入过来document.querySelector('.title span').innerHTML = '修改文章'document.querySelector('.send').innerHTML = '修改'// 4.4 获取文章详情数据并回显表单const res = await axios({url: `/v1_0/mp/articles/${value}`,})console.log(res)// ***组织我需要的数据对象,我后续遍历回显到页面上做铺垫const dataObj = {channel_id: res.data.channel_id,title: res.data.title,rounded: res.data.cover.images[0],//封面图content: res.data.content,id: res.data.id}// ***遍历数据对象属性,映射到页面元素上,快速赋值Object.keys(dataObj).forEach(key => {console.log(key)if (key === 'rounded') {// 封面设置if (dataObj[key]) {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.1 判断按钮文字,区分业务(因为共用一套表单)

* 5.2 调用编辑文章接口,保存信息到服务器

* 5.3 基于 Alert 反馈结果消息给用户


document.querySelector('.send').addEventListener('click', async e => {// 5.1 判断按钮文字,区分业务(因为共用一套表单)if (e.target.innerHTML !== '修改') return// 修改文章逻辑// 5.2 调用编辑文章接口,保存信息到服务器try {const form = document.querySelector('.art-form')const data = serialize(form, { hash: true, empty: true })console.log(data)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]}}})console.log(res)myAlert(true,'修改文章成功')} catch (error) {myAlert(false,'error.response.data.message')}
})

退出登录


\* 3.1 绑定点击事件

* 3.2 清空本地缓存,跳转到登录页面

// 3.1 绑定点击事件
document.querySelector('.quit').addEventListener('click', e => {// 3.2 清空本地缓存,跳转到登录页面localStorage.clear()location.href = '../login/index.html'
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/44038.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

树莓派4B最新系统Bullseye 64 bit使用xrdp远程桌面黑屏卡顿问题

1、树莓派换源 打开源文件 sudo nano /etc/apt/sources.list注释原来的&#xff0c;更换为清华源 deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib no…

Python编程——列表解析与常用操作

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 本文专栏&#xff1a;Python专栏 专栏介绍&#xff1a;本专栏为免费专栏&#xff0c;并且会持续更新python基础知识&#xff0c;欢迎各位订阅关注。 目录 一、列表是什么&#xff1f; 二、列表的特点 1、元素…

pyltp 0.2.1安装

1. LTP及pyltp pyltp是 LTP的 Python封装&#xff0c;它里面提供了包括分词&#xff0c;词性标注&#xff0c;命名实体识别&#xff0c;句法分析等等能力。 比较坑的是我们可能无法直接通过pip install pyltp0.2.1方式来安装&#xff0c;所以本文就简单记录下如何通过源码安装…

商城-学习整理-高级-性能压测缓存问题(十一)

目录 一、基本介绍1、性能指标2、JMeter1、JMeter 安装2、JMeter 压测示例1、添加线程组2、添加 HTTP 请求3、添加监听器4、启动压测&查看分析结果 3、JMeter Address Already in use 错误解决 二、性能监控1、jvm 内存模型2、堆3、jconsole 与 jvisualvm1、jvisualvm 能干…

Flink CDC系列之:Oracle CDC 导入 Elasticsearch

Flink CDC系列之&#xff1a;Oracle CDC 导入 Elasticsearch 一、深入理解Flink Oracle CDC Connector二、创建docker-compose.yml文件三、启动容器四、下载Flink Oracle CDC的jar包五、启动 Flink 集群&#xff0c;再启动 SQL CLI六、检查 ElasticSearch 中的结果七、在 Oracl…

音视频 FFmpeg音视频处理流程

ffmpeg -i test_1920x1080.mp4 -acodec copy -vcodec libx264 -s 1280x720 test_1280x720.flv推荐一个零声学院项目课&#xff0c;个人觉得老师讲得不错&#xff0c;分享给大家&#xff1a; 零声白金学习卡&#xff08;含基础架构/高性能存储/golang云原生/音视频/Linux内核&am…

【计算机视觉】相机基本知识(还在更新)

1.面阵工业相机与线阵工业相机 1.1 基本概念区别 面阵相机则主要采用的连续的、面状扫描光线来实现产品的检测&#xff1b; 线阵相机即利用单束扫描光来进行物体扫描的工作的。 1.2 优缺点 &#xff08;1&#xff09;面阵CCD工业相机&#xff1a; 优点&#xff1a;应用面…

Jakarta 的 Servlet 下BeanUtils的日期处理 和JSTL 的使用

jsp优于性能等问题已经不被spring boot等支持&#xff0c;如果想使用jsp和jstl标签库需要引入一下依赖。 <!-- 用jakarta.servlet.jsp.jstl&#xff0c;用org.glassfish.web--><dependency><groupId>jakarta.servlet.jsp.jstl</groupId><art…

python使用dir()函数获取对象中可用的属性和方法(看不到python源码又想知道怎么调用,DLL调用分析,SDK二次开发技巧)

有时候调用一些SDK&#xff0c;但是人家又是封装成dll文件形式调用的&#xff0c;这时没法看源码&#xff0c;也不想看其对应的开发文档&#xff08;尤其有些开发文档写得还很难懂&#xff0c;或者你从某个开源社区拿过来&#xff0c;就根本没找到开发文档&#xff09;&#xf…

学习笔记:Opencv实现图像特征提取算法SIFT

2023.8.19 为了在暑假内实现深度学习的进阶学习&#xff0c;特意学习一下传统算法&#xff0c;分享学习心得&#xff0c;记录学习日常 SIFT的百科&#xff1a; SIFT Scale Invariant Feature Transform, 尺度不变特征转换 全网最详细SIFT算法原理实现_ssift算法_Tc.小浩的博客…

2235.两整数相加:19种语言解法(力扣全解法)

【LetMeFly】2235.两整数相加&#xff1a;19种语言解法&#xff08;力扣全解法&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/add-two-integers/ 给你两个整数 num1 和 num2&#xff0c;返回这两个整数的和。 示例 1&#xff1a; 输入&#xff1a;num…

Seaborn数据可视化(一)

目录 1.seaborn简介 2.Seaborn绘图风格设置 21.参数说明&#xff1a; 2.2 示例&#xff1a; 1.seaborn简介 Seaborn是一个用于数据可视化的Python库&#xff0c;它是建立在Matplotlib之上的高级绘图库。Seaborn的目标是使绘图任务变得简单&#xff0c;同时产生美观且具有信…

【Git】分支管理

文章目录 一、理解分支二、创建、切换、合并分支三、删除分支四、合并冲突五、合并模式六、分支策略七、bug分支八、强制删除分支 努力经营当下 直至未来明朗&#xff01; 一、理解分支 HEAD指向的是master分支&#xff0c;master中指向的是最新一次的提交&#xff0c;也就是m…

Visual Studio 2019源码编译cpu版本onnxruntime

1.下载onnxruntime源码 源码地址&#xff1a;gitee 》https://gitee.com/mirrors/onnx-runtime github 》https://github.com/microsoft/onnxruntime git clone --recursive https://gitee.com/mirrors/onnx-runtime 2.安装anaconda并配置python环境 安装anaconda时记得勾选默…

CSS基础 知识点总结

一.CSS简介 1.1 CSS简介 ① CSS指的是层叠样式表&#xff0c;用来控制网页外观的一门技术 ② CSS发展至今&#xff0c;经历过CSS1.0 CSS2.0 CSS2.1 CSS3.0这几个版本&#xff0c;CSS3.0是CSS最新版本 1.2 CSS引入方式 ① 在一个页面引入CSS&#xff0c;共有三种方式 外部…

Ansible 进阶

Ansible 进阶 ⤴️Ansible 入门看这篇文章⤵️Ansible 实战看这篇文章 一.Ansible 中的 Playbook 1.1 Playbook 介绍 如下图&#xff0c;ansible 在整个管理过程中使用 playbook 的大体流程。 Playbook 中包含多个 role&#xff0c;每个 role 对应于在远程主机完成某个比较复…

2.创建小程序

创建 在开发工具中,选择小程序,点击加号 填写小程序信息,模板使用的是TS+Sass 编辑器的工作区 目录结构 项目使用的是ts的模板,目录结构和js的有一点差异,目录结构如下: miniprogram:小程序根目录 —pages:小程序页面目录 ——xxx:页面目录,一个页面对应一个目…

水果成篮(力扣)双指针滑动窗口 JAVA

你正在探访一家农场&#xff0c;农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示&#xff0c;其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多地收集水果。然而&#xff0c;农场的主人设定了一些严格的规矩&#xff0c;你必须按照要求采摘水果&…

一、openlayer开发介绍

首先需要引入openlayer api开发包。两种方式&#xff1a; 1、import方式&#xff0c;也就是npm安装&#xff0c;npm install ol 2、外部js引入。 下载地址&#xff1a;https://github.com/openlayers/openlayers 历史版本地址&#xff1a;Releases openlayers/openlayers …

UVa10048 Audiophobia(floyd)

题意 给出一个图&#xff0c;图中的边表示从点u到点v路径上的噪音。给出q个查询&#xff0c;问从u到v所经路径上的最小噪音 思路 在使用floyd计算点对之间的路径时&#xff0c; D u , v k m i n { D u , v k − 1 , m a x { D u , k k − 1 , D k , v k − 1 } } D_{u, v}^…