Selenium

Selenium是一个用于Web应用程序测试工具。Selenium测试直接运行浏览器中,就像真正的用户操作一样。支持浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera,Edge等。这个工具的主要功能包括:测试浏览器兼容性——测试应用程序是否能够很好得工作在不同浏览器操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求支持自动录制动作自动生成.Net、Java、Perl等不同语言测试脚本

结果预览

在这里插入图片描述

在这里插入图片描述

实现使用框架

django+ selenium + vue

服务端代码

django models配置

class UI_case(models.Model):
    address = models.TextField("启动页面地址", null=False, default="")
    value = models.JSONField("执行值", null=False, default=dict)
    # value = [{"name": "每个元素名称", "xpath": "xpath地址", "iframe":"0不是iframe,1是iframe", "event": "事件类型", "value": "输入值" ,"wait_time":" 等待时间"}]
    update_time = models.DateTimeField("更新时间", auto_now=True)
    create_time = models.DateTimeField("创建时间", auto_now_add=True)
    user = models.ForeignKey(Userinfo, on_delete=models.CASCADE)

    def __str__(self):
        return self.value


class UI_case_result(models.Model):
    result = models.TextField("执行结果", null=False, default="")
    result_type = models.IntegerField("结果类型", null=False, default=1)  # 1.执行结果, 2.截图
    create_time = models.DateTimeField("创建时间", auto_now_add=True)
    ui = models.ForeignKey(UI_case, on_delete=models.CASCADE)

    def __str__(self):
        return self.result

服务端逻辑代码

import json
from datetime import datetime
from django.http import JsonResponse
from lapi_app.models.testcase_model.testcase_tree import Menu
from lapi_app.models.ui_model.ui_case import UI_case

# 获取UI自动化列表信息
def ui_ifo(request):
    global ui_dict, ui_result, update_time, create_time, ui_id, user_name, address
    try:
        data = json.loads(request.body)
        menu_id = data["id"]
        menu = Menu.objects.filter(id=menu_id)
        for i in menu:
            case = UI_case.objects.filter(id=i.ui_id)
            ui_id = i.ui_id
            for j in case:
                address = j.address
                user_name = j.user.account
                update_time, create_time = datetime.strftime(j.create_time, "%Y-%m-%d %H:%M:%S"), datetime.strftime(
                    j.update_time, "%Y-%m-%d %H:%M:%S")
                if j.value:
                    ui_result = j.value
                else:
                    ui_result = []
        return JsonResponse({
            "code": 200,
            "message": "获取用例信息成功",
            "address": address,
            "ui_id": ui_id,
            "content": ui_result,
            "update_time": update_time,
            "create_time": create_time,
            "username": user_name
        })
    except Exception as e:
        return JsonResponse({
            "code": 100,
            "message": str(e)
        })


# 编辑UI自动化列表信息
def edit_ui_info(request):
    try:
        data = json.loads(request.body)
        id = data["id"]
        value = data["value"]
        UI_case.objects.filter(id=id).update(value=value, address=data["address"], update_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        return JsonResponse({
            "code": 200,
            "message": "编辑成功"
        })
    except Exception as e:
        return JsonResponse({
            "code": 100,
            "message": str(e)
        })
# 执行UI自动化
def run_ui(request):
    data = json.loads(request.body)
    id = data["id"]
    try:
        if id == "" or data["address"] == "":
            return JsonResponse({"code": 100, "message": "必要参数不可为空"})
        case = UI_case.objects.filter(id=id)
        res = UI_case_result.objects.filter(ui_id=id)

        root = r'xxx/img/'
        for j in res:
            if j.result_type == 2:
                os.remove(os.path.join(root, j.result))
        res.delete()
        # chrome_address = "C:/Program Files/Google/Chrome/Application/chrome.exe"
        # 定义驱动
        driver = webdriver.Chrome()

        # 全屏显示
        driver.maximize_window()

        # 使用驱动 ,打开网页
        driver.get(data["address"])
        for i in case:
            if i.value == "":
                return JsonResponse({"code": 100, "message": "自动化配置不可为空"})
            UI_case_result.objects.create(result="[info]->正在遍历操作步骤", ui_id=id)
            for j in i.value:
                if j["iframe"] == 1 and j["iframe_value"] != "":
                    UI_case_result.objects.create(result="[info]->正在遍历iframe", ui_id=id)
                    try:
                        driver.switch_to.frame(j["iframe_value"])
                        UI_case_result.objects.create(result="[info]->存在这个iframe:" + j["iframe_value"], ui_id=id)
                        driver.switch_to.frame(j["iframe_value"])
                        UI_case_result.objects.create(result="[info]->正在进入iframe:" + j["iframe_value"], ui_id=id)
                        time.sleep(int(j["wait_time"]))
                        UI_case_result.objects.create(result="[info]->设置隐性等待时间:" + str(j["wait_time"]) + "s成功",
                                                      ui_id=id)
                    except Exception as e:
                        UI_case_result.objects.create(result="[error]->没有这个iframe元素地址为>>" + j["iframe_value"],
                                                      ui_id=id)
                        UI_case_result.objects.create(result="[error]->异常原因" + str(e) + ',元素命为:' + j["xpath"], ui_id=id)

                if j["xpath"] is not None:
                    UI_case_result.objects.create(result="[info]->正在遍历页面元素", ui_id=id)
                    img = save_img(driver)
                    try:
                        xpath = driver.find_element(By.XPATH, j["xpath"])
                        if j["event"] == 1:
                            xpath.click()
                            UI_case_result.objects.create(result="[info]->点击成功>>" + j["name"] + ",xpath地址:" + ':' + j["xpath"],
                                                          ui_id=id)
                            UI_case_result.objects.create(result=img, ui_id=id, result_type=2)
                            time.sleep(int(j["wait_time"]))
                            UI_case_result.objects.create(result="[info]->设置隐性等待时间:" + str(j["wait_time"]) + "s成功",
                                                          ui_id=id)
                        elif j["event"] == 2:
                            xpath.send_keys(j["value"])
                            UI_case_result.objects.create(result="[info]->输入值成功: " + str(j["value"]), ui_id=id)
                            time.sleep(int(j["wait_time"]))
                            UI_case_result.objects.create(result=img, ui_id=id, result_type=2)
                            UI_case_result.objects.create(result="[info]->设置隐性等待时间:" + str(j["wait_time"]) + "s成功", ui_id=id)
                    except Exception as e:
                        UI_case_result.objects.create(result="[error]->没有这个元素名为>>" + str(j["name"]) + ':' + j["xpath"],
                                                      ui_id=id)
                        UI_case_result.objects.create(result="[error]->异常原因" + str(e) + ',元素命为:' + str(j["name"]), ui_id=id)
        time.sleep(5)
        # 关闭浏览器
        driver.quit()
        UI_case_result.objects.create(result="[info]->已关闭浏览器", ui_id=id)
        UI_case_result.objects.create(result="结束", ui_id=id)
        return JsonResponse({
            "code": 200,
            "message": "执行结束"
        })
    except Exception as e:
        UI_case_result.objects.create(result="[error]->异常原因" + str(e), ui_id=id)
        UI_case_result.objects.create(result="结束", ui_id=id)
        return JsonResponse({
            "code": 100,
            "message": str(e)
        })

# 执行过程中对步骤进行截图保存
def save_img(driver):
    now = calendar.timegm(time.gmtime())  # 截图保存文件名格式
    pic_path = str(now) + ''.join(random.sample(string.ascii_letters+string.digits, 4)) + '_screen.png'  # 截图保存路径
    # print(pic_path)
    driver.save_screenshot("xxx/img/" + pic_path)  # 调用Driver的截图保存功能
    return pic_path


# 获取执行结果
def get_run_ui_result(request):
    try:
        data = json.loads(request.body)
        if data["time"] == "":
            res = UI_case_result.objects.filter(ui_id=data["id"])
        else:
            res = UI_case_result.objects.filter(ui_id=data["id"], create_time__gt=data["time"])
        result = []
        for i in res:
            i_dict = {
                "id": i.id,
                "result": i.result,
                "timestamp": datetime.strftime(i.create_time, "%Y-%m-%d %H:%M:%S"),
                "type": i.result_type
            }
            result.append(i_dict)
        return JsonResponse({
            "code": 200,
            "content": result
        })
    except Exception as e:
        return JsonResponse({
            "code": 100,
            "message": str(e)
        })

前端逻辑代码

<template>
  <div class="app-container" style="height: 100%; padding-left: 5px !important;">
    <div style="border-radius: 2px; float: left; width: 20%; padding-right:10px;height: 100%;overflow: auto">
      <el-input v-model="filterText" placeholder="输入搜索节点" style="margin-bottom:5px;" />
      <el-tree
        ref="tree"
        :data="tree_data"
        :props="defaultProps"
        :highlight-current="true"
        class="filter-tree"
        :default-expanded-keys="[1, 10]"
        :expand-on-click-node="false"
        :filter-node-method="filterNode"
        node-key="id"
        draggable
        :allow-drop="allowDrop"
        @node-drop="node_drop"
        @node-click="node_click"
      >
        <span slot-scope="{ node, data }" class="custom-tree-node" @mouseenter="getcase(data)">
          <span v-if="data.type===0"><i :class="icon0" style="padding-right: 5px" />{{ node.label }}</span>
          <span v-if="data.type===3"><i :class="icon1" style="padding-right: 5px" />{{ node.label }}</span>
          <span v-if="data.type===4"><i :class="icon2" style="padding-right: 5px" />{{ node.label }}</span>
          <span v-if="data.type === 0" class="right" :class="{newStyle: 1 === number}">
            <el-dropdown placement="bottom">
              <i class="el-icon-more" />
              <span class="el-dropdown-link" style="font-size: 20px" />
              <el-dropdown-menu slot="dropdown" class="header-new-drop">
                <el-dropdown-item icon="el-icon-folder-add" @click.native="new_menu(data)">新建菜单</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </span>
          <span v-if="data.type === 3" class="right" :class="{newStyle: 1 === number}">
            <el-dropdown placement="bottom">
              <i class="el-icon-more" />
              <span class="el-dropdown-link" style="font-size: 20px" />
              <el-dropdown-menu slot="dropdown" class="header-new-drop">
                <el-dropdown-item icon="el-icon-folder-add" @click.native="new_menu(data)">新增</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-edit" @click.native="edit(data)">重命名</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-folder-delete" @click.native="delete_del(node, data)">删除文件夹</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </span>
          <span v-if="data.type ===4" class="right" :class="{newStyle: 2 === number}">
            <el-dropdown placement="bottom">
              <i class="el-icon-more" />
              <span class="el-dropdown-link" style="font-size: 20px" />
              <el-dropdown-menu slot="dropdown" class="header-new-drop">
                <el-dropdown-item icon="el-icon-edit" @click.native="edit(data)">重命名</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-document-delete" @click.native="delete_case(node, data)">删除接口</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </span>
        </span>
      </el-tree>
    </div>
    <div style="overflow: auto; height: 100%">
      <el-tabs v-model="TabsValue" type="card" closable @tab-remove="removeTab" @tab-click="tab_click">
        <el-tab-pane
          v-for="(item) in tableTabs"
          :key="item.name"
          :label="item.title"
          :name="item.name"
        >
          <span slot="label">
            <span v-if="item.type===3"><i :class="icon1" style="padding-right: 5px" />{{ item.title }}</span>
            <span v-if="item.type===4"><i :class="icon2" style="padding-right: 5px" />{{ item.title }}</span>
          </span>
          <div v-show="1 === number">
            {{ item.title }}
          </div>
          <div v-show="2 === number">
            <div>
              <div style="padding-block-end: 10px">
                <el-button type="success" @click="run_ui_test">立即执行</el-button>
                <el-button type="primary" @click="ui_test_result">查看一次结果</el-button>
                <el-button style="float: right" type="primary" @click="edit_ui_dialog()">编辑</el-button>
              </div>
              <div style="padding-block-end: 10px">
                <el-descriptions :column="3" border>
                  <el-descriptions-item label-class-name="my-label" label="ID:" :content-style="{'text-align': 'left'}" style="width: 200px">
                    {{ ui_id }}</el-descriptions-item>
                  <el-descriptions-item label-class-name="my-label" label="用例名称:" :content-style="{'text-align': 'left'}" style="width: 200px">{{ item.title }}</el-descriptions-item>
                  <el-descriptions-item label-class-name="my-label" label="定位方式:" :content-style="{'text-align': 'left'}" style="width: 200px">xpath</el-descriptions-item>
                  <el-descriptions-item label-class-name="my-label" label="创建人:" :content-style="{'text-align': 'left'}" style="width: 200px">{{ username }}</el-descriptions-item>
                  <el-descriptions-item label-class-name="my-label" label="创建时间:" :content-style="{'text-align': 'left'}" style="width: 200px">
                    {{ create_time }}</el-descriptions-item>
                  <el-descriptions-item label-class-name="my-label" label="编辑时间:" :content-style="{'text-align': 'left'}" style="width: 200px">
                    {{ update_time }}</el-descriptions-item>
                  <el-descriptions-item label-class-name="my-label" label="执行方式:" :content-style="{'text-align': 'left'}" style="width: 200px">Chrome</el-descriptions-item>
                  <el-descriptions-item label-class-name="my-label" label="启动地址:" :content-style="{'text-align': 'left'}" style="width: 200px">{{ address }}</el-descriptions-item>
                </el-descriptions>
              </div>
              <div>
                <el-table
                  class="view_ui"
                  :data="table_data"
                  element-loading-text="Loading"
                  border
                  fit
                  highlight-current-row
                  style="float:left;width:100%"
                >
                  <el-table-column label="步骤名称" width="200px">
                    <template slot-scope="scope">
                      {{ scope.row.name }}
                    </template>
                  </el-table-column>
                  <el-table-column label="xpath地址">
                    <template slot-scope="scope">
                      {{ scope.row.xpath }}
                    </template>
                  </el-table-column>
                  <el-table-column label="是否iframe" width="100px">
                    <template slot-scope="scope">
                      <span v-if="scope.row.iframe===1"><el-tag type="success"></el-tag></span>
                      <span v-if="scope.row.iframe===0"><el-tag type="danger"></el-tag></span>
                    </template>event
                  </el-table-column>
                  <el-table-column label="iframe地址" width="200px">
                    <template slot-scope="scope">
                      {{ scope.row.iframe_value }}
                    </template>event
                  </el-table-column>
                  <el-table-column label="事件类型" width="100px">
                    <template slot-scope="scope">
                      {{ scope.row.event }}
                    </template>
                  </el-table-column>
                  <el-table-column label="输入" width="100px">
                    <template slot-scope="scope">
                      {{ scope.row.value }}
                    </template>
                  </el-table-column>
                  <el-table-column label="等待时间" width="100px">
                    <template slot-scope="scope">
                      {{ scope.row.wait_time }} s
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </div>
          </div>
        </el-tab-pane>
      </el-tabs>
    </div>
    <div>
      <el-dialog
        title="重命名"
        :visible.sync="editdialogVisible"
        width="30%"
        :before-close="handleClose"
      >
        <el-form :model="menu_form">
          <el-form-item label="menu_id">
            <el-input v-model="menu_form.id" readonly />
          </el-form-item>
          <el-form-item label="菜单名称">
            <el-input v-model="tree_name" />
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button @click="editdialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="edit_menu">确 定</el-button>
        </span>
      </el-dialog>
    </div>
    <div>
      <el-dialog
        title="新增菜单"
        :visible.sync="dialogVisible"
        width="30%"
        :before-close="handleClose"
      >
        <el-form :model="menu_pid">
          <el-form-item label="Type:">
            <el-select v-model="type_value">
              <el-option
                v-for="item in type_form"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="菜单名称">
            <el-input v-model="menu_form.label" />
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button @click="dialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="add_menu">确 定</el-button>
        </span>
      </el-dialog>
    </div>
    <div>
      <el-dialog
        title="提示"
        :visible.sync="del_case_dialog"
        width="20%"
      >
        <span>是否删除配置</span>
        <span slot="footer" class="dialog-footer">
          <el-button @click="del_case_dialog = false">取 消</el-button>
          <el-button type="primary" @click="deletepro()">确 定</el-button>
        </span>
      </el-dialog>
    </div>
    <div>
      <el-dialog
        title="编辑配置"
        :visible.sync="edit_case_dialog"
        width="80%"
      >
        <el-form :model="edit_ui">
          <el-form-item>
            <el-button type="primary" style="float: right" @click="add_ui_step">新增步骤</el-button>
          </el-form-item>
          <el-form-item label="启动地址">
            <el-input v-model="address" style="width: 500px" />
          </el-form-item>
          <el-form-item>
            <el-table
              class="edit_ui"
              :data="edit_ui"
              element-loading-text="Loading"
              border
              fit
              highlight-current-row
              style="float:left;width:100%"
              @cell-mouse-enter="handleCellEnter"
              @cell-mouse-leave="handleCellLeave"
              @cell-click="handleCellClick"
            >
              <el-table-column label="步骤名称" width="200px">
                <div slot-scope="scope" class="item">
                  <el-input v-model="scope.row.name" class="item__input" placeholder="输入内容" />
                </div>
              </el-table-column>
              <el-table-column label="xpath地址">
                <div slot-scope="scope" class="item">
                  <el-input v-model="scope.row.xpath" class="item__input" placeholder="输入内容" />
                </div>
              </el-table-column>
              <el-table-column label="是否iframe" width="100px">
                <div slot-scope="scope" class="item">
                  <el-select v-model="scope.row.iframe" class="item__input" placeholder="选择">
                    <el-option
                      v-for="item in iframe"
                      :key="item.iframe"
                      :label="item.label"
                      :value="item.iframe"
                    />
                  </el-select>
                </div>
              </el-table-column>
              <el-table-column label="iframe地址">
                <div slot-scope="scope" class="item">
                  <el-input v-model="scope.row.iframe_value" class="item__input" placeholder="输入内容" />
                </div>
              </el-table-column>
              <el-table-column label="事件类型" width="120px">
                <div slot-scope="scope" class="item">
                  <el-select v-model="scope.row.event" class="item__input" placeholder="请选择">
                    <el-option
                      v-for="item in event"
                      :key="item.event"
                      :label="item.label"
                      :value="item.event"
                    />
                  </el-select>
                </div>
              </el-table-column>
              <el-table-column label="输入" width="200px">
                <div slot-scope="scope" class="item">
                  <el-input v-model="scope.row.value" class="item__input" placeholder="输入内容" />
                </div>
              </el-table-column>
              <el-table-column label="等待时间" width="80px">
                <div slot-scope="scope" class="item">
                  <el-input v-model="scope.row.wait_time" class="item__input" placeholder="请输入内容" />
                </div>
              </el-table-column>
              <el-table-column align="center" prop="action" label="操作" width="100px">
                <template slot-scope="scope">
                  <el-button type="danger" icon="el-icon-delete" circle @click="del_ui_step(scope.$index, scope.row)" />
                </template>
              </el-table-column>
            </el-table>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" style="float: right" @click="save_ui_info">保存</el-button>
          </el-form-item>
        </el-form>
      </el-dialog>
    </div>
    <div>
      <el-dialog
        title="执行结果"
        :visible.sync="run_ui_dialog"
        width="60%"
        append-to-body
      >
        <div style="overflow: auto; height: 630px">
          <el-timeline style="padding: 15px">
            <el-timeline-item
              v-for="(activity, index) in run_ui_result"
              :key="index"
              :icon="icon"
              :type="type"
              :size="size"
              :timestamp="activity.timestamp"
            >
              <div v-if="2 === activity.type">
                <el-image :src="require('xxxx/img/' + activity.result + '')" style="width:800px;height:600px" @click="showImage(activity.result)" />
              </div>
              <div v-if="2 !== activity.type">
                {{ activity.result }}
              </div>
            </el-timeline-item>
          </el-timeline>
        </div>
      </el-dialog>
    </div>
    <div v-if="img_path !== ''">
      <el-dialog
        title="预览大图"
        :visible.sync="imageDialogVisible"
        width="70%"
      >
        <img :src="require('xxx/img/' + img_path + '')" style="width:100%;height:100%">
      </el-dialog>
    </div>
  </div>
</template>

<script>
import { edit_ui_info, get_ui_info, getUI_tree, run_result, run_ui } from "@/api/ui";
import { addmenu, change_pid, deletecase, deletepeoject } from "@/api/testcase";

export default {
  name: "Ui",
  data() {
    return {
      img_path: "",
      imageDialogVisible: false,
      address: "",
      run_ui_dialog: false,
      size: 'large',
      type: 'primary',
      icon: 'el-icon-bottom',
      timer: null,
      run_ui_result: [
        {
          result: '开始',
          // timestamp: '0000-00-00 00:00:00',
          id: 0,
        }
      ],
      iframe: [
        {
          label: "是",
          iframe: 1
        },
        {
          label: "否",
          iframe: 0
        },
      ],
      event: [
        {
          label: "click",
          event: 1
        },
        {
          label: "input",
          event: 2
        },
      ],
      // 需要编辑属性
      editProp: ['name', 'xpath', 'iframe', 'event', 'value', 'wait_time'],
      // 保存进入编辑cell
      clickCellMap: {},
      ui_id: null,
      create_time: "",
      update_time: "",
      menu_pid: null,
      editableTabs: [],
      TabsValue: "",
      // 用例id
      case_form: {
        menu_id: '',
        current_page: 1,
        size_page: 3,
      },
      del_case_dialog: false,
      menu_form: {
        label: '',
        pid: '',
        type: null,
        user_id: null,
      },
      table_data: [],
      type_form: [
        {
          label: "文件夹",
          value: 3
        },
        {
          label: "UI用例",
          value: 4
        },
      ],
      icon0: 'el-icon-s-home',
      icon1: 'el-icon-folder-opened',
      icon2: 'el-icon-s-data',
      number: null,
      filterText: '',
      defaultProps: {
        children: 'children',
        label: 'label',
        id: "id"
      },
      node_data: [],
      tree_data: [],
      edit_case_dialog: false,
      dialogVisible: false,
      type_value: '',
      tree_name: '',
      editdialogVisible: false,
      // eslint-disable-next-line no-dupe-keys
      tableTabs: [],
      pidFrom: {
        id: ''
      },
      username: "",
      edit_ui: [],
      now: "",
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    }
  },
  created() {
    this.get_ui_tree()
    this.is_login()
  },
  destroyed() {
    clearTimeout(this.timer)
  },
  methods: {
    is_login() {
      // eslint-disable-next-line no-prototype-builtins
      if (localStorage.hasOwnProperty("user_id") === false || localStorage.getItem("user_id") === '') {
        this.$router.push("/login")
        this.$message.error("未登录,请前往登录")
      }
    },
    showImage(data) {
      this.imageDialogVisible = true
      this.img_path = data
      console.log(this.img_path)
    },
    /** 鼠标移入cell */
    handleCellEnter(row, column, cell, event) {
      const property = column.property
      if (property === 'date' || property === 'name' || property === 'food') {
        cell.querySelector('.item__txt').classList.add('item__txt--hover')
      }
    },
    /** 鼠标移出cell */
    handleCellLeave(row, column, cell, event) {
      const property = column.property
      if (this.editProp.includes(property)) {
        cell.querySelector('.item__txt').classList.remove('item__txt--hover')
      }
    },
    /** 点击cell */
    handleCellClick(row, column, cell, event) {
      const property = column.property
      if (this.editProp.includes(property)) {
        // 保存cell
        this.saveCellClick(row, cell)
        cell.querySelector('.item__txt').style.display = 'none'
        cell.querySelector('.item__input').style.display = 'block'
        cell.querySelector('input').focus()
      }
    },
    /** 取消编辑状态 */
    cancelEditable(cell) {
      cell.querySelector('.item__txt').style.display = 'block'
      cell.querySelector('.item__input').style.display = 'none'
    },
    /** 保存进入编辑的cell */
    saveCellClick(row, cell) {
      const id = row.id
      if (this.clickCellMap[id] !== undefined) {
        if (!this.clickCellMap[id].includes(cell)) {
          this.clickCellMap[id].push(cell)
        }
      } else {
        this.clickCellMap[id] = [cell]
      }
    },
    /** 保存数据 */
    save(row) {
      const id = row.id
      // 取消本行所有cell的编辑状态
      this.clickCellMap[id].forEach(cell => {
        this.cancelEditable(cell)
      })
      this.clickCellMap[id] = []
    },
    // 获取接口目录
    get_ui_tree() {
      getUI_tree().then(res => {
        this.tree_data = res.data.content
      })
    },
    new_menu(data) {
      this.dialogVisible = true
      this.node_data = data
      this.tree_menu_id = data.id
      if (this.children_view(this.node_data) === 0) {
        this.node_data.children = []
      }
    },
    tab_click(tab) {
      const tabs = this.tableTabs
      for (const t of tabs) {
        if (t.name === tab.name) {
          if (t.type === 3) {
            this.number = 1
            this.pidFrom.id = t.content
          } else if (t.type === 4) {
            this.number = 2
            this.case_form.menu_id = t.content
            this.case_form.size_page = 3
            this.case_form.current_page = 1
            this.ui_ifo(t.content)
          }
        }
      }
    },
    removeTab(targetName) {
      const tabs = this.tableTabs;
      let activeName = this.TabsValue;
      if (activeName === targetName) {
        tabs.forEach((tab, index) => {
          if (tab.name === targetName) {
            const nextTab = tabs[index + 1] || tabs[index - 1];
            if (nextTab) {
              activeName = nextTab.name;
              this.tab_click(nextTab)
            }
          }
        });
      }
      this.TabsValue = activeName;
      this.tableTabs = tabs.filter(tab => tab.name !== targetName);
    },
    addTab(targetName, id, type) {
      const index = this.tableTabs.findIndex(item => item.title === targetName)
      if (index === -1) {
        this.tableTabs.push({
          title: targetName,
          name: targetName,
          content: id,
          type: type
        })
      }
      this.TabsValue = targetName;
    },
    node_click(data) {
      this.addTab(data.label, data.id, data.type)
      this.tree_name = data.label
      this.m_id = data.pid
      if (data.type === 3) {
        this.number = 1;
        this.menu_pid = data.id;
        this.pidFrom.id = data.id;
      } else if (data.type === 4) {
        this.number = 2;
        this.case_form.menu_id = data.id;
        this.menu_pid = data.id;
        this.ui_ifo(data.id)
      }
    },
    getcase(data) {
      switch (data.type) {
        case 3:
          this.menu_pid = this.pidFrom.id = data.id;
          this.m_id = data.pid;
          break
        case 4:
          this.case_form.menu_id = this.menu_pid = this.pidFrom.id = data.id;
          this.m_id = data.pid;
          break;
        case 0:
          this.menu_pid = this.pidFrom.id = data.id;
          break;
        default:
          // handle unexpected data.type
          break;
      }
    },
    children_view(data) {
      if ("children" in data) { // json就是数组,name是你要找的值
        return 1
      } else {
        return 0
      }
    },
    delete_case(node, data) {
      deletecase({ "menu_id": data.id }).then(res => {
        if (res.data.code === 200) {
          this.$message({
            message: "删除接口成功",
            type: "success"
          })
          const parent = node.parent;
          const children = parent.data.children || parent.data;
          const index = children.findIndex(d => d.id === data.id);
          children.splice(index, 1);
        } else if (res.data.code === 100) {
          this.$message({
            message: "删除接口失败,无此接口",
            type: 'error'
          })
        }
      })
    },
    add_menu() {
      const req = this.menu_form
      req.type = this.type_value
      req.pid = this.node_data.id
      req.user_id = Number(localStorage.getItem("user_id"))
      addmenu(this.menu_form).then(res => {
        if (res.data.code === 200) {
          this.$message({
            message: res.data.message,
            type: 'success'
          })
          this.dialogVisible = false
          this.node_data.children.push(res.data.data)
        } else if (res.data.code === 100) {
          this.dialogVisible = true
          this.$message.error("菜单名称不可为空")
        } else if (res.data.code === 101) {
          this.dialogVisible = true
          this.$message.error("名称已存在,请重新输入")
        }
      })
    },
    edit(data) {
      this.menu_form.id = data.id
      this.editdialogVisible = true
      this.tree_name = data.label
      this.node_data = data
    },
    edit_menu() {
      const req = this.menu_form
      req.id = this.menu_form.id
      req.label = this.tree_name
      req.pid = this.node_data.id
      req.user_id = Number(localStorage.getItem("user_id"))
      addmenu(req).then(res => {
        if (res.data.code === 200) {
          this.$message({
            message: '重命名成功',
            type: 'success'
          })
          this.editdialogVisible = false
          const temp = this.tableTabs.find(o => o.content === this.menu_form.id)
          if (temp) {
            temp.title = res.data.label;
          }
          this.node_data.label = res.data.label
          this.form_case.name = res.data.label
        } else if (res.data.code === 100) {
          this.editdialogVisible = true
          this.$message.error("菜单名称不可为空")
        } else if (res.data.code === 101) {
          this.editdialogVisible = true
          this.$message.error("名称已存在,请重新输入")
        }
      })
    },
    delete_del(node, data) {
      this.del_case_dialog = true
      this.node_data = node
      this.pid_list = data
    },
    // 删除文件夹
    deletepro() {
      const data = this.pid_list
      const node = this.node_data
      deletepeoject({ "id": data.id }).then(res => {
        if (res.data.code === 200) {
          this.$message({
            message: res.data.message,
            type: "success"
          })
          const parent = node.parent;
          const children = parent.data.children || parent.data;
          const index = children.findIndex(d => d.id === data.id);
          children.splice(index, 1);
          this.del_case_dialog = false
        } else {
          this.$message({
            message: res.data.message,
            type: 'error'
          })
        }
      })
    },
    allowDrop(from, to, type) {
      return !(to.data.type === 3 || type !== 'inner');
    },
    node_drop(from, to) {
      const req = {}
      req.from_id = from.data.id
      req.to_id = to.data.id
      change_pid(req).then(res => {
        if (res.data.code === 200) {
          this.$message.success(res.data.message)
        } else if (res.data.code !== 200) {
          this.$message.error(res.data.message)
        }
      })
    },
    filterNode(value, tree_data) {
      if (!value) return true;
      return tree_data.label.indexOf(value) !== -1;
    },
    handleClose(done) {
      done()
    },
    getNowTime() {
      let now = ""
      const yy = new Date().getFullYear()
      const mm = new Date().getMonth() + 1
      const dd = new Date().getDate()
      const hh = new Date().getHours() < 10 ? '0' + new Date().getHours() : new Date().getHours()
      const mf = new Date().getMinutes() < 10 ? '0' + new Date().getMinutes() : new Date().getMinutes()
      const ss = new Date().getSeconds() < 10 ? '0' + new Date().getSeconds()
        : new Date().getSeconds()
      now = yy + '-' + mm + '-' + dd + ' ' + hh + ':' + mf + ':' + ss
      return now
    },
    ui_test_result() {
      this.run_ui_dialog = true
      this.now = this.getNowTime()
      run_result({ "id": this.ui_id, "time": "" }).then(res => {
        this.run_ui_result = res.data.content
      })
    },
    run_ui_test() {
      this.$message.success("开始执行")
      this.run_ui_dialog = true
      run_ui({
        "id": this.ui_id,
        "address": this.address
      }).then(res => {
        if (res.data.code !== 200) {
          this.$message.error(res.data.message)
        }
      })
      this.now = this.getNowTime()
      this.run_ui_result = [{
        result: '开始',
        // timestamp: '0000-00-00 00:00:00',
        id: 0,
      }]
      this.ui_result()
    },
    edit_ui_dialog() {
      this.edit_case_dialog = true
      this.edit_ui = this.table_data
    },
    del_ui_step(index, row) {
      this.edit_ui.splice(index, 1)
    },
    add_ui_step() {
      const obj = {
        "name": "",
        "xpath": "",
        "iframe": 0,
        "iframe_value": "",
        "value": "",
        "event": null,
        "wait_time": ""
      }
      this.edit_ui.push(obj)
    },
    ui_ifo(data) {
      get_ui_info({ "id": data }).then(res => {
        if (res.data.code === 200) {
          this.update_time = res.data.update_time
          this.create_time = res.data.create_time
          this.table_data = res.data.content
          this.username = res.data.username
          this.ui_id = res.data.ui_id
          this.address = res.data.address
        } else {
          this.$message.error(res.data.message)
        }
      })
    },
    save_ui_info() {
      let flag = true
      this.edit_ui.forEach(item => {
        if (item.name === "" || item.wait_time === "" || item.event === "" || item.xpath === "") {
          this.$message.error("必要参数不可为空")
          flag = false
        }
      })
      if (flag) {
        edit_ui_info({
          "id": this.ui_id,
          "value": this.edit_ui,
          "user_id": localStorage.getItem("user_id"),
          "address": this.address
        }).then(res => {
          if (res.data.code === 200) {
            this.$message.success(res.data.message)
            this.edit_case_dialog = false
          } else {
            this.$message.error(res.data.message)
          }
        })
      }
    },
    ui_result() {
      const that = this
      run_result({ "id": this.ui_id, "time": this.now }).then(res => {
        if (res.data.code === 200) {
          const list = res.data.content
          for (const obj1 of list) {
            let flag = true
            for (const obj2 of this.run_ui_result) {
              if (obj1.id === obj2.id) {
                flag = false
              }
            }
            if (flag) {
              this.run_ui_result.push(obj1)
            }
          }
        } else {
          this.$message.error(res.data.message)
        }
      }).finally(() => {
      // 每隔10s循环遍历数据库获取自动化执行的结果
        this.run_ui_result.forEach(item => {
          if (item.result === '结束') {
            clearTimeout(that.timer);
          } else {
            clearTimeout(that.timer);
            that.timer = setTimeout(() => {
              that.ui_result()
            }, 10000)
          }
        })
      })
    }
  }
}
</script>

<style scoped>
.el-dialog__body {
  padding: 10px !important;
}
  .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 4px;
  }
  .el-dropdown {
    font-size: 16px;
    color: #5d697a;
  }
  .my-label {
    background: rgba(216, 243, 234, 0.31) !important;
  }
  .my-content {
    background: #e2fdf1;
  }
</style>

总结

闲暇时候写的这套代码只能执行简单点击,输入,更高深的技术真正摸索中!!!
个人主页仍有精彩的内容,欢迎私信交流!!!!

原文地址:https://blog.csdn.net/ljyljyyeah/article/details/130108944

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_24726.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注