黑馬頭條-數據管理平臺

目錄

項目介紹

功能

項目準備

技術

驗證碼

驗證碼登錄

驗證碼登錄-流程

關于token

token的介紹

token的使用

個人信息設置

個人信息設置和axios請求攔截器

axios響應攔截器和身份驗證失敗

優化-axios響應結果

發布文章

發布文章-富文本編輯器

發布文章-頻道列表

發布文章-封面設置

發布文章-收集并保存

內容管理

內容管理-文章列表展示

內容管理-篩選功能

內容管理-分頁功能

內容管理-刪除功能

內容管理-刪除最后一條

內容管理-編輯文章-回顯

內容管理-編輯文章-保存

退出登錄

項目介紹

黑馬頭條-數據管理平臺:對IT資訊移動網站的數據,進行數據管理

數據管理平臺-演示:配套代碼在本地運行

移動網站-演示:http://geek.itheima.net/


?

功能

  1. 登錄和權限判斷
  2. 查看文章內容列表(篩選,分頁)
  3. 編輯文章(數據回顯)
  4. 刪除文章
  5. 發布文章(圖片上傳,富文本編輯器)
    ?

總結:

1. 黑馬頭條-數據管理平臺,是什么樣網站,要完成哪些功能?

  • 數據管理網站, 登錄后對數據進行增刪改查

2. 數據管理平臺,未登錄能否管理數據?

  • 不能,數據是公司內部的,需賬號登錄后管理

項目準備

技術

  • 基于Bootstrap搭建網站標簽和樣式
  • 集成wangEditor插件實現富文本編輯器
  • 使用原生JS完成增刪改查等業務
  • 基于axios與黑馬頭條線上接口交互
  • 使用axios攔截器進行權限判斷
    ?

項目準備:準備配套的素材代碼

包含:html,CSS,js,靜態圖片,第三方插件等等

目錄管理:建議這樣管理,方便查找

  • assets:資源文件夾(圖片,字體等)
  • lib:資料文件夾( 第三方插件,例如:form-serialize )
  • page:頁面文件夾
  • utils:實用程序文件夾(工具插件)
    ?

總結:

1. 為什么要按照一定的結構,管理代碼文件?

  • 方便以后的查找擴展

驗證碼

驗證碼登錄

目標:完成驗證碼登錄,后端設置驗證碼默認為246810

原因:因為短信接口不是免費的,防止攻擊者惡意盜刷

步驟:

1. 在utils/request.js配置axios請求基地址

  • 作用:提取公共前綴地址,配置后axios請求時都會baseURL + url

2. 收集手機號和驗證碼數據

3. 基于axios調用驗證碼登錄接口

4. 使用Bootstrap的Alert警告框反饋結果給用戶


驗證碼登錄-流程

手機號+驗證碼,登錄流程:


?

關于token

token的介紹

概念:訪問權限的令牌,本質上是一串字符串

創建:正確登錄后,由后端簽發并返回


?

作用:判斷是否有登錄狀態等,控制訪問權限

注意:前端只能判斷token有無,而后端才能判斷token的有效性
?

token的使用

目標:只有登錄狀態,才可以訪問內容頁面

步驟:

  1. 在utils/auth.js 中判斷無token令牌字符串,則強制跳轉到登錄頁(手動修改地址欄測試)
  2. 在登錄成功后,保存token令牌字符串到本地,再跳轉到首頁(手動修改地址欄測試)
    ?

總結:

1. token的作用?

  • 判斷用戶是否有登錄狀態

2. token的注意:

  • 前端只能判斷token的有無
  • 后端通過解密可以提取token字符串的原始信息,判斷有效性
    ?
/*** 目標1:驗證碼登錄* 1.1 在 utils/request.js 配置 axios 請求基地址* 1.2 收集手機號和驗證碼數據* 1.3 基于 axios 調用驗證碼登錄接口* 1.4 使用 Bootstrap 的 Alert 警告框反饋結果給用戶*/// 1.2 收集手機號和驗證碼數據
document.querySelector('.btn').addEventListener('click', () => {const form = document.querySelector('.login-form')const data = serialize(form, { hash: true, empty: true })console.log(data)// 1.3 基于 axios 調用驗證碼登錄接口axios({url: '/v1_0/authorizations',method: 'POST',data}).then(result => {// 1.4 使用 Bootstrap 的 Alert 警告框反饋結果給用戶myAlert(true, '登錄成功')console.log(result)// 登錄成功后,保存 token 令牌字符串到本地,并跳轉到內容列表頁面localStorage.setItem('token', result.data.token)setTimeout(() => {// 延遲跳轉,讓 alert 警告框停留一會兒location.href = '../content/index.html'}, 1500)}).catch(error => {myAlert(false, error.response.data.message)console.dir(error.response.data.message)})
})

個人信息設置

個人信息設置和axios請求攔截器

需求:設置用戶昵稱

語法:axios 可以在headers選項傳遞請求頭參數


?

問題:很多接口,都需要攜帶token令牌字符串

解決:請求攔截器統一設置公共headers選項


?

axios請求攔截器:發起請求之前,觸發的配置函數,對請求參數進行額外配置

總結:

1. 什么是axios請求攔截器?

  • 發起請求之前,調用的一個函數,對請求參數進行設置

2. axios 請求攔截器,什么時候使用?

  • 公共配置和設置時,統一-設置在請求攔截器中

axios響應攔截器和身份驗證失敗

axios響應攔截器:響應回到then/catch之前,觸發的攔截函數,對響應結果統一處理

例如:身份驗證失敗,統一判斷并做處理


?

// axios 公共配置
// 基地址
axios.defaults.baseURL = 'http://geek.itheima.net'// 添加請求攔截器
axios.interceptors.request.use(function (config) {// 在發送請求之前做些什么// 統一攜帶 token 令牌字符串在請求頭上const token = localStorage.getItem('token')token && (config.headers.Authorization = `Bearer ${token}`)return config;
}, function (error) {// 對請求錯誤做些什么return Promise.reject(error);
});// 添加響應攔截器
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);
});

總結:

1. 什么是axios響應攔截器?

  • 響應回到then/catch之前,觸發的攔截函數,對響應結果統一處理

2. axios 響應攔截器,什么時候觸發成功/失敗的回調函數?

  • 狀態為2xx觸發成功回調,其他則觸發失敗的回調函數

優化-axios響應結果

目標:axios直接接收服務器返回的響應結果


?

// axios 公共配置
// 基地址
axios.defaults.baseURL = 'http://geek.itheima.net'// 添加請求攔截器
axios.interceptors.request.use(function (config) {// 在發送請求之前做些什么// 統一攜帶 token 令牌字符串在請求頭上const token = localStorage.getItem('token')token && (config.headers.Authorization = `Bearer ${token}`)return config;
}, function (error) {// 對請求錯誤做些什么return Promise.reject(error);
});// 添加響應攔截器
axios.interceptors.response.use(function (response) {// 2xx 范圍內的狀態碼都會觸發該函數。// 對響應數據做點什么,例如:直接返回服務器的響應結果對象const result = response.datareturn result;
}, function (error) {// 超出 2xx 范圍的狀態碼都會觸發該函數。// 對響應錯誤做點什么,例如:統一對 401 身份驗證失敗情況做出處理console.dir(error)if (error?.response?.status === 401) {alert('身份驗證失敗,請重新登錄')localStorage.clear()location.href = '../login/index.html'}return Promise.reject(error);
});

發布文章

發布文章-富文本編輯器

富文本:帶樣式,多格式的文本,在前端一般使用標簽配合內聯樣式實現

富文本編輯器:用于編寫富文本內容的容器


?

目標:發布文章頁,富文本編輯器的集成

使用:wangEditor 插件

步驟:參考文檔

  1. 引入CSS定義樣式
  2. 定義HTML結構
  3. 引入JS創建編輯器
  4. 監聽內容改變,保存在隱藏文本域(便于后期收集)
    ?

// 富文本編輯器
// 創建編輯器函數,創建工具欄函數
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: '<p><br></p>',// 配置項config: editorConfig,// 配置集成模式(default 全部)(simple 簡潔)mode: 'default', // or 'simple'
})// 工具欄配置對象
const toolbarConfig = {}// 創建工具欄
const toolbar = createToolbar({// 為指定編輯器創建工具欄editor,// 工具欄創建的位置selector: '#toolbar-container',// 工具欄配置對象config: toolbarConfig,// 配置集成模式mode: 'default', // or 'simple'
})

發布文章-頻道列表

目標:展示頻道列表,供用戶選擇

步驟:

  1. 獲取頻道列表數據
  2. 展示到下拉菜單中
    ?

/*** 目標1:設置頻道下拉菜單*  1.1 獲取頻道列表數據*  1.2 展示到下拉菜單中*/
// 1.1 獲取頻道列表數據
async function setChannleList() {const res = await axios({url: '/v1_0/channels'})// 1.2 展示到下拉菜單中const htmlStr = `<option value="" selected="">請選擇文章頻道</option>` + res.data.channels.map(item => `<option value="${item.id}">${item.name}</option>`).join('')document.querySelector('.form-select').innerHTML = htmlStr
}
// 網頁運行后,默認調用一次
setChannleList()

發布文章-封面設置

目標:文章封面的設置

步驟:

  1. 準備標簽結構和樣式
  2. 選擇文件并保存在FormData
  3. 單獨上傳圖片并得到圖片URL地址
  4. 回顯切換img標簽展示(隱藏+號上傳標簽)

注意:圖片地址臨時存儲在img標簽上,并未和文章關聯保存

/*** 目標2:文章封面設置*  2.1 準備標簽結構和樣式*  2.2 選擇文件并保存在 FormData*  2.3 單獨上傳圖片并得到圖片 URL 網址*  2.4 回顯并切換 img 標簽展示(隱藏 + 號上傳標簽)*/
// 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})// 2.4 回顯并切換 img 標簽展示(隱藏 + 號上傳標簽)const imgUrl = res.data.urldocument.querySelector('.rounded').src = imgUrldocument.querySelector('.rounded').classList.add('show')document.querySelector('.place').classList.add('hide')
})
// 優化:點擊 img 可以重新切換封面
// 思路:img 點擊 => 用 JS 方式觸發文件選擇元素 click 事件方法
document.querySelector('.rounded').addEventListener('click', () => {document.querySelector('.img-file').click()
})

發布文章-收集并保存

目標:收集文章內容,并提交保存

步驟:

  1. 基于form-serialize插件收集表單數據對象
  2. 基于axios提交到服務器保存
  3. 調用Alert警告框反饋結果給用戶
  4. 重置表單并跳轉到列表頁
    ?

/*** 目標3:發布文章保存*  3.1 基于 form-serialize 插件收集表單數據對象*  3.2 基于 axios 提交到服務器保存*  3.3 調用 Alert 警告框反饋結果給用戶*  3.4 重置表單并跳轉到列表頁*/
// 3.1 基于 form-serialize 插件收集表單數據對象
document.querySelector('.send').addEventListener('click', async e => {if (e.target.innerHTML !== '發布') returnconst 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] // 封面圖片 URL 網址}// 3.2 基于 axios 提交到服務器保存try {const res = await axios({url: '/v1_0/mp/articles',method: 'POST',data: 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. 準備查詢參數對象
  2. 獲取文章列表數據
  3. 展示到指定的標簽結構中
    ?

/*** 目標1:獲取文章列表并展示*  1.1 準備查詢參數對象*  1.2 獲取文章列表數據*  1.3 展示到指定的標簽結構中*/
// 1.1 準備查詢參數對象
const queryObj = {status: '', // 文章狀態(1-待審核,2-審核通過)空字符串-全部channel_id: '', // 文章頻道 id,空字符串-全部page: 1, // 當前頁碼per_page: 2 // 當前頁面條數
}
let totalCount = 0 // 保存文章總條數// 獲取并設置文章列表
async function setArtileList() {// 1.2 獲取文章列表數據const res = await axios({url: '/v1_0/mp/articles',params: queryObj})// 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-primary">待審核</span>` : `<span class="badge text-bg-success">審核通過</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 data-id="${item.id}"><i class="bi bi-pencil-square edit"></i><i class="bi bi-trash3 del"></i></td>
</tr>`).join('')document.querySelector('.art-list').innerHTML = htmlStr// 3.1 保存并設置文章總條數totalCount = res.data.total_countdocument.querySelector('.total-count').innerHTML = `共 ${totalCount} 條`
}
setArtileList()

內容管理-篩選功能

目標:根據篩選條件,獲取匹配數據展示

步驟:

  1. 設置頻道列表數據
  2. 監聽篩選條件改變,保存查詢信息到查詢參數對象
  3. 點擊篩選時,傳遞查詢參數對象到服務器
  4. 獲取匹配數據,覆蓋到頁面展示
    ?

/*** 目標2:篩選文章列表*  2.1 設置頻道列表數據*  2.2 監聽篩選條件改變,保存查詢信息到查詢參數對象*  2.3 點擊篩選時,傳遞查詢參數對象到服務器*  2.4 獲取匹配數據,覆蓋到頁面展示*/
// 2.1 設置頻道列表數據
async function setChannleList() {const res = await axios({url: '/v1_0/channels'})const htmlStr = `<option value="" selected="">請選擇文章頻道</option>` + res.data.channels.map(item => `<option value="${item.id}">${item.name}</option>`).join('')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()
})

內容管理-分頁功能

目標:完成文章列表,分頁管理功能

步驟:

  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. 重新設置頁碼數,獲取最新列表展示
    ?

內容管理-編輯文章-回顯

目標:編輯文章時,回顯數據到表單

步驟:

  1. 頁面跳轉傳參(URL 查詢參數方式)
  2. 發布文章頁面接收參數判斷(共用同一套表單)
  3. 修改標題和按鈕文字
  4. 獲取文章詳情數據并回顯表單
    ?

/*** 目標4:編輯-回顯文章*  4.1 頁面跳轉傳參(URL 查詢參數方式)*  4.2 發布文章頁面接收參數判斷(共用同一套表單)*  4.3 修改標題和按鈕文字*  4.4 獲取文章詳情數據并回顯表單*/; (function () {// 4.2 發布文章頁面接收參數判斷(共用同一套表單)const paramsStr = location.searchconst params = new URLSearchParams(paramsStr)params.forEach(async (value, key) => {// 當前有要編輯的文章 id 被傳入過來if (key === 'id') {// 4.3 修改標題和按鈕文字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 => {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]}})}})})();

內容管理-編輯文章-保存

目標:確認修改,保存文章到服務器

步驟:

  1. 判斷按鈕文字,區分業務(因為共用一套表單)
  2. 調用編輯文章接口,保存信息到服務器
  3. 基于Alert反饋結果消息給用戶
    ?

/*** 目標5:編輯-保存文章*  5.1 判斷按鈕文字,區分業務(因為共用一套表單)*  5.2 調用編輯文章接口,保存信息到服務器*  5.3 基于 Alert 反饋結果消息給用戶*/
document.querySelector('.send').addEventListener('click', async e => {// 5.1 判斷按鈕文字,區分業務(因為共用一套表單)if (e.target.innerHTML !== '修改') return// 修改文章邏輯const form = document.querySelector('.art-form')const data = serialize(form, { hash: true, empty: true })// 5.2 調用編輯文章接口,保存信息到服務器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]}}})console.log(res)myAlert(true, '修改文章成功')} catch (error) {myAlert(false, error.response.data.message)}
})

退出登錄

目標:完成退出登錄效果

步驟:

  1. 綁定點擊事件
  2. 清空本地緩存,跳轉到登錄頁面
    ?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/86100.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/86100.shtml
英文地址,請注明出處:http://en.pswp.cn/web/86100.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Pytorch3D 中涉及的知識點匯總

PyTorch3D 是 Facebook&#xff08;現 Meta&#xff09;AI 研究院&#xff08;FAIR&#xff09;推出的一個基于 PyTorch 的三維計算庫&#xff0c;主要用于 3D 計算機視覺與圖形學任務&#xff0c;如 3D 重建、渲染、點云處理、網格操作等。 下面是對 PyTorch3D 中重要涉及知識…

XML在線格式化工具

XML格式化 免費在線XML格式化與壓縮工具&#xff0c;一鍵美化、校驗、壓縮和優化您的XML代碼。支持自定義縮進、節點折疊&#xff0c;提升可讀性&#xff0c;減小文件體積&#xff0c;加速數據傳輸。 https://toolshu.com/xml 本工具是一款專為處理XML&#xff08;可擴展標記…

【軟件系統架構】系列四:嵌入式技術

目錄 一、嵌入式系統組成 (1)嵌入式處理器 (2)支撐硬件 (3)嵌入式操作系統 (4)支撐軟件 (5)應用軟件 二、嵌入式系統特性 三、嵌入式系統分類與分層結構 1.分類 2.嵌入式軟件的五層架構深入解析 (1)硬件層(Hardware Layer) (2)抽象層(Hardware Ab…

監管報送面試回答思路和示例

在銀行監管報送崗位的面試中&#xff0c;回答問題時需要展現出你的專業知識、實際操作經驗、問題解決能力以及對監管合規的重視。以下是對各類問題的回答思路和示例&#xff1a; 一、專業知識類問題 1. 請簡述銀行監管報送的主要類型和報送頻率 回答思路&#xff1a;分類介紹…

音視頻SDK架構演進的實踐與思考

“不是每一行代碼都值得驕傲&#xff0c;但每一次迭代&#xff0c;都是一次更接近極致的嘗試。” 從最初的數千行代碼、到如今跨平臺、全功能、穩定可靠的直播技術基座&#xff0c;大牛直播SDK走過了整整十年。十年&#xff0c;既是時間的刻度&#xff0c;更是技術沉淀與產品信…

vue.config.js配置學習

1.部署應用包時的基本 URL (baseUrl或publicPath) baseUrl在vue-cli 3.3 時棄用了&#xff0c;自此之后使用publicPath 默認&#xff1a;/ module.exports {// baseUrl:"/",publicPath: ./, ) 2.打包時輸出的文件位置&#xff1a;outputDir 默認: dist module.…

大模型——Prompt Design

Prompt Design 為什么未來最重要的寫作,不是寫給人看的,而是寫給AI理解的? 01|一切從一次“客服神操作”開始 前幾天前,我在看一場 YC Demo Day 分享的時候,聽到一個很炸裂的細節: 有個叫 Parahelp 的 AI 客服創業項目,靠一段幾百行的“提示詞”,打敗了市面上大多數…

web布局20

在當下&#xff0c;可用于 Web 布局的 CSS 特性有很多&#xff0c;而且這個集合越來越強大。自從 Flexbox 的兼容性越來越完善&#xff0c;它替代了浮動布局&#xff0c;成為主流的布局技術。只不過&#xff0c;近幾年來&#xff0c;CSS Grid 快速得到主流瀏覽器的支持&#xf…

數據集-目標檢測系列- 餐具叉子 數據集 fork >> DataBall

數據集-目標檢測系列- 餐具叉子 數據集 fork &#xff1e;&#xff1e; DataBall 貴在堅持&#xff01; * 相關項目 1&#xff09;數據集可視化項目&#xff1a;gitcode: https://gitcode.com/DataBall/DataBall-detections-100s/overview 2&#xff09;數據集訓練、推理相…

力扣-45.跳躍游戲 ll

題目描述 給定一個長度為 n 的 0 索引整數數組 nums。初始位置為 nums[0]。 每個元素 nums[i] 表示從索引 i 向后跳轉的最大長度。換句話說&#xff0c;如果你在 nums[i] 處&#xff0c;你可以跳轉到任意 nums[i j] 處: 0 < j < nums[i] i j < n 返回到達 nums[n…

借助STL工具解題的各個技巧

目錄 前言 STL容器一覽 set和map如何降序構建 set和map如何插入自定義對象 multiset和multimap如何降序構建 multiset和multimap如何插入自定義對象 multi_系列如何equal_range multiset multimap unorder_multiset unorder_multimap STL容器迭代器一覽 迭代器性能一覽…

【Linux 設備樹DTS】

Linux 設備樹DTS 一、設備樹概述&#xff1a;為什么它是 Linux 驅動開發的關鍵&#xff1f;二、設備樹語法詳解&#xff1a;從基礎到高級2.1 基本結構&#xff1a;節點與屬性2.2 數據類型與表示方式2.3 引用與別名2.4 address-cells和size-cells屬性詳解2.5 包含與覆蓋2.6 未定…

【技巧】使用frpc安全地內網穿透ssh訪問內網機器

【技巧】使用frpc安全地內網穿透ssh訪問內網機器 0. 為什么需要部署 office的機器可以單向訪問互聯網&#xff0c;互聯網無法直接訪問到這臺機器。有時候需要從家里通過ssh遠程訪問和配置。 在云服務器上部署frpc把轉發ssh給需要訪問的機器。 1. 互聯網云服務器&#xff08;…

【Faster-Whisper】離線識別本地視頻并生成字幕

【Faster-Whisper】離線識別本地視頻并生成字幕 1 前言2 工具說明2.1 ffmpeg 媒體轉換器2.1.1 理論簡介文檔 2.1.2 安裝win安裝python安裝 2.1.3 查看查看音視頻文件格式、編碼 2.1.4 視頻處理視頻格式轉換設置 視頻碼率裁剪視頻 2.1.5 音頻處理視頻提取音頻音頻格式轉換gpu加速…

開源CMS vs 閉源CMS:二次開發究竟有何不同?

在網站建設項目中&#xff0c;內容管理系統&#xff08;CMS&#xff09; 是核心基礎設施。而“二次開發”則是讓CMS真正適配業務需求的關鍵環節&#xff0c;譬如調整頁面樣式&#xff0c;或者新增會員體系等等。但很多人沒意識到&#xff1a;選擇開源CMS還是閉源CMS&#xff0c…

npm 更新包名,本地導入

package.json 更新包根目錄名字&#xff0c;同時改 name 和 dependencies相關的依賴也需本地導入&#xff0c;否則無法生效 之后將改包放在你所需的項目位置&#xff0c;通過以下命令導入node_modules生效 pnpm install file:../table-ui/m-table -w防止包數據更新或丟棄&…

若依框架二次開發——若依前后端分離版集成 UReport2 報表工具

文章目錄 一、UReport2 簡介二、解決方案1、后端配置1.1 引入 UReport2 依賴1.2 啟動類配置1.3配置文件1.4 修改安全配置2、前端配置2.1 配置 Vue.js 代理2.2創建設計器頁面2.3 新增菜單運行結果一、UReport2 簡介 UReport2 是一款開源的 Java 報表工具,廣泛應用于各類企業管…

Ntfs!_LFCB結構如何構建出來的--從Ntfs!NtfsMountVolume到Ntfs!LfsAllocateLfcb

Ntfs!LfsRestartLogFile函數分析之調用Ntfs!LfsAllocateLfcb函數初始化Lfcb->LbcbWorkque 第一部分&#xff1a; F:\srv03rtm>grep "NtfsStartLogFile" -rn F:\srv03rtm\base\fs\ntfs |grep -v "inary" F:\srv03rtm\base\fs\ntfs/fsctrl.c:1890: …

Domain層到底是什么

層級主要職責是否依賴 iOS / UIKit&#xff1f;Presentation (UI)視圖、控制器、ViewModel&#xff0c;將用戶操作轉成「意圖」&#xff0c;把結果渲染到屏幕是Domain業務規則 與 用例 (Use Case)&#xff0c;維護系統在概念上的真實世界模型否&#xff08;純 Swift&#xff0c…

Rust 服務端項目分層結構

DDD src/ ├── main.rs # 程序入口&#xff0c;負責啟動和依賴注入 ├── lib.rs # 公共庫入口&#xff0c;便于單元測試和復用 ├── config.rs # 配置管理&#xff08;如數據庫、端口、環境變量等&#xff09; ├── entities/ …