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

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

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

本篇掌握功能点:

  • 后端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 

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-icon-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字段表明消息类型,可以为 successerrorinfo 和 warning 更多定制属性可直接参考官方,详细代码和说明如下(methods):

      // 对应的参数是 (提示内容,标题 {自定义确定按钮文案,自定义取消按钮文案, 对话框类型}
      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

 

【官方文档参考】

 

【系列前要阅读】

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

posted @ 2021-08-13 21:39  MrZ大奇  阅读(191)  评论(0编辑  收藏  举报