Selenium
Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera,Edge等。这个工具的主要功能包括:测试与浏览器的兼容性——测试应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成.Net、Java、Perl等不同语言的测试脚本。
结果预览:
实现使用到框架
服务端代码
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进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。