day-110-one-hundred-and-ten-20230711-組件緩存-圖片上傳-富文編輯器-鑒權(quán)處理
組件緩存
keep-alive組件的使用
keep-alive組件的原理
圖片上傳
圖片上傳流程
- 點擊上傳圖片后,把圖片發(fā)送給服務(wù)器。
- 服務(wù)器返回一個相對或絕對地址。
- 提交時,把圖片地址與其余表單數(shù)據(jù)一起傳遞給服務(wù)器。
el-upload組件
-
圖片上傳分為兩步:
-
選取圖片
- 規(guī)則限制:類型、大小…
- multiple 是否支持多圖片上傳
- limit 最大上傳的個數(shù)
- on-exceed 超出最大限制觸發(fā)的函數(shù)
- accept 格式限制
- before-upload 上傳之前的鉤子
- auto-upload 默認(rèn)true
-
把圖片上傳到服務(wù)器,服務(wù)器返回上傳后的絕對地址
- 圖片流程中常用的屬性:
- action 上傳的接口地址
- headers 上傳請求的請求頭設(shè)置
- data 上傳請求的請求主體設(shè)置
- name 上傳文件的字段名「默認(rèn) file」
- with-credentials 是否允許攜帶資源憑證
- on-success 上傳成功「response, file, fileList」
- on-error 上傳失敗 「err, file, fileList」
- on-progress 上傳中「event, file, fileList」
- http-request 覆蓋默認(rèn)的上傳行為
- 其余文件常用的屬性:
- show-file-list
- file-list [{name,url},…]
- drag
- on-preview
- on-remove
- 圖片流程中常用的屬性:
-
-
內(nèi)置上傳機(jī)制說明:
-
element-ui / antd 等組件庫中的上傳組件
- 除了正常的文件選取和常規(guī)操作外,最主要的是:組件內(nèi)部,內(nèi)置了Ajax請求
-
用的是原生的 XMLHttpRequest 「不是我們的axios,所以我們axios的二次封裝等操作,對其內(nèi)置的ajax不生效」
-
基于POST,向action指定的接口地址發(fā)送請求,我們可以基于headers設(shè)置請求頭信息,請求主體中,其默認(rèn)帶了一個信息
字段名 值 file 選取的文件對象 - 而且是基于 FormData 格式,把信息傳遞給服務(wù)器的??!
- 如果需要設(shè)置除file以外的,額外的請求主體信息,可以基于 data 設(shè)置
-
都指定好之后,開始上傳
- 可以基于 on-progress 監(jiān)聽上傳進(jìn)度,處理進(jìn)度條
- 成功觸發(fā) on-success,其中 response 就是服務(wù)器返回的響應(yīng)主體信息
- 失敗觸發(fā) on-error
-
…文章來源:http://www.zghlxwxcb.cn/news/detail-564559.html
-
- 當(dāng)然除了這些內(nèi)置的設(shè)置外,我們還可以基于 http-request 覆蓋內(nèi)置的上傳行為,轉(zhuǎn)而走自己單獨的上傳請求
- 除了正常的文件選取和常規(guī)操作外,最主要的是:組件內(nèi)部,內(nèi)置了Ajax請求
內(nèi)置上傳
<script>
import ut from "@/assets/utils";
export default {
data() {
return {
// imageURL: "https://iot.fastbee.cn/prod-api/profile/avatar/2023/07/07/blob_20230707165813A006.png",
imageURL: "",
token: ut.storage.get("TK"),
};
},
methods: {
uploadSuccess(response) {
console.log(`response-->`, response);
let {code,msg,url}=response
if (+code===200) {
this.imageURL=url
this.$message.success("上傳成功");
return false;
}
this.$message.error(`網(wǎng)絡(luò)繁忙請稍后再試`)
},
uploadError(err) {
console.log(`err-->`, err);
this.$message.error(msg)
},
//限制大?。? beforeUpload(file) {
console.log(`file-->`, file);
let { size } = file;
if (size > 1000 * 1024) {
this.$message.warning("上傳的圖片不能超過1000kb");
return false;
}
return true;
},
},
};
</script>
<template>
<div class="category-box">
<el-upload
class="avatar-uploader"
:show-file-list="false"
accept="image/*"
:on-success="uploadSuccess"
:on-error="uploadError"
:before-upload="beforeUpload"
action="/api/iot/tool/upload"
:headers="{
Authorization: token,
}"
>
<img v-if="imageURL" :src="mixinPrefixAdd(imageURL)" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</div>
</template>
<style lang="less" scoped>
.category-box {
min-height: 300px;
background-color: #fff;
}
.avatar-uploader {
box-sizing: border-box;
width: 200px;
height: 200px;
border: 1px solid #ddd;
display: flex;
justify-content: center;
align-items: center;
.avatar {
width: 100px;
height: 100px;
}
.avatar-uploader-icon {
font-size: 20px;
}
}
</style>
自定義上傳
- fang/f20230711/ManageSystem/src/api/index.js
import http from "./http";
//圖片上傳
/* // https://iot.fastbee.cn/prod-api/iot/tool/upload
/iot/tool/upload - POST
Authorization 需要傳遞Token
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryalInqpHWOwZhUZyQ
請求主體
file:文件對象
返回值:
code: 200
fileName: "/profile/iot/6/2023-0711-105411.jpg"
msg: "操作成功"
url: "/profile/iot/6/2023-0711-105411.jpg" */
const uploadImage = (file) => {
let theFormData = new FormData();
theFormData.append("file", file);
return http.post("/iot/tool/upload", theFormData);
};
/* 暴露API */
const API = {
uploadImage,
};
export default API;
- fang/f20230711/ManageSystem/src/views/iot/Category.vue
<script>
import ut from "@/assets/utils";
export default {
data() {
return {
// imageURL: "https://iot.fastbee.cn/prod-api/profile/avatar/2023/07/07/blob_20230707165813A006.png",
imageURL: "",
token: ut.storage.get("TK"),
};
},
methods: {
//限制大??;
beforeUpload(file) {
console.log(`file-->`, file);
let { size } = file;
if (size > 1000 * 1024) {
this.$message.warning("上傳的圖片不能超過1000kb");
return false;
}
return true;
},
// ============
// 自定義請求
async request(data) {
let { file } = data;
console.log(`file-->`, file);
try {
let { code, msg, url } = await this.$API.uploadImage(file);
if (+code === 200) {
this.imageURL = url;
this.$message.success("自定義上傳-上傳成功");
return;
}
this.$message.error(`自定義上傳-上傳失敗:${msg}`);
} catch (error) {
console.log(`error:-->`, error);
}
},
},
};
</script>
<template>
<div class="category-box">
<el-upload
class="avatar-uploader"
:show-file-list="false"
accept="image/*"
:before-upload="beforeUpload"
action=""
:http-request="request"
>
<img v-if="imageURL" :src="mixinPrefixAdd(imageURL)" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</div>
</template>
<style lang="less" scoped>
.category-box {
min-height: 300px;
background-color: #fff;
}
.avatar-uploader {
box-sizing: border-box;
width: 200px;
height: 200px;
border: 1px solid #ddd;
display: flex;
justify-content: center;
align-items: center;
.avatar {
width: 100px;
height: 100px;
}
.avatar-uploader-icon {
font-size: 20px;
}
}
</style>
富文編輯器
- vue富文本編輯器vue-quill-editor的使用和介紹
- 一般來說,全局導(dǎo)入與局部導(dǎo)入都差不多,不過個人感覺還是局部導(dǎo)入來得好。
- 不過目前演示的是全局導(dǎo)入。
關(guān)于源碼
- fang/f20230711/ManageSystem/node_modules/vue-quill-editor/src/index.js
- fang/f20230711/ManageSystem/node_modules/vue-quill-editor/src/editor.vue
代碼示例
- Vue2進(jìn)階/ManageSystem/src/global.js
import Vue from "vue"
// 富文本編輯器
import VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
Vue.use(VueQuillEditor, {
placeholder: '請輸入正文信息'
})
- Vue2進(jìn)階/ManageSystem/src/views/iot/Product.vue
<script>
export default {
data() {
return {
content: "",
};
},
methods: {
handle() {
console.log(this.content);
},
},
};
</script>
<template>
<div>
<quill-editor v-model="content" />
<el-button type="primary" @click="handle">按鈕</el-button>
</div>
</template>
<style lang="less" scoped>
.quill-editor {
width: 800px;
}
</style>
鑒權(quán)處理
權(quán)限校驗定義
- 什么是權(quán)限校驗?
- 根據(jù)不同的登錄者(具備不同的權(quán)限),呈現(xiàn)不同的內(nèi)容,或者限制相關(guān)的操作;例如:一個管理系統(tǒng),公司全員可登錄,管理員、經(jīng)理、業(yè)務(wù)員肯定具備不同的權(quán)限?。?/li>
- 登錄校驗也算是權(quán)限校驗的一種!只不過登錄校驗只是用來判斷一個大類,不能具體到路由與頁面與按鈕。
權(quán)限表現(xiàn)形式
- 權(quán)限表現(xiàn)的形式:
- 具備相關(guān)的權(quán)限,我們再展示渲染出對應(yīng)的菜單;如果不具備,就不給用戶看到??!
- 例如:分類菜單、刪除按鈕…
- 不論是否具備權(quán)限,我們都渲染出來,但是在操作的時候,給予沒有相關(guān)操作權(quán)限的提示?。?
- 例如:沒會員不能看、沒會員只能看5分鐘、引導(dǎo)充會員…
- 有權(quán)限和沒權(quán)限看到不同的內(nèi)容??!
- 例如:客戶列表,經(jīng)理看到的是全部客戶,業(yè)務(wù)員只能看到自己的客戶…
- …
- 具備相關(guān)的權(quán)限,我們再展示渲染出對應(yīng)的菜單;如果不具備,就不給用戶看到??!
權(quán)限校驗機(jī)制的構(gòu)建流程
- 權(quán)限是如何在系統(tǒng)中構(gòu)建的:
- 開發(fā)者根據(jù)需求,構(gòu)建出對應(yīng)的權(quán)限代碼,例如:
-
我們發(fā)現(xiàn)哪些地方未來要做權(quán)限處理,則都設(shè)置對應(yīng)的編號代碼文章來源地址http://www.zghlxwxcb.cn/news/detail-564559.html
設(shè)備管理 iot:template:list -> 物模型列表 iot:template:query -> 物模型查詢篩選 iot:template:add -> 新增物模型信息 iot:template:update -> 修改物模型信息 iot:template:delete -> 刪除物模型信息 iot:category:list -> 產(chǎn)品分類管理 iot:product:list -> 產(chǎn)品管理 系統(tǒng)管理 system:user:query -> 用戶管理 system:menu:query -> 菜單管路 ...
- 職務(wù)/角色管理
- 在創(chuàng)建職務(wù)的時候,我們會為當(dāng)前職務(wù)勾選對應(yīng)的權(quán)限;這樣職務(wù)就具備對應(yīng)的權(quán)限代碼了!
- 員工管理
- 在管理員工的時候,我們會前為其分配職務(wù),這樣員工就有自己所屬的權(quán)限「具備的權(quán)限代碼」!
- 職務(wù)/角色管理
-
- 開發(fā)者根據(jù)需求,構(gòu)建出對應(yīng)的權(quán)限代碼,例如:
權(quán)限校驗具體實現(xiàn)邏輯
- 前端開發(fā)者如何實現(xiàn)權(quán)限校驗?
- 從表現(xiàn)形式上來看上述的1~3:
- 在用戶登錄成功后,我們從服務(wù)器獲取登錄者信息的時候,一般后臺會返回當(dāng)前用戶具備的權(quán)限代碼「即便沒有返回,也會有對應(yīng)的接口,可以讓我們獲取到其權(quán)限代碼」;我們把獲取的權(quán)限代碼存儲起來:
- vuex中「推薦:安全、頁面刷新就會從服務(wù)器獲取最新的權(quán)限…」
- localStorage中「不安全、更新度較慢…」
- 情況3:有權(quán)限和沒權(quán)限看到不同的內(nèi)容!
- 這種情況一般都是服務(wù)器處理{為了保障安全},服務(wù)器會根據(jù)當(dāng)前登陸者的權(quán)限,返回所擁有的信息!!
- 同樣的請求接口,同樣的參數(shù)設(shè)置,業(yè)務(wù)員登錄只能獲取自己的客戶,經(jīng)理登錄,服務(wù)器返回的就是全部客戶??!
- 情況2:不論是否具備權(quán)限,我們都渲染出來,但是在操作的時候,給予沒有相關(guān)操作權(quán)限的提示!
- 在我們進(jìn)行相關(guān)操作的時候,我們首先看vuex中是否具備對應(yīng)的權(quán)限代碼,不具備就給與對應(yīng)的提示和引導(dǎo)即可!
- 一般是做一個全局minix或在原型上掛載一個方法,在用戶點擊對應(yīng)的按鈕時就執(zhí)行一下那個方法,看該方法的返回結(jié)果。如果是拒絕的Promise或false,就不做任何操作或者提示用戶沒權(quán)限。如果是正確的Promise或true,就進(jìn)行后續(xù)操作。
- 在我們進(jìn)行相關(guān)操作的時候,我們首先看vuex中是否具備對應(yīng)的權(quán)限代碼,不具備就給與對應(yīng)的提示和引導(dǎo)即可!
- 情況1:具備相關(guān)的權(quán)限,我們再展示渲染出對應(yīng)的菜單。
- 實現(xiàn)方案有兩種:
- 客戶端在渲染內(nèi)容的時候,根據(jù)權(quán)限代碼進(jìn)行判斷,具備相關(guān)權(quán)限的,則渲染出來,不具備的則不渲染!!
- v-if
- 自定義指令處理「推薦」
- 問題:路由表中包含了,項目中所有的頁面的路由配置(不管是否擁有對應(yīng)的權(quán)限);這樣即便沒有權(quán)限,我們把菜單隱藏了,但是“高級玩家”還是可以自己去改變地址欄中的路由地址,從而進(jìn)入到指定的路由中!
- 解決:如果還是前端解決,則我們需要在每一次路由跳轉(zhuǎn)(導(dǎo)航守衛(wèi)中)的時候,做權(quán)限校驗!
- 客戶端在渲染內(nèi)容的時候,根據(jù)權(quán)限代碼進(jìn)行判斷,具備相關(guān)權(quán)限的,則渲染出來,不具備的則不渲染!!
- 實現(xiàn)方案有兩種:
- 在用戶登錄成功后,我們從服務(wù)器獲取登錄者信息的時候,一般后臺會返回當(dāng)前用戶具備的權(quán)限代碼「即便沒有返回,也會有對應(yīng)的接口,可以讓我們獲取到其權(quán)限代碼」;我們把獲取的權(quán)限代碼存儲起來:
- 從表現(xiàn)形式上來看上述的1~3:
在操作的時候給予沒有相關(guān)操作權(quán)限的提示的流程
- fang/f20230711/ManageSystem/src/global.js
import Vue from "vue";
// 權(quán)限校驗-第二種情況:不論是否具備權(quán)限,都先渲染出來,只不過操作的時候再校驗權(quán)限。
Vue.prototype.$handlePermiseCheck = function $handlePermiseCheck(checkFlag) {
//先獲取登錄者具備的全部權(quán)限標(biāo)識:
let permissions = this.$store.state.profile.permissions || [];
//驗證傳遞的標(biāo)識是否存在
if (permissions.includes(checkFlag)) {
return Promise.resolve('');
}
//沒有權(quán)限:
this.$notify({
title: "權(quán)限警告",
message: "你不具備此操作權(quán)限,請先聯(lián)系管理員!",
type: "warning",
duration: 2000,
});
return Promise.reject('');
};
- fang/f20230711/ManageSystem/src/views/iot/Template.vue
<script>
export default {
methods: {
// 觸發(fā)刪除多項的按鈕
async triggerDeleteAll() {
try {
await this.$handlePermiseCheck("iot:template:delete");
// 執(zhí)行校驗通過相關(guān)的操作。
//....
} catch (_) {
// 執(zhí)行校驗失敗相關(guān)的操作。
//....
}
},
// 觸發(fā)下載按鈕
async triggerDownLoad() {
try {
await this.$handlePermiseCheck("iot:template:download");
// 執(zhí)行校驗通過相關(guān)的操作。
//....
} catch (error) {
console.log(`error:-->`, error);
// 執(zhí)行校驗失敗相關(guān)的操作。
//....
}
},
// 觸發(fā)新增
async triggerAdd() {
try {
await this.$handlePermiseCheck("iot:template:add");
// 執(zhí)行校驗通過相關(guān)的操作。
//....
} catch (error) {
console.log(`error:-->`, error);
// 執(zhí)行校驗失敗相關(guān)的操作。
//....
}
},
},
};
</script>
<template>
<div class="template-box">
<!-- 篩選/操作區(qū)域 -->
<div class="filter-box">
<div class="handler">
<el-button type="primary" ghost icon="el-icon-plus" @click="triggerAdd">
新增
</el-button>
<el-button
type="danger"
ghost
icon="el-icon-minus"
@click="triggerDeleteAll"
>
刪除
</el-button>
<el-button
type="success"
ghost
icon="el-icon-download"
@click="triggerDownLoad"
>
下載
</el-button>
</div>
</div>
</div>
</template>
動態(tài)路由
- 動態(tài)路由 -> 權(quán)限校驗交給后臺,客戶端只需要在登錄成功后,從服務(wù)器獲取對應(yīng)的路由表即可
- 我們事先按照最高權(quán)限編寫路由表的配置;
- 把寫好的路由表直接給后臺(不是ajax傳輸,而是直接把代碼給后臺),后臺提供一個接口,客戶端可基于ajax,從服務(wù)器端進(jìn)行獲取;
- 獲取到的路由表是經(jīng)過服務(wù)器端權(quán)限校驗完成的,例如:登陸者不具備產(chǎn)品管理的權(quán)限,那么返回的路由表中是沒有這個路由的配置的!!
- 客戶端基于router.addRoutes/addRoute來動態(tài)增加路由配置??!
- 頁面左側(cè)的Menu菜單,也是基于服務(wù)器返回的路由表信息,循環(huán)動態(tài)綁定的!
進(jìn)階參考
- vue富文本編輯器vue-quill-editor的使用和介紹
到了這里,關(guān)于20230711----重返學(xué)習(xí)-組件緩存-圖片上傳-富文編輯器-鑒權(quán)處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!