您的位置:首页 > 其它

测试开发【提测平台】分享6-产品线修改和软硬删除功能实现

2021-08-13 21:39 836 查看

微信搜索【大奇测试开】,关注这个坚持分享测试开发干货的家伙。

学习建议还是要多动手做,用一首歌的时间看,用半小时去实际实现,才能事半功倍!

本篇掌握功能点:

  • 后端python实现数据库更新逻辑接口
  • 前端<el-link>文字链接组件实现表菜单操作
  • 前端slot-scope插件槽获取Table的行数据
  • 前端控件v-if 和:实现动态判断
  • 后端删除软和硬两种实现方法
  • 前端掌握$confirm执行前的确认组件

项目/产品线修改功能实现

服务端实现更新接口

Flask更新接口实现

更新接口实现可以直接参考上节的添加操作,只是将数据库insert变成根据id条件update操作,更新的时候也需要进行重复的校验,代码如下

# [POST方法]实现新建数据的数据库插入
@app_product.route("/api/product/update",methods=['POST'])
def product_update():

# 按返回模版格式进行json结果返回
resp_data = {
"code": 20000,
"message": "success",
"data": []
}

# 获取请求传递json
body = request.get_data()
body = json.loads(body)
# 初始化数据库链接
connection = connectDB()

with connection:
with connection.cursor() as cursor:
select = "SELECT * FROM `products` WHERE `keyCode`=%s"
cursor.execute(select, (body["keyCode"],))
result = cursor.fetchall()

# 有数据并且不等于本身则为重复,封装提示直接返回
if len(result) > 0 and result[0]["id"] != body["id"]:
resp_data["code"] = 20001
resp_data["message"] = "唯一编码keyCode已存在"
return resp_data

# 如果没有重复,定义新的链接,进行更新操作
with connection.cursor() as cursor:
# 拼接更新语句,并用参数化%s构造防止基本的SQL注入
# 条件为id,更新时间用数据库NOW()获取当前时间
sql = "UPDATE `products` SET `keyCode`=%s, `title`=%s,`desc`=%s,`operator`=%s, `update`= NOW() WHERE id=%s"
cursor.execute(sql, (body["keyCode"], body["title"], body["desc"], body["operator"], body['id']))
# 提交执行保存更新数据
connection.commit()

return resp_data[code] 

Vue页面实现修改

优化对话框表单 修改操作的页面由于之前添加的时候都进行过el-dialog绑定,这的修改对话框可以共用的,只需要定义个状态变量,然后标题通过对属性前加:冒号,以及组件的显示和隐藏通过组件中使用v-if进行判断显示和隐藏,这两种的作用跟语法的if 是一个道理;

  • : 是vue中v-bind的语法糖缩写,作用可以使标签动态绑定

  • v-if 是判断语句,它还可以和v-else-if ,v-else 配合使用

  • 需要修改的点

    1.  <el-diglog> 中的title动态设置的变量值动态显示,注意判断语法 === (使用三个等于号)
    2. 增加一行表单并在 dialogProductStatus 是更新操作的时候显示
    3. 增加一个修改按钮,并同时优化添加按钮,根据状态决定显示

    表格中操作菜单 表格控件中增加一列,列里增加一个编辑按钮,使用组件 Link 文字链接,并带个icon

    基本语法:<el-link icon="el-icon-edit"></el-link>

     

    另外我们在修改操作的时候是对本行进行操作的,要想获取本行的数据,并透传给调用方法,需要使用vue里一个叫插件槽的东西

    基本语法:<template slot-scope="scope"></template>

    几个要掌握的关键点已经大致说完,剩下我直接给api和方法的代码

      product.js 增加更新请求接口

    export function apiProductUpdate(requestBody) {
    return request({
    url: '/api/product/update',
    method: 'post',
    data: requestBody
    })
    }


    product.vue中js 增加方法引用和状态变量

    // <script>...</script> 头部追加
    import { apiProductList, apiProductCreate, apiProductUpdate } from '@/api/product'
    
    // data() { return {...} } 内添加
    dialogProductStatus: 'ADD',
    
    

     methods:{中实现dialogProductUpdate()}

    // 获取当前编辑行数数据并赋值给product
    dialogProductUpdate(row) {
    // 添加先初始化空状态
    this.product.id = row.id
    this.product.keyCode = row.keyCode
    this.product.title = row.title
    this.product.desc = row.desc
    this.product.operator = this.op_user
    
    // 标记弹窗是修改操作
    this.dialogProductStatus = 'UPDATE'
    // 弹出对话框设置为true
    this.dialogProductShow = true
    },

     

    methods:{ 实现 pUpdate() }

    pUpdate() {
    apiProductUpdate(this.product).then(res => {
    this.$notify({
    title: '成功',
    message: '项目或产品修改成功',
    type: 'success'
    })
    // 关闭对话框
    this.dialogProductShow = false
    // 重新查询刷新数据显示
    this.getProductList()
    })
    }


    联调运行修改

    前后端重新启动,运行查看效果如下:

    需要进行一下简单的测试:

    CASE1:  修改名称和备注 - 验证保存成功

    CASE2: 修改唯一编号其他项目存在 - 验证提示已经存在不保存

     

    后端实现删除功能

    实现硬删除功能

    1.服务端实现Delete删除逻辑接口

    按照标准的RefAPI,通过定义methods = delete方法定义请求接口,参数只需要对应数据的id即可,这里并增加一个请求是否传了id的参数校验,这个接口是真正的数据删除,即所谓的硬删除,这个实现当中额外增加一个参数校验的逻辑,具体的实现代码如下:

    # [DELETE方法]根据id实际删除项目信息
    @app_product.route("/api/product/delete", methods=['DELETE'])
    def product_delete():
    # 返回的reponse
    resp_data = {
    "code": 20000,
    "message": "success",
    "data": []
    }
    # 方式1:通过params 获取id
    ID = request.args.get('id')
    # 做个参数必填校验
    if ID is None:
    resp_data["code"] = 20002
    resp_data["message"] = "请求id参数为空"
    return resp_data
    # 重新链接数据库
    connection = connectDB()
    with connection.cursor() as cursor:
    sql = "DELETE from `products` where id=%s"
    cursor.execute(sql, ID)
    connection.commit()
    return resp_data

    其实一个好的后端接口是需要增加各种校验的,保证代码的健壮性,可以每个方法自己写,也可以采用统一的异常处理形式。

     

    2.前端实现删除功能

    按照之前修改,我们在产品项目管理的菜单处增加一个删除的el-link并给定一个待实现的方法 pHardRemove(),其中scope.row.id表所在行数据的ID值

    <el-link icon="el-ic
    25f4
    on-delete" @click="pHardRemove(scope.row.id)">删除</el-link>

     接着继续按照规定模式js实现接口请求定义,vue删除方引用和实现

    src/api/product.js 增加代码

    // 调用真实删除数据库接口
    export function apiProductDelete(id) {
    return request({
    url: '/api/product/delete',
    method: 'delete',
    params: {
    'id': id
    }
    })
    }

     

    在 src/view/product/product.vue 的methods{ 实现pHarRemove }

    最先不要忘记接口方法引用

    import { apiProductDelete } from '@/api/product'

    在这里的删除逻辑里一般要给个二次确认是否进行操作,使用的是组件 MessageBox 弹框 中 确认消息 功能是提示用户确认其已经触发的动作,并询问是否进行此操作,确认继续执行或者取消此操作,调用的是

    $confirm
    对应可设置
    type
    字段表明消息类型,可以为 
    success
    error
    info 
    和 
    warning 
    更多定制属性可直接参考官方,详细代码和说明如下(methods):

    pHardRemove(id) {
    // 对应的参数是 (提示内容,标题 {自定义确定按钮文案,自定义取消按钮文案, 对话框类型}
    this.$confirm('此操作将永久删除该项目, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
    // then 点击confirmButton后执行的方法,否则是不执行关闭对话框
    }).then(() => {
    // vue click时候传d的id需要定义参数
    apiProductDelete(id).then(res => {
    this.$message({
    type: 'success',
    message: '删除成功!'
    })
    // 重新查询刷新数据显示
    this.getProductList()
    })
    }).catch(() => {
    this.$message({
    type: 'info',
    message: '已取消删除'
    })
    })
    }

     

    3. 运行测试硬删除

    后端IDE运行或者运行命令 # TPMServer路径下

    $ python3 app.py

    前端IDE运营或者运行命令 # TPMWeb 路径下

    $ npm run dev

    点击"删除"后的界面如下

     进行用例测试

    CASE1 : 选择任意行点删除,对话框选择取消,验证取消成功数据未删除

    CASE2: 添加一行数据,再选择删除-确定,验证查看新增的数据已删除 ,同步需确认数据库表中是否真删除

     

    优化实现软删除

    在通常的业务操作中数据都不是真的删除的,尤其像产品/项目这种会有下游依赖的数据,一般做法都是表数据增加对应的状态字段,用数字或者字符表示状态,所需要做的操作就是“删除”触发的是更新操作,这里我们叫“停用”更为合适一些,这也就是所谓的软删除,仅标记状态不做实际数据删除。

    1. 数据库优化products表

    需要对TPMStore数据中products表增加字段status,其中默认数字 0 为有效数据,数字 1 为已停用数据

    alter table products add status int default 0 not null comment '状态有效0,无效0' after `desc`;优化查询接口

     

    2. 后端实现软删除接口

    参考产品修改接口实现对应的如下代码,注意同上边一样,需要增加个参数校验逻辑

    # [POST方法]根据id更新状态项目状态,做软删除
    @app_product.route("/api/product/remove", methods=['POST'])
    def product_remove():
    # 返回的reponse
    resp_data = {
    "code": 20000,
    "message": "success",
    "data": []
    }
    ID = request.args.get('id')
    # 做个参数必填校验
    if ID is None:
    resp_data["code"] = 20002
    resp_data["message"] = "请求id参数为空"
    return resp_data
    # 重新链接数据库
    connection = connectDB()
    with connection.cursor() as cursor:
    # 状态默认正常状态为0,删除状态为1
    # alter table products add status int default 0 not null comment '状态有效0,无效0' after `desc`;
    sql = "UPDATE `products` SET `status`=1 WHERE id=%s"
    cursor.execute(sql, ID)
    connection.commit()
    
    return resp_data
     

    3. 后端优化其他接口

    由于表增加了一个标记状态字段,其他的已实现的接口我们需要做下优化处理,其中 查询接口需要修改查询语句增加条件过滤 status = 0 即只返回有效的数据

    # 查询产品信息表-按更新时间新旧排序 且 状态为0有效
    sql = "SELECT * FROM `products` WHERE `status`=0 ORDER BY `update` DESC"

     

    在新增product_create和更新接口方法 product_update() 中的 查重语句增加状态条件有效,即已停用的keycode不应该算作重复(这里前提业务需求是停用不可恢复)

    # 查询需要过滤状态为有效的 且 状态为0有效
    select = "SELECT * FROM `products` WHERE `keyCode`=%s AND `status`=0"

     

    4.前端实现软删除

    页面参考上边的流程和编码,分别是增加新的 el-link 动作按钮、接口请求定义、vue实现删除,这里不在多赘述,稍作改动,代码如下:

    product.js部分

    // 软删除,更改数据状态
    export function apiProductRemove(id) {
    return request({
    url: '/api/product/remove',
    method: 'post',
    params: {
    'id': id
    }
    })
    }

    product.vue <template> 部分

    <el-link icon="el-icon-delete" @click="pSoftRemove(scope.row.id)">停用</el-link>

    product.vue js部分

    import { apiProductRemove } from '@/api/product'
    pSoftRemove(id) {
    this.$confirm('此操作将停用不显示, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
    }).then(() => {
    apiProductRemove(id).then(res => {
    this.$message({
    type: 'success',
    message: '删除成功!'
    })
    // 重新查询刷新数据显示
    this.getProductList()
    })
    }).catch(() => {
    this.$message({
    type: 'info',
    message: '已取消删除'
    })
    })
    }

     

    5.前后端联调

    重新运行前后端,便可看到最终实现界面

    同样写完程序要进行必要测试

    CASE1 : 选择任意行点停用,对话框选择取消,验证取消成功数据未删除

    CASE2: 选择任意数据删除-确定,验证页面刷新正常和删除数据不显示 ,同步需确认数据库表中数据并未删除,只是标记status为1

    CASE3: 新增和修改的填写已删除数据的keyCode,验证添加和更新正常

     

    【代码更新】

    地址:https://github.com/mrzcode/TestProjectManagement

    TAG:TPMShare6

     

    【官方文档参考】

     

    【系列前要阅读】

    原创不易,经过实践的总结分享更不易,如果你觉得有用,请点击推荐,也欢迎关注我博客园和微信公众号。 

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: 
    相关文章推荐