【Flask】測試平臺開發,應用管理模塊實現-第十一篇

?概述

通過Element UI抽屜和表單校驗&增改接口合并實現應用管理

Drawer 抽屜

之前產品修改和添加是使用Dialog組件實現的,但這個組件有時候并不滿足我們的需求, 比如表單很長, 亦或是你需要臨時展示一些文檔, Drawer 是可以從側面彈出的一個層,可以容納更多的控件,優化交互體驗。基本用法

<el-drawertitle="我是從右到左側展示的抽屜":visible.sync="drawer"direction="rtl">這里可組合放其他組件Body部分
</el-drawer>
<!..script部分省略..>

顯示和隱藏通過 visible 屬性,類型是 boolean,當為 true 時顯示 Drawer。Drawer 分為兩個部分:title 和 body,title 可省略, direction為設置打開方向, Drawer 默認是從右往左打開,其他方向包括ltr(從左到右)、ttb(從上到下)、btt(從下往上),更多屬性事件參考官方[注解1]

Form 表單驗證

在之前的產品添加和修改功能都是直接提交的,一些驗證是在后端做的處理,正常情況下,前端提交數據的時候就要進行一些如非空校驗、是否為字符串、是否符合正則規則等,這里Form 組件是直接提供了表單驗證的功能,只需要通過 rules 屬性傳入約定的驗證規則,支持默認屬性綁定和自定義校驗。更多參考[注解2],示例代碼:

<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"><el-form-item label="綁定規則校驗對應prop屬性" prop="name"><el-input v-model="ruleForm.name"></el-input></el-form-item><el-form-item label="密碼自定義校驗" prop="pass"><el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input></el-form-item><el-form-item><el-button type="primary" @click="submitForm('ruleForm')">提交事件校驗</el-button><el-button @click="resetForm('ruleForm')">重置</el-button></el-form-item>
</el-form>
<script>export default {data() {var validatePass = (rule, value, callback) => {if (value === '') {callback(new Error('請輸入密碼'));} else {if (this.ruleForm.checkPass !== '') {this.$refs.ruleForm.validateField('checkPass');}callback();}},return {ruleForm: {name: '',checkPass:''},rules: {name: [{ required: true, message: '請輸入活動名稱', trigger: 'blur' },{ min: 3, max: 5, message: '長度在 3 到 5 個字符', trigger: 'blur' }],pass: [{ validator: validatePass, trigger: 'blur' }]}};},methods: {submitForm(formName) {// 這里是提交前觸發校驗this.$refs[formName].validate((valid) => {if (valid) {alert('submit!');} else {console.log('error submit!!');return false;}});},resetForm(formName) {// 清除所有校驗提示this.$refs[formName].resetFields();}}}
</script>

1)表單通過 :rules="rules" ref="ruleForm"進行數據和屬性綁定

2)行項目中 prop=""去綁定規則對應的key,這里最好數據和驗證的key保持一致

3)基本屬性配置包括是否必須,字符的長短等,詳細參考規則async-validator

  1. 自定義規則是一些較為復雜的校驗通過回調進行邏輯自定義,參考例子第二個form-item

5)上述被定義required: true規則的控件在會自動增加 紅色*號,trigger 定義什么時候觸發校驗

開發頁面

此頁面添加/修改功能需求說明:

  • 點擊添加/編輯彈抽屜,紅色為必填選項

  • 分類來源歸屬分類,外鍵關聯

  • 應用名稱有重名校驗,創建后不可以修改

  • 默認必須有測試、研發和產品負責人,多人郵件用;分隔

  • 目前要求必須填寫代碼地址,以便測試人員了解信息,編寫測試code

  • 以上數據字符長度暫無限制

功能實現(步驟)偽代碼

  1. Python Flask 編寫一個接口同時實現添加和修改數據功能

  2. 創建抽屜控件,內嵌form,實現原型中的各控件綁定

  3. 控件紅色*標記的規則配置,觸發方式trigger: 'blur'即點擊提交統一校驗,

  4. 頁面修改和添加使用同一個Drawer 標題根據上一步操作動態顯示 “應用添加” / “應用編輯”

  5. 應用編輯的自增ID不需要顯示,應用ID不可編輯

實踐參考實現

  1. 應用增改接口實現

這個合并接口的實現核心的邏輯點就是根據前端是否傳了數據庫id主鍵,如果有便認為是歷史數據,走修改操作,否則走添加邏輯,完整代碼和說明見代碼:

@app_application.route("/api/application/update",methods=['POST'])
def product_update():# 獲取傳遞的數據,并轉換成JSONbody = request.get_data()body = json.loads(body)# 定義默認返回體resp_success = format.resp_format_successresp_failed = format.resp_format_failed# 判斷必填參數if 'appId' not in body:resp_failed['message'] = '應用不能為空'return resp_failedelif 'tester' not in body:resp_failed['message'] = '測試負責人不能為空'return resp_failedelif 'developer' not in body:resp_failed['message'] = '測試負責人不能為空'return resp_failedelif 'producer' not in body:resp_failed['message'] = '產品負責人不能為空'returnif not body.get('note'):body['note'] = ''if not body.get('cCEmail'):body['cCEmail'] = ''if not body.get('gitCode'):body['gitCode'] = ''if not body.get('wiki'):body['wiki'] = ''if not body.get('more'):body['more'] = ''if not body.get('createUser'):body['createUser'] = ''if not body.get('updateUser'):body['updateUser'] = ''# 使用連接池鏈接數據庫connection = pool.connection()# 判斷增加或是修改邏輯with connection:# 如果傳的值有ID,那么進行修改操作,否則為新增數據if 'id' in body and body['id'] != '':with connection.cursor() as cursor:# 拼接修改語句,由于應用名不可修改,不需要做重復校驗appIdsql = "UPDATE `apps` SET `productId`=%s, `note`=%s,`tester`=%s,`developer`=%s,`producer`=%s,`cCEmail`=%s, " \"`gitCode`=%s, `wiki`=%s, `more`=%s, `updateUser`=%s, `updateDate`= NOW() WHERE id=%s"cursor.execute(sql, (body["productId"], body["note"], body["tester"], body["developer"], body['producer'], body["cCEmail"],body["gitCode"], body["wiki"], body["more"], body["updateUser"], body["id"]))# 提交執行保存更新數據connection.commit()else:# 新增需要判斷appId是否重復with connection.cursor() as cursor:select = "SELECT * FROM `apps` WHERE `appId`=%s AND `status`=0"cursor.execute(select, (body["appId"],))result = cursor.fetchall()# 有數據說明存在相同值,封裝提示直接返回if len(result) > 0:resp_failed["code"] = 20001resp_failed["message"] = "唯一編碼keyCode已存在"return resp_failedwith connection.cursor() as cursor:# 拼接插入語句,并用參數化%s構造防止基本的SQL注入# 其中id為自增,插入數據默認數據設置的當前時間sql = "INSERT INTO `apps` (`appId`,`productId`,`note`,`tester`,`developer`,`producer`,`cCEmail`,`gitCode`" \",`wiki`,`more`,`createUser`,`updateUser`) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"cursor.execute(sql, (body["appId"],body["productId"], body["note"], body["tester"], body["developer"], body['producer'],body["cCEmail"],body["gitCode"],body["wiki"],body["more"],body["createUser"],body["updateUser"]))# 提交執行保存新增數據connection.commit()return resp_success
  • 組合表單的抽屜控件實現

在app.vue 代碼文件<script></script> 添加綁定數據和基本規則

1)不要忘記登錄人的變量導入

2)規則和請求變量的key一定確保一致

3)除了選擇框未改變時候觸發校驗,其他都使用提交時候再做統一校驗

data() {return {
// 獲得登錄的名字op_user: store.getters.name,// 定義動作appAction: 'ADD',// 控制抽屜顯示隱藏drawerVisible: false,// 添加/修改綁定的數據appInfo: {id: '',appId: '',productId: '',note: '',tester: '',developer: '',producer: '',cCEmail: '',gitCode: '',wiki: '',more: '',createUser: '',updateUser: ''},// 規則設定rules: {appId: [{ required: true, message: '請輸應用名稱', trigger: 'blur' }],productId: [{ required: true, message: '請選擇所屬范圍', trigger: 'change' }],tester: [{ required: true, message: '請輸入測試負責人', trigger: 'blur' }],developer: [{ required: true, message: '請輸入開發負責人', trigger: 'blur' }],producer: [{ required: true, message: '請輸入產品負責人', trigger: 'blur' }]}}
}

在app.vue 代碼文件 <div class="app-container"> </div>內編寫組合控件

1)標題和appId是否可編輯根據 appAction 判斷根據

2)歸屬分類沿用搜索里的下拉實現,也可以使用基本方式

3)實現規則一定注意el-form-item 中 prop 的定義和一致性

<el-drawer:title="appAction==='ADD'? '添加應用': '修改應用'":visible.sync="drawerVisible"size="45%"direction="rtl"><div><el-form :model="appInfo" :rules="rules" ref="appInfo" label-width="120px"><el-form-item label="應用ID" prop="appId" ><el-input v-model="appInfo.appId" :disabled="appAction==='ADD'? false : true" style="width: 300px"/></el-form-item><el-form-item label="歸屬分類" prop="productId"><el-select v-model="appInfo.productId" style="width: 300px"><el-optionv-for="item in options":key="item.id":label="item.title":value="item.id"><span style="float: left">{{ item.keyCode }}</span><span style="float: right; color: #8492a6; font-size: 13px">{{ item.title }}</span></el-option></el-select></el-form-item><el-form-item label="應用描述"><el-input v-model="appInfo.note" style="width: 300px"/></el-form-item><el-form-item label="測試負責" prop="tester"><el-input v-model="appInfo.tester" style="width: 300px"/></el-form-item><el-form-item label="研發負責" prop="developer"><el-input v-model="appInfo.developer" style="width: 300px"/></el-form-item><el-form-item label="產品負責" prop="producer"><el-input v-model="appInfo.producer" style="width: 300px"/></el-form-item><el-form-item label="默認抄送"><el-input v-model="appInfo.cCEmail" style="width: 300px"/></el-form-item><el-form-item label="代碼地址"><el-input v-model="appInfo.gitCode" style="width: 300px"/></el-form-item><el-form-item label="相關wiki"><el-input v-model="appInfo.wiki" style="width: 300px"/></el-form-item><el-form-item label="更多信息"><el-input v-model="appInfo.more" style="width: 300px"/></el-form-item><el-form-item><span class="dialog-footer"><el-button @click="drawerVisible=false">取 消</el-button><el-button type="primary" @click="commitApp('appInfo')">提 交</el-button></span></el-form-item></el-form></div>
</el-drawer>
  • 實現接口請求

在app.js 定義/api/application/update接口模版請求

// 調用應用增加/修改統一接口
export function apiAppsCommit(requestBody) {return request({url: '/api/application/update',method: 'post',data: requestBody})
}

在app.vue 代碼文件<script></script> 實現添加和修改請求方法

1)addApp上節的占位的方法體,這里要實現信息清空和動作定義

2)updateApp 同樣,實現選擇的數據反填和遺留信息清空基本操作

3)請求后端接口要在所有規則校驗通過后才進行真正的提交

addApp() {// 定義動作,以抽屜做判斷this.appAction = 'ADD'// 添加數據初始化this.appInfo.id = ''this.appInfo.appId = ''this.appInfo.productId = ''this.appInfo.note = ''this.appInfo.tester = ''this.appInfo.developer = ''this.appInfo.producer = ''this.appInfo.cCEmail = ''this.appInfo.gitCode = ''this.appInfo.wiki = ''this.appInfo.more = ''this.appInfo.createUser = this.op_userthis.appInfo.updateUser = this.op_user// 初始化完成后顯示抽屜this.drawerVisible = true// 如果有遺留驗證清空this.$nextTick(() => {this.$refs['appInfo'].resetFields()})},updateApp(row) {// 定義動作,以抽屜做判斷this.appAction = 'UPDATE'// 初始化完成后顯示抽屜this.drawerVisible = true// 如果有遺留驗證清空this.$nextTick(() => {this.$refs['appInfo'].resetFields()})// 選擇數據反填抽屜表單中this.appInfo.id = row.idthis.appInfo.appId = row.appIdthis.appInfo.productId = row.productIdthis.appInfo.note = row.notethis.appInfo.tester = row.testerthis.appInfo.developer = row.developerthis.appInfo.producer = row.producerthis.appInfo.cCEmail = row.cCEmailthis.appInfo.gitCode = row.gitCodethis.appInfo.wiki = row.wikithis.appInfo.more = row.morethis.appInfo.createUser = ''this.appInfo.updateUser = row.updateUser},commitApp() {// 上邊form定義ref,驗證通過if valid的方式判斷this.$refs['appInfo'].validate((valid) => {if (valid) {this.appInfo.updateUser = this.op_userapiAppsCommit(this.appInfo).then(response => {// 如果request.js沒有攔截即表示成功,給出對應提示和操作this.$notify({title: '成功',message: this.appAction === 'ADD' ? '應用添加成功' : '應用修改成功',type: 'success'})// 關閉對話框this.drawerVisible = false// 重新查詢刷新數據顯示this.getProductList()})} else {return false}})}
  • 聯調前后端運行

分別運行前后端,解決掉運行中的錯誤后,做兩條測試驗證功能是否OK

1)添加操作,默認為空數據,提交不完整信息是否有校驗提示阻止提交

2)編輯操作,數據是否正常反填,修改后提交是否正常更新落庫

至此添加服務應用管理產品管理的功能模塊我們就開發完成了,下一階段我們將繼續開發新的功能菜單欄--測試管理模塊

【注解&參考】

  • [注解1] https://element.eleme.io/#/zh-CN/component/drawer

  • [注解2] https://element.eleme.io/#/zh-CN/component/form#biao-dan-yan-zheng

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

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

相關文章

Elasticsearch 深分頁限制與解決方案

最近在準備面試&#xff0c;正把平時積累的筆記、項目中遇到的問題與解決方案、對核心原理的理解&#xff0c;以及高頻業務場景的應對策略系統梳理一遍&#xff0c;既能加深記憶&#xff0c;也能讓知識體系更扎實&#xff0c;供大家參考&#xff0c;歡迎討論。在項目中遇到一個…

基于偏最小二乘法PLS多輸入單輸出的回歸預測【MATLAB】

基于偏最小二乘法&#xff08;PLS&#xff09;多輸入單輸出的回歸預測【MATLAB】 在科學研究和工程實踐中&#xff0c;我們常常需要根據多個相關變量來預測一個關鍵結果。例如&#xff0c;根據氣溫、濕度、風速等多個氣象因素預測空氣質量指數&#xff0c;或根據多種原材料成分…

SQL Server核心架構深度解析

SQL Server 的體系結構是一個復雜但設計精密的系統&#xff0c;主要可以分為四大核心組件&#xff0c;它們協同工作以管理數據庫、處理查詢、確保數據安全與一致性。以下是其體系結構的核心組成部分&#xff1a; 核心組件&#xff1a;協議層 (Protocol Layer) 作用&#xff1a;…

Django REST Framework Serializer 進階教程

1. 序列化器概述 在 Django REST Framework&#xff08;DRF&#xff09;中&#xff0c;序列化器&#xff08;Serializer&#xff09;用于將復雜的數據類型&#xff08;如模型實例&#xff09;轉換為 JSON 格式&#xff0c;以便于 API 返回給客戶端。此外&#xff0c;序列化器還…

面試問題詳解十四:Qt 多線程同步【QSemaphore】講解

在多線程開發中&#xff0c;經常需要控制多個線程對共享資源的訪問數量。例如限制同時下載文件的數量、控制數據庫連接池的連接使用等等。這時候&#xff0c;Qt 提供的 QSemaphore&#xff08;信號量&#xff09;就非常派得上用場。一、什么是 QSemaphore&#xff1f; QSemapho…

Spark mapGroups 函數詳解與多種用法示例

mapGroups 是 Spark 中一個強大的分組操作函數&#xff0c;它允許你對每個分組應用自定義邏輯并返回一個結果。以下是多個使用簡單樣例數據的具體用法示例。基礎示例數據假設我們有一個簡單的學生成績數據集&#xff1a;// 創建示例DataFrame val studentScores Seq(("Ma…

【圖論】Graphs.jl 圖數據的讀寫與生成器

文章目錄圖數據的讀寫Graphs.loadgraphGraphs.loadgraphsGraphs.savegraph保存單個圖保存圖字典Graphs.loadlg_multGraphs.savelgGraphs.savelg_mult圖的生成器1. 隨機圖模型1.1 Erd?s–Rnyi 模型1.2 巴拉巴西-阿爾伯特模型 (無標度網絡)1.3 小世界網絡模型1.4 隨機塊模型 (SB…

Go指針全解析:從基礎到實戰

基本概念與定義指針的定義指針是一種特殊的變量類型&#xff0c;它存儲的不是實際數據值&#xff0c;而是另一個變量在計算機內存中的地址。在底層實現上&#xff0c;指針本質上是保存內存位置的無符號整數&#xff0c;它直接指向內存中的特定位置&#xff0c;允許程序直接操作…

Oracle 查詢有哪些用戶 提示用戶名密碼無效

要查詢 Oracle 數據庫中的所有用戶&#xff0c;可以使用以下 SQL 查詢語句。這個查詢將返回數據庫中所有用戶的列表。 [] SELECT username FROM all_users ORDER BY username;如果你有足夠的權限&#xff08;通常是 DBA 權限&#xff09;&#xff0c;你也可以使用 dba_users 視…

小白成長之路-develops -jenkins部署lnmp平臺

文章目錄一、準備工作1.1兩臺虛擬機1.2配置文件1.3免密登錄二、實戰1.構建主item2.測試nginx,php,mysql2.1新建測試項目2.2與正式項目綁定構建后的操作2.3測試2.4導入discuz項目總結一、準備工作 1.1兩臺虛擬機 服務器&#xff1a;192.168.144.24 客戶端&#xff1a;192.168.…

【HarmonyOS 6】仿AI喚起屏幕邊緣流光特效

【HarmonyOS 6】仿AI喚起屏幕邊緣流光特效 一、前言 最近在做 HarmonyOS 6.0 的適配&#xff0c;發現 Beta1版本里多了個很實用的視效功能——自帶背景的雙邊流光。 之前做屏幕邊緣流光特效的時候&#xff0c;要么得自己寫漸變動畫拼效果&#xff0c;要么就得套好幾個組件疊層&…

跟做springboot尚品甄選項目

springbootvue3 【尚硅谷Java項目《尚品甄選》 SpringBootSpringCloud萌新學會企業級java項目】003.后臺系統-搭建前端環境&#xff08;工程創建&#xff09;_嗶哩嗶哩_bilibili E:\project\AllProJect\Shangpin Selection\項目材料素材\課件\尚品甄選項目課件 前端套用框架…

【Linux】創建線程

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 文章目錄 一、為什么需要線程&#xff1f; 創建線程 示例&#xff1a;計算斐波恩夕法 一、為什么需要線程&#xff1f; 在多核處理器的計算機上&#xff0c;線程可…

HTML應用指南:利用POST請求獲取全國九號電動車體驗店服務店位置信息

九號公司(Ninebot)作為全球領先的智能短途出行解決方案提供商,始終秉持“智慧移動,愉悅生活”的品牌理念,致力于為個人用戶打造安全、智能、時尚的城市出行體驗。依托“智能硬件 + 數字服務 + 線下觸點”三位一體的戰略布局,九號公司已建立起覆蓋全國、輻射全球的銷售與服…

Kafka面試精講 Day 4:Consumer消費者模型與消費組

【Kafka面試精講 Day 4】Consumer消費者模型與消費組 在“Kafka面試精講”系列的第四天&#xff0c;我們將深入探討Kafka的核心組件之一——Consumer消費者模型與消費組&#xff08;Consumer Group&#xff09;。這是Kafka實現高吞吐、可擴展消息消費的關鍵機制&#xff0c;也…

使用 Uni-app 打包 外鏈地址APK 及 iOS 注意事項

本文詳細介紹了如何使用 Uni-app 框架將項目打包為 Android APK 和 iOS 應用&#xff0c;重點講解了 minSdkVersion、targetSdkVersion 和 abiFilters 的配置&#xff0c;以及 iOS 開發的注意事項。文章還包含了您提供的 WebView 示例代碼&#xff0c;并提供了關鍵的注意事項&a…

異常處理小妙招——3.構造函數的安全第一原則:為什么不在構造函數中拋出異常?

文章目錄災難性的生日派對構造函數&#xff1a;對象的出生證明安全第一&#xff1a;嚴格的出生檢查為什么要在構造函數中嚴格驗證&#xff1f;1. 避免"僵尸對象"2. Fail-Fast&#xff08;快速失敗&#xff09;原則現實世界的實踐建議1. 使用工廠方法模式2. 使用Build…

iptables 和 ip route

文章目錄iptables原理及常用命令表鏈鏈表鏈表總結iptables 常用命令及參數1. 規則管理命令 (Commands)2. 規則匹配參數 (Rule-Specification - Matches)3. 目標動作參數 (Target)命令示例配置流程示例ip route常用命令iptables和ip route的聯系實用命令示例對比iptables原理及常…

RPC和HTTP的區別?

RPC和HTTP是兩種不同的通信協議&#xff0c;它們在通信方式、性能效率以及靈活性可擴展性等方面存在區別。以下是具體分析&#xff1a; 通信方式 RPC&#xff1a;RPC是基于遠程過程調用的二進制協議&#xff0c;它允許客戶端像調用本地函數一樣調用遠程服務器上的函數或方法[2]…

貝葉斯分類(Bayes Classify)

一. 核心思想貝葉斯分類是一類基于貝葉斯定理&#xff08;Bayes Theorem&#xff09;和概率統計的分類算法&#xff0c;核心思想是 “通過已知的先驗概率&#xff0c;結合數據的似然性&#xff0c;計算后驗概率&#xff0c;最終將樣本歸為后驗概率最高的類別”。它在機器學習、…