摘要:重要功能一些擴(kuò)展的重要功能將在這里一點點從零開始進(jìn)行思考。假設(shè)現(xiàn)在的數(shù)據(jù)是這樣的演示項目接口示例超長字符串測試項目描述前端工程師宋青樹后端工程師獲取接口描述增加接口描述刪除接口描述更新接口描述我們需要將里面所有的字段數(shù)組去除。
前言
二月初想想這個月還得搗鼓一篇文章,也沒啥好的想法那還是記錄一下畢設(shè)的一些思路吧。
重要功能一些擴(kuò)展的重要功能將在這里一點點從零開始進(jìn)行思考。
項目導(dǎo)入導(dǎo)出功能項目導(dǎo)入導(dǎo)出的構(gòu)想是在設(shè)定特色功能時候想到的,主要是用于不同服務(wù)器上如果部署了平臺,如果想要自己私下部署測試,那么重新建立項目,然后再一個個配置接口路徑,配置返回數(shù)據(jù)是一件很麻煩的事情。為了以后用(自)戶(己)用的順暢,想了一鍵各種版本的功能,其中就包括項目的導(dǎo)入導(dǎo)出。
因此在設(shè)計數(shù)據(jù)結(jié)構(gòu)的時候,我將最終返回結(jié)果數(shù)據(jù)設(shè)計成如下形式
{ project:{ projectId:, ... interfaceList: [] } }
也就是前端本地緩存的數(shù)據(jù)就可以直接導(dǎo)出。
當(dāng)然導(dǎo)出可以把一些信息先過濾處理一遍,比如項目Id ,接口 Id。
于是導(dǎo)出可以為一個純 Json 文本。
然后倒入時候需要驗證 Json 格式,其實就是需要做個遍歷,看看該有的屬性有沒有,沒有的話就報錯不進(jìn)行數(shù)據(jù)導(dǎo)入。
而且導(dǎo)入的時候需要做個分類,是導(dǎo)入到項目示例還是個人/團(tuán)隊項目。
常見的是打包下載 zip。這個大概需要后端處理,因此先找找有沒有前端處理的。
搜了一下方案,再結(jié)合 github 上一些項目的源碼,可以簡單的寫出一個導(dǎo)出模塊
export function exportFile(data: string, filename: string, type: string) { var typeList = { json: "application/json;charset=utf-8", markdown: "text/markdown;charset=utf-8", doc: "application/mswordcharset=utf-8", } // 創(chuàng)建隱藏的可下載鏈接 var eleLink = document.createElement("a"); eleLink.download = filename; eleLink.style.display = "none"; // 字符內(nèi)容轉(zhuǎn)變成blob地址 var blob ; blob= new Blob(["uFEFF" + data],{type: typeList[type]}); eleLink.href = URL.createObjectURL(blob); document.body.appendChild(eleLink); eleLink.click(); document.body.removeChild(eleLink); }
調(diào)用方式很簡單,就是傳入三個參數(shù):
exportFile(JSON.stringify(this.state.currentProjectData), "default.md", "markdwon")
當(dāng)然我們現(xiàn)在獲得的數(shù)據(jù)是沒有進(jìn)行處理的,我們需要對數(shù)據(jù)做個過濾,剔除一些關(guān)鍵信息以及沒必要的數(shù)據(jù)。
假設(shè)現(xiàn)在的數(shù)據(jù)是這樣的
{ "_id": "project001", "projectName": "演示項目 - REST接口示例超長字符串測試asd123", "projectUrl": "/project001", "projectDesc": "項目描述", "version": "v1.0", "transferUrl": "http://haoqiao.me/api/project", "status": "transfer", "type": "demo", "teamMember": [ { "_id": "user001", "username": "2333", "role": "前端工程師", "avatar": "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" }, { "_id": "user002", "username": "宋青樹", "role": "后端工程師", "avatar": "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" } ], "interfaceList": [ { "_id": "interface001", "interfaceName": "獲取", "url": "/getAll", "method": "get", "desc": "接口描述", "mode": "{data: 1 || 2}" }, { "_id": "interface002", "interfaceName": "增加", "url": "/add", "method": "post", "desc": "接口描述", "mode": "{data: 1 || 2}" }, { "_id": "interface003", "interfaceName": "刪除", "url": "/delete", "method": "delete", "desc": "接口描述", "mode": "{data: 1 || 2}" }, { "_id": "interface004", "interfaceName": "更新", "url": "/update", "method": "put", "desc": "接口描述", "mode": "{data: 1 || 2}" } ] }
我們需要將里面所有的 _id(字段), teamMember(數(shù)組) 去除。這里大家想想如果是自己要怎么處理?
其實非常簡單,只要你對原生的 JSON.stringify 比較熟悉,你就知道它的完整定義如下
JSON.stringify(value, replacer?, space?)
replacer 是一個過濾函數(shù)或則一個數(shù)組包含要被 stringify 的屬性名。如果沒有定義,默認(rèn)所有屬性都被 stringify。
可以做一個遍歷器,遍歷Json里的屬性名。然后內(nèi)部做個剔除。
比如這樣
filterData = (json: any) =>{ console.log(json) let expectArr = ["_id", "teamMember"] let filterArr = [] let result = "" for( let key in json){ if (expectArr.indexOf(key) === -1){ filterArr.push(key) } result = JSON.stringify(this.state.currentProjectData, filterArr) console.log(result) return result }
但這樣只能拿到第一層的屬性名,如何拿到嵌套的數(shù)組里的Json的屬性呢?
我們只需要再做個判斷就可以了
filterData = (json: any) =>{ console.log(json) let expectArr = ["_id", "teamMember"] let filterArr = [] let result = "" for( let key in json){ if (expectArr.indexOf(key) === -1){ filterArr.push(key) // 如果是嵌套數(shù)組,而且數(shù)組內(nèi)有數(shù)據(jù) if(Object.prototype.toString.call(json[key]) == "[object Array]" && json[key].length > 0){ for( let item in json[key][0]){ // 同樣對里面的json數(shù)據(jù)進(jìn)行屬性字段過濾 if (expectArr.indexOf(item) === -1){ filterArr.push(item) } } } } } result = JSON.stringify(this.state.currentProjectData, filterArr) console.log(result) return result }
這樣就把該有的屬性篩選出來了。然后做個轉(zhuǎn)換就能過濾只剩需要的數(shù)據(jù)。
數(shù)據(jù)清理后就變成如下格式
{ "_id": "project001", "projectName": "演示項目 - REST接口示例超長字符串測試asd123", "projectUrl": "/project001", "projectDesc": "項目描述", "version": "v1.0", "transferUrl": "http://haoqiao.me/api/project", "status": "transfer", "type": "demo", "teamMember": [ { "_id": "user001", "username": "2333", "role": "前端工程師", "avatar": "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" }, { "_id": "user002", "username": "宋青樹", "role": "后端工程師", "avatar": "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" } ], "interfaceList": [ { "_id": "interface001", "interfaceName": "獲取", "url": "/getAll", "method": "get", "desc": "接口描述", "mode": "{data: 1 || 2}" }, { "_id": "interface002", "interfaceName": "增加", "url": "/add", "method": "post", "desc": "接口描述", "mode": "{data: 1 || 2}" }, { "_id": "interface003", "interfaceName": "刪除", "url": "/delete", "method": "delete", "desc": "接口描述", "mode": "{data: 1 || 2}" }, { "_id": "interface004", "interfaceName": "更新", "url": "/update", "method": "put", "desc": "接口描述", "mode": "{data: 1 || 2}" } ] }
之后是要考慮導(dǎo)入項目,我首先想到點擊上傳 JSON 格式文件然后讀取里面的內(nèi)容,然后驗證數(shù)據(jù)再讓后臺將其導(dǎo)入到指定表中。
這里面發(fā)生了一些事情,比如我肯定不希望用戶真的把json文件上傳到服務(wù)器上,我覺得這玩意前端肯定能解析和解決,但是我們肯定還是需要一個上傳的按鈕和UI交互。
這里我直接用了 antd 的 upload 組件,它里面有個方法就是 beforeUpload , 只要我們在這個函數(shù)里直接返回 false 那么是不會真正觸發(fā)上傳動作的,但是我們又可以拿到本地的 File,可以用 HTML5 的新方法 FileReader 來幫助讀取內(nèi)容。
我們的組件可以這么修改
const uploadProps = { name: "file", action: "", showUploadList: false, beforeUpload: (file: any) => { const isJSON = file.type === "application/json"; if (!isJSON) { Message.error("只允許上傳JSON格式文件!"); } const isLt2M = file.size / 1024 / 1024 < 2; if (!isLt2M) { Message.error("JSON文件大小必須小于 2MB!"); } var reader = new FileReader(); // 讀取操作都是由FileReader完成的 var that = this reader.readAsText(file); reader.onload = function(){//讀取完畢從中取值 const json = this.result if(isJson(json) && that.state.uploadJsonData.length === 0){ that.setState({ uploadProject:true, uploadJsonData: json }) Message.success("Json文件上傳識別成功!"); } } return false; }}, onChange: (info: any) => { }, };
點擊上傳JSON文件或者拖拽上傳JSON文件
來看下實際的交互效果
這樣我們就打通了項目的導(dǎo)入導(dǎo)出功能的交互。之后就是接口對接一下就行了。
項目克隆 / 接口克隆這兩個功能其實很類似,主要是用于幫助用戶能夠復(fù)制已經(jīng)存在的接口或者項目。
比如我已經(jīng)之前建立了一套系統(tǒng)的接口,包括了增刪減改。我下一個系統(tǒng)和這套系統(tǒng)很類似,可能只需改幾個字段就可以用了。
我們當(dāng)然可以利用導(dǎo)入和導(dǎo)入功能,但是在系統(tǒng)內(nèi)部我們最好有一鍵遷移的方式,那就是克隆。
克隆我們需要注意,首先是接口克隆,假設(shè)我們接口定義的格式如下:
_id(pin): "interface005" interfaceName(pin): "注冊" url(pin): "/reg" method(pin): "post" desc(pin): "接口描述" mode(pin): "{data: 1 || 2}"
然后我為了方便定義的項目 Model 里面包含了接口 Model。
也就是我只需把 接口 Id,和 項目 Id 傳給后臺,讓后臺做一個查詢接口內(nèi)容,然后新建接口把查詢到的內(nèi)容插入到指定 Id 就可以了。
這很簡單。主要部分是 UI 這塊,不過通過對數(shù)據(jù)流的管理也是花時間就能解決的事情。如下圖:
之后是克隆項目這塊,
我們首先已經(jīng)知道項目 Model 里面包含了 接口 Model,因此我們克隆整個項目其實是需要將整個接口提取出來,團(tuán)隊成員是需要剔除的,因為新克隆項目應(yīng)該是只有創(chuàng)建者,因此我們需要把 用戶 Id 也從前端傳過去,當(dāng)然也可不傳,通過 Jwt 對 token 解析也能識別用戶信息。
主要是后端拿到信息之后它的思路應(yīng)該是先查詢這個項目的信息,然后提取部分信息創(chuàng)建新項目, 然后遍歷原有項目的接口列表,批量創(chuàng)建接口。
個人信息的更改基本上中后臺的應(yīng)用都會有個人信息管理這項,有的用表單,有的拆分。
其余數(shù)據(jù)都好搞定,無非是傳參的問題,前后端約定的問題。
當(dāng)然比較麻煩的其實是頭像的更改。
假設(shè)你注冊的時候默認(rèn)分配給一個用戶頭像,然后再個人信息里用戶想要更改。
這時候問題來了。更改頭像其實是一個交互問題,你肯定不能讓用戶一步步操作。而是一步到位,符合要求的圖片上傳之后,拿到上傳后的圖片地址。然后更改本地的數(shù)據(jù)。還需要在后臺自動更新數(shù)據(jù)。
這里是用 redux 維護(hù)了一個本地的前端數(shù)據(jù)層,所有顯示的變更顯示操作需要對其進(jìn)行更新。
然后是 reducer 里監(jiān)聽了動作, 定義為 UPDATE_LOCALXXX 的動作是用于提交數(shù)據(jù)后等待后臺處理完畢后返回成功,然后將本地的數(shù)據(jù)進(jìn)行更新。
顯而易見這個動作是異步操作。如果很多個類似操作需要管理我們代碼寫起來肯定會很亂。因此我在技術(shù)評估階段引入了 rxjs。
通過其特點時間線的管理,就很容易了。以下是簡單的示例代碼
export const userUpdate = (action$: any) => action$.ofType(UPDATE_USER) .mergeMap((action: any) => { return fetch.post(updateUser, action.data) // 登錄驗證情況 .map((response: any) => { console.log(response); if (response.state.code === 1) { updateUserSuccess(response.state.msg); return updateLocalUser(action.data); } else { console.log("token error") updateUserError(response.state.msg); return nothing(); } }) // 只有服務(wù)器崩潰才捕捉錯誤 .catch((e: any): any => { // console.log(e) return Observable.of(({ type: USER_LOGINERROR })).startWith(loadingError()) }) });結(jié)尾
還有一些功能需要等后端開發(fā)的時候再記錄思路,因此這部分先到這里。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/107283.html
摘要:前言最近一直在搗鼓畢設(shè),準(zhǔn)備做的是一個基于前后端開發(fā)的平臺,前期花了很多時間完成了功能模塊的交互。核心代碼就是這么一句。經(jīng)過各種猜想和測試,發(fā)現(xiàn)是模擬有問題。其實用的最終核心思路還是一樣的。 前言 最近一直在搗鼓畢設(shè),準(zhǔn)備做的是一個基于前后端開發(fā)的Mock平臺,前期花了很多時間完成了功能模塊的交互。現(xiàn)在進(jìn)度推到如何設(shè)計核心功能,也就是Mock數(shù)據(jù)的解析。 根據(jù)之前的需求設(shè)定加上一些思考...
摘要:前言最近一直在搗鼓畢設(shè),準(zhǔn)備做的是一個基于前后端開發(fā)的平臺,前期花了很多時間完成了功能模塊的交互。核心代碼就是這么一句。經(jīng)過各種猜想和測試,發(fā)現(xiàn)是模擬有問題。其實用的最終核心思路還是一樣的。 前言 最近一直在搗鼓畢設(shè),準(zhǔn)備做的是一個基于前后端開發(fā)的Mock平臺,前期花了很多時間完成了功能模塊的交互。現(xiàn)在進(jìn)度推到如何設(shè)計核心功能,也就是Mock數(shù)據(jù)的解析。 根據(jù)之前的需求設(shè)定加上一些思考...
摘要:前言最近一直在搗鼓畢設(shè),準(zhǔn)備做的是一個基于前后端開發(fā)的平臺,前期花了很多時間完成了功能模塊的交互。核心代碼就是這么一句。經(jīng)過各種猜想和測試,發(fā)現(xiàn)是模擬有問題。其實用的最終核心思路還是一樣的。 前言 最近一直在搗鼓畢設(shè),準(zhǔn)備做的是一個基于前后端開發(fā)的Mock平臺,前期花了很多時間完成了功能模塊的交互。現(xiàn)在進(jìn)度推到如何設(shè)計核心功能,也就是Mock數(shù)據(jù)的解析。 根據(jù)之前的需求設(shè)定加上一些思考...
閱讀 2600·2021-07-26 23:38
閱讀 3496·2019-08-30 13:10
閱讀 2392·2019-08-29 18:33
閱讀 2382·2019-08-29 16:12
閱讀 1075·2019-08-29 10:59
閱讀 1852·2019-08-26 17:40
閱讀 889·2019-08-26 11:59
閱讀 875·2019-08-26 11:41