add:元素库 - api

This commit is contained in:
2025-04-27 13:36:36 +08:00
parent bbb9cb26f9
commit 75b83d2847
8 changed files with 468 additions and 48 deletions

View File

@@ -1 +1 @@
//
import request from '@/utils/request'

View File

@@ -0,0 +1,37 @@
import request from '@/utils/request'
// 元素库-列表查询
export function getElementList(query) {
return request({
url: '/test/element/list',
method: 'get',
params: query
})
}
// 元素库 - 新增
export function addElement(data) {
return request({
url: '/test/element/add',
method: 'post',
data: data
})
}
// 元素库 - 删除
export function deleteElement(data) {
return request({
url: '/test/element/delete/' + data,
method: 'put',
data: data
})
}
// 元素库- 编辑
export function updateElement(data) {
return request({
url: '/test/element/update',
method: 'put',
data: data
})
}

View File

@@ -0,0 +1 @@
import request from '@/utils/request'

View File

@@ -27,21 +27,50 @@
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="场景步骤" name="second">场景步骤</el-tab-pane>
<el-tab-pane label="场景步骤" name="second">
<el-menu :default-active="String(defaultActive)" @select="handleSelect">
<div v-for="(item, index) in stepList">
<el-menu-item :index="String(index + 1)">
<div class="menu-wrap">
<div class="stepCount">{{ index + 1 }}</div>
<div>{{ item.name }}</div>
</div>
</el-menu-item>
</div>
</el-menu>
</el-tab-pane>
</el-tabs>
</div>
<div class="scene-wrap">
<div class="scene-header">
<el-button size="mini" @click="handleClickSave">保存</el-button>
</div>
<el-button icon="el-icon-circle-plus-outline" type="text" style="font-size: 30px;"></el-button>
<SceneStep v-show="defaultActive != 0" :step="stepName" @stepNameChange="stenNameChange" />
<AdvancedSetting v-show="defaultActive != 0" />
</div>
<!-- 添加步骤 -->
<div class="add-btn">
<el-dropdown @command="handleClickAddStep" :hide-on-click="false">
<el-button icon="el-icon-circle-plus-outline" type="text" style="font-size: 30px;"></el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="浏览器操作">浏览器操作</el-dropdown-item>
<el-dropdown-item command="弹窗操作">弹窗操作</el-dropdown-item>
<el-dropdown-item command="元素操作">元素操作</el-dropdown-item>
<el-dropdown-item command="鼠标操作">鼠标操作</el-dropdown-item>
<el-dropdown-item command="输入操作">输入操作</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
import AdvancedSetting from './advancedSetting.vue'
import SceneStep from './sceneStep.vue'
export default {
name: "AddScene",
components: { AdvancedSetting, SceneStep },
data() {
return {
activeName: 'first',
@@ -60,15 +89,50 @@ export default {
name2: [{ required: true, message: '请输入名称', trigger: 'blur' }],
name3: [{ required: true, message: '请输入名称', trigger: 'blur' }],
},
stepList: [],
defaultActive: 0, // 当前激活菜单的 index
stepName: null, // 当前所选中的步骤的名称
}
},
mounted() {
},
methods: {
handleClick() { },
// 场景步骤
handleSelect(key, keyPath) {
this.defaultActive = Number(key)
this.stepName = this.stepList[Number(key) - 1].name
},
// 添加步骤
handleClickAddStep() {
handleClickAddStep(command) {
var param = {
name: '',
}
switch (command) {
case '浏览器操作':
param.name = '打开网页'
break
case '弹窗操作':
param.name = '弹窗操作'
break
case '元素操作':
param.name = '提交表单'
break
case '鼠标操作':
param.name = '鼠标点击'
break
case '输入操作':
param.name = '输入操作'
break
}
this.stepName = param.name
this.stepList.splice(this.defaultActive, 0, param);
this.defaultActive++;
},
// 步骤名称同步
stenNameChange(val) {
this.stepName = val
this.stepList[this.defaultActive - 1].name = val
},
// 保存
handleClickSave() {
@@ -85,6 +149,24 @@ export default {
.left-wrap {
width: 300px;
overflow: auto;
.menu-wrap {
display: flex;
align-items: center;
gap: 10px;
.stepCount {
width: 20px;
height: 20px;
border: solid 1px;
border-radius: 10px;
display: flex;
justify-content: center;
align-items: center;
}
}
}
.scene-wrap {
@@ -93,8 +175,26 @@ export default {
.scene-header {
display: flex;
justify-content: flex-end;
padding-right: 30px;
}
}
.add-btn {
position: fixed;
bottom: 100px;
right: 100px;
}
}
::v-deep .el-menu-item {
height: 36px;
line-height: 36px;
}
::v-deep .el-menu-item.is-active {
background-color: white;
/* 自定义背景色 */
color: #409EFF;
/* 自定义字体颜色 */
}
</style>

View File

@@ -0,0 +1,36 @@
<template>
<div class="advanced-setting">
<div class="title">高级设置</div>
</div>
</template>
<script>
export default {
name: "AdvancedSetting",
props: {
step: '',
},
data() {
return {
}
},
mounted() {
},
methods: {
}
}
</script>
<style scoped lang="scss">
.advanced-setting {
padding: 20px;
.title {
padding: 10px 20px;
font-weight: 600;
margin-bottom: 10px;
}
}
</style>

View File

@@ -7,8 +7,6 @@
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="1">创建场景</el-dropdown-item>
<el-dropdown-item command="2">创建指令</el-dropdown-item>
<el-dropdown-item command="3">关闭所有标签</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<div class="searchInput">

View File

@@ -1,10 +1,10 @@
<template>
<folder-page type="element" @click="folderHandleSelected" ref="folder">
<div class="header">
<el-button icon="el-icon-circle-plus-outline" size="mini" @click="addElement">创建元素</el-button>
<el-button icon="el-icon-circle-plus-outline" size="mini" @click="addElementData">创建元素</el-button>
<div class="searchInput">
<i class="el-icon-search"></i>
<el-input class="input" v-model="search" placeholder="根据名称搜索"></el-input>
<el-input class="input" v-model="searchForm.name" placeholder="根据名称搜索" @blur="searchName"></el-input>
</div>
</div>
<div class="list">
@@ -12,15 +12,13 @@
<el-table-column type="selection" width="55" />
<el-table-column prop="id" label="ID" width="50" align="center" />
<el-table-column prop="name" label="元素名称" width="150" align="center" />
<el-table-column prop="createBy" label="定位类型" width="150" align="center" />
<el-table-column prop="createTime" label="元素定位" width="150" align="center" />
<el-table-column prop="updateTime" label="创建人" width="150" sortable align="center" />
<el-table-column prop="status" label="创建时间" width="150" align="center" sortable />
<el-table-column prop="action" label="操作" align="center" fixed="right" width="200px">
<el-table-column prop="locType" label="定位类型" width="150" align="center" />
<el-table-column prop="elementLoc" label="元素定位" width="150" align="center" />
<el-table-column prop="updateBy" label="创建人" width="150" sortable align="center" />
<el-table-column prop="createTime" label="创建时间" width="150" align="center" sortable />
<el-table-column prop="action" label="操作" align="center" fixed="right" width="150px">
<template slot-scope="scope">
<el-button type="text" icon="el-icon-edit-outline" @click="hadleClickEdit(scope.row)">编辑</el-button>
<el-button type="text" icon="el-icon-view" @click="handleClickDetail(scope.row)"
style="color: green;">查看</el-button>
<el-button type="text" icon="el-icon-delete" style="color: red;"
@click="hadleClickDelete(scope.row)">删除</el-button>
</template>
@@ -33,24 +31,24 @@
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="40%">
<div class="form">
<el-form :model="editForm" :rules="rules" label-position="right" label-width="80px">
<el-form-item label="元素名称" prop="name1">
<el-input v-model="editForm.name1" placeholder="请输入元素名称"></el-input>
<el-form-item label="元素名称" prop="name">
<el-input v-model="editForm.name" placeholder="请输入元素名称"></el-input>
</el-form-item>
<el-form-item label="所属模块" prop="name2">
<el-select v-model="editForm.name2" placeholder="请选择">
<el-option key='1' label="模块1" value="1"></el-option>
<el-form-item label="所属模块" prop="groupId">
<el-select v-model="editForm.groupId" placeholder="请选择">
<el-option v-for="item in groupList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="定位类型" prop="name3">
<el-select v-model="editForm.name3" placeholder="请选择">
<el-option v-for="(item, index) in typeList" :key="index" :label="item" :value="index"></el-option>
<el-form-item label="定位类型" prop="locType">
<el-select v-model="editForm.locType" placeholder="请选择">
<el-option v-for="(item, index) in typeList" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="元素定位" prop="name4">
<el-input v-model="editForm.name4" placeholder="请输入元素定位"></el-input>
<el-form-item label="元素定位" prop="elementLoc">
<el-input v-model="editForm.elementLoc" placeholder="请输入元素定位"></el-input>
</el-form-item>
<el-form-item label="备注" prop="name5">
<el-input v-model="editForm.name5" placeholder="请输入备注" type="textarea" :rows="2"></el-input>
<el-form-item label="备注" prop="description">
<el-input v-model="editForm.description" placeholder="请输入备注" type="textarea" :rows="2"></el-input>
</el-form-item>
</el-form>
</div>
@@ -63,51 +61,79 @@
</template>
<script>
import FolderPage from "@/components/FolderPage/index.vue";
import FolderPage from "@/components/FolderPage/index.vue"
import { listGroup } from "../../../api/test/group";
import { getElementList, addElement, deleteElement, updateElement } from "../../../api/uiTest/elementLibrary";
export default {
name: "ElementLibrary.vue",
components: { FolderPage },
data() {
return {
search: '',
elementList: [{ name1: '名称1' }],
elementList: [],
searchForm: {
pageNumber: 1,
pageSize: 10,
name: null,
groupId: null,
},
total: 0,
dialogTitle: '',
dialogVisible: false,
editForm: {
name1: null,
name2: null,
name3: null,
name4: null,
name5: null,
name: null, // 元素名称
groupId: null, // 所属模块
locType: null, // 定位类型
elementLoc: null, // 元素定位
description: null, // 备注
},
typeList: ['id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath', 'lable', 'value', 'index'],
typeList: ['id', 'name', 'className', 'tagName', 'linkText', 'partialLinkText', 'css', 'xpath', 'lable', 'value', 'index'],
rules: {
name1: [{ required: true, message: '请输入元素名称', trigger: 'blur' }],
name2: [{ required: true, message: '请选择所属模块', trigger: 'blur' }],
name3: [{ required: true, message: '请选择定位类型', trigger: 'blur' }],
name4: [{ required: true, message: '请输入元素定位', trigger: 'blur' }],
name: [{ required: true, message: '请输入元素名称', trigger: 'blur' }],
groupId: [{ required: true, message: '请选择所属模块', trigger: 'blur' }],
locType: [{ required: true, message: '请选择定位类型', trigger: 'blur' }],
elementLoc: [{ required: true, message: '请输入元素定位', trigger: 'blur' }],
},
deleteVisible: false,
groupList: [], // 分组
}
},
mounted() {
this.getElementData()
this.getGroupListData()
},
methods: {
folderHandleSelected(id) {
if (id) {
// 获取列表
this.searchForm.groupId = id;
this.getElementData();
} else {
this.elementList = [];
}
},
//
getGroupListData() {
listGroup('element').then(res => {
if (res.code === 200) {
this.groupList = res.data
}
})
},
// 获取元素
getElementData() {
getElementList(this.searchForm).then(res => {
if (res.code === 200) {
this.elementList = res.rows
}
})
},
// 搜索
searchName() {
this.getElementData();
},
// 创建元素
addElement() {
addElementData() {
this.dialogTitle = '创建元素'
this.dialogVisible = true
for (let key in this.editForm) {
@@ -122,15 +148,40 @@ export default {
},
// 删除
hadleClickDelete(val) {
this.$modal.confirm('确认删除元素' + '').then(() => {
this.$modal.msgSuccess("删除成功");
}).catch(() => { })
deleteElement(val.id).then(res => {
if (res.code === 200) {
this.$modal.msgSuccess("删除成功");
this.getElementData();
} else {
this.$modal.msgError("删除失败");
}
})
},
// 查看
handleClickDetail() { },
// 确定
handleWithAdd() {
console.log(this.editForm)
if (this.dialogTitle === '创建元素') {
// 创建元素
addElement(this.editForm).then(res => {
if (res.code === 200) {
this.$modal.msgSuccess("创建成功")
this.dialogVisible = false
this.getElementData()
} else {
this.$modal.msgError("创建失败");
}
})
} else {
// 编辑元素
updateElement(this.editForm).then(res => {
if (res.code === 200) {
this.$modal.msgSuccess("编辑成功");
this.dialogVisible = false
this.getElementData()
} else {
this.$modal.msgError("编辑失败");
}
})
}
},
handleCurrentChange() { },
handleSizeChange() { },

View File

@@ -0,0 +1,197 @@
<template>
<div class="scene-step">
<div class="title">场景步骤</div>
<el-form :model="saveForm" :rules="rules" label-width="100px">
<el-form-item prop="stepName" label="名称">
<el-input v-model="saveForm.stepName" placeholder="请输入名称" maxlength="100" show-word-limit @input="changeInput"
class="input" />
</el-form-item>
<el-form-item prop="type" label="步骤类型">
<el-select v-model="saveForm.type" placeholder="请选择" class="select" @change="changeSelectType">
<el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
<span style="margin-left: 20px; color: gray;">{{ typeTitle }}</span>
</el-form-item>
<div v-show="typeName === '打开网页'">
<el-form-item prop="url" label="URL">
<el-input v-model="saveForm.stepName" placeholder="URL或路径" class="input" />
<el-tooltip class="item" effect="dark" content="根据URL,打开指定的页面" placement="right">
<i class="el-icon-info" style="margin-left: 20px;"></i>
</el-tooltip>
</el-form-item>
<el-form-item>
<el-radio v-model="saveForm.radio" label="1">追加页面</el-radio>
<el-tooltip class="item" effect="dark" content="追加页面在新的页面打开url不勾选覆盖当前url" placement="right">
<i class="el-icon-info"></i>
</el-tooltip>
</el-form-item>
</div>
<div v-show="typeName === '弹窗操作'">
<el-form-item label="是否输入" prop="isInput">
<el-select v-model="saveForm.isInput" class="select">
<el-option key="1" label="是" value="1"></el-option>
<el-option key="0" label="否" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item label="操作方式" prop="actionType">
<el-select v-model="saveForm.actionType" class="select">
<el-option key="1" label="确定" value="1"></el-option>
<el-option key="0" label="取消" value="0"></el-option>
</el-select>
<el-tooltip class="item" effect="dark" content="点击弹窗确定按钮或取消按钮" placement="right" style="margin-left: 10px;">
<i class="el-icon-info"></i>
</el-tooltip>
</el-form-item>
</div>
<div
v-show="typeName === '切换窗口' || typeName === '设置窗口大小' || typeName === '选择内嵌网页' || typeName === '下拉框操作' || typeName === '设置选项'">
<el-form-item label="操作">
<el-select v-model="saveForm.action" class="select">
<el-option v-for="item in actionList" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
</div>
<div v-show="typeName === '提交表单' || typeName === '下拉框操作' || typeName === '设置选项' || typeName === '等待元素'">
<el-form-item label="操作对象">
<el-select v-model="saveForm.action" class="select">
<el-option key="1" label="元素对象" value="1"></el-option>
<el-option key="1" label="元素定位" value="1"></el-option>
</el-select>
<el-select v-model="saveForm.action" class="select" style="margin: 0px 10px;">
<el-option key="1" label="元素对象" value="1"></el-option>
<el-option key="1" label="元素定位" value="1"></el-option>
</el-select>
<el-select v-model="saveForm.action" class="select">
<el-option key="1" label="元素对象" value="1"></el-option>
<el-option key="1" label="元素定位" value="1"></el-option>
</el-select>
</el-form-item>
</div>
</el-form>
</div>
</template>
<script>
export default {
name: "SceneStep",
props: {
step: '',
},
data() {
return {
saveForm: {
stepName: null,
type: '1',
url: null,
radio: true,
action: null,
isInput: null,
actionType: null
},
rules: {
stepName: [{ required: true, message: '请输入元素名称', trigger: 'blur' }],
type: [{ required: true, message: '请选择步骤类型', trigger: 'blur' }],
url: [{ required: true, message: '请输入URL或路径', trigger: 'blur' }],
isInput: [{ required: true, message: '请选择是否输入', trigger: 'blur' }],
actionType: [{ required: true, message: '请选择操作方式', trigger: 'blur' }],
},
typeList: [],// 步骤类型
typeTitle: '', // 步骤类型
typeName: '', // 步骤类型
actionList: [],
}
},
mounted() {
},
methods: {
changeInput(val) {
this.$emit('stepNameChange', val);
},
changeSelectType(val) {
this.saveForm.stepName = this.typeList[val - 1].label
this.typeName = this.typeList[val - 1].label
this.$emit('stepNameChange', this.saveForm.stepName);
switch (this.typeList[val - 1].label) {
case '打开网页': this.typeTitle = '使用指定的浏览器打开网页'
break
case '关闭网页':
this.typeTitle = '关闭当前网页'
break
case '切换窗口':
this.typeTitle = '切换到指定窗口'
this.actionList = [{ label: '根据句柄ID切换到指定窗口', value: '1' }, { label: '根据网页索引号切换到指定窗口', value: '2' }, { label: '切换到初始窗口', value: '3' }]
break
case '设置窗口大小':
this.typeTitle = '设置窗口大小'
this.actionList = [{ label: '窗口最大化', value: '1' }, { label: '指定尺寸(像素为单位)', value: '2' }]
break
case '选择内嵌网页':
this.typeTitle = '选择内嵌网页'
this.actionList = [{ label: '退出当前frame(回到主页面)', value: '1' }, { label: '根据frame索引号切换到指定frame', value: '2' }, { label: '根据定位方式切换frame', value: '3' }]
break
case '提交表单':
this.typeTitle = '针对属性type="submit”的元素用于提交表单数据'
break
case '下拉框操作':
this.typeTitle = '对下拉选项进行操作,可实现单选,多选,以及取消选择的操作'
this.actionList = [{ label: '选择', value: '1' }, { label: '取消', value: '2' }]
break
case '设置选项':
this.typeTitle = '用于设置 checkbox/radio 的状态'
this.actionList = [{ label: '选择', value: '1' }, { label: '取消', value: '2' }]
break
}
},
},
watch: {
step(newVal, oldVal) {
this.saveForm.stepName = newVal
this.typeName = newVal
switch (newVal) {
case '打开网页':
this.typeList = [{ label: '打开网页', value: '1' }, { label: '关闭网页', value: '2' }, { label: '切换窗口', value: '3' },
{ label: '设置窗口大小', value: '4' }, { label: '选择内嵌网页', value: '5' }]
this.typeTitle = '使用指定的浏览器打开网页'
break
case '弹窗操作':
this.typeList = [{ label: '弹窗操作', value: '1' }]
this.typeTitle = '对无法进行元素定位的弹窗实现的操作 (注:弹框事件不会产生截图)'
break
case '提交表单':
this.typeList = [{ label: '提交表单', value: '1' }, { label: '下拉框操作', value: '2' }, { label: '设置选项', value: '3' },
{ label: '等待元素', value: '4' }]
this.typeTitle = '针对属性type="submit”的元素用于提交表单数据'
break
case '鼠标点击':
this.typeList = [{ label: '鼠标点击', value: '1' }, { label: '鼠标移动', value: '2' }]
this.typeTitle = '模拟鼠标点击的操作,支持单击/双击/按下/弹起'
break
case '输入操作':
this.typeList = [{ label: '输入操作', value: '1' }]
this.typeTitle = '对元素实现输入的操作'
break
}
}
},
}
</script>
<style scoped lang="scss">
.scene-step {
padding: 20px;
.title {
padding: 10px 20px;
font-weight: 600;
margin-bottom: 10px;
}
.input {
width: 700px;
}
.select {
width: 200px;
}
}
</style>