Merge branch 'v1.5' into master
# Conflicts: # frontend/src/business/components/track/case/components/TestCaseList.vue
This commit is contained in:
commit
f92209383b
|
@ -258,7 +258,8 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="list" resultType="io.metersphere.track.dto.TestCaseDTO">
|
<select id="list" resultType="io.metersphere.track.dto.TestCaseDTO">
|
||||||
select test_case.* from test_case
|
select <include refid="io.metersphere.base.mapper.TestCaseMapper.Base_Column_List"/>
|
||||||
|
from test_case
|
||||||
<where>
|
<where>
|
||||||
<if test="request.combine != null">
|
<if test="request.combine != null">
|
||||||
<include refid="combine">
|
<include refid="combine">
|
||||||
|
|
|
@ -55,204 +55,205 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import NodeTree from '../common/NodeTree';
|
import NodeTree from '../common/NodeTree';
|
||||||
import TestCaseEdit from './components/TestCaseEdit';
|
import TestCaseEdit from './components/TestCaseEdit';
|
||||||
import {CURRENT_PROJECT, ROLE_TEST_MANAGER, ROLE_TEST_USER} from '../../../../common/js/constants';
|
import {CURRENT_PROJECT, ROLE_TEST_MANAGER, ROLE_TEST_USER} from '../../../../common/js/constants';
|
||||||
import TestCaseList from "./components/TestCaseList";
|
import TestCaseList from "./components/TestCaseList";
|
||||||
import SelectMenu from "../common/SelectMenu";
|
import SelectMenu from "../common/SelectMenu";
|
||||||
import TestCaseMove from "./components/TestCaseMove";
|
import TestCaseMove from "./components/TestCaseMove";
|
||||||
import MsContainer from "../../common/components/MsContainer";
|
import MsContainer from "../../common/components/MsContainer";
|
||||||
import MsAsideContainer from "../../common/components/MsAsideContainer";
|
import MsAsideContainer from "../../common/components/MsAsideContainer";
|
||||||
import MsMainContainer from "../../common/components/MsMainContainer";
|
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||||
import {checkoutTestManagerOrTestUser, hasRoles} from "../../../../common/js/utils";
|
import {checkoutTestManagerOrTestUser, hasRoles} from "../../../../common/js/utils";
|
||||||
import BatchMove from "./components/BatchMove";
|
import BatchMove from "./components/BatchMove";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TestCase",
|
name: "TestCase",
|
||||||
components: {
|
components: {
|
||||||
MsMainContainer,
|
MsMainContainer,
|
||||||
MsAsideContainer, MsContainer, TestCaseMove, TestCaseList, NodeTree, TestCaseEdit, SelectMenu, BatchMove},
|
MsAsideContainer, MsContainer, TestCaseMove, TestCaseList, NodeTree, TestCaseEdit, SelectMenu, BatchMove
|
||||||
comments: {},
|
},
|
||||||
data() {
|
comments: {},
|
||||||
return {
|
data() {
|
||||||
result: {},
|
return {
|
||||||
currentPage: 1,
|
result: {},
|
||||||
pageSize: 5,
|
currentPage: 1,
|
||||||
total: 0,
|
pageSize: 5,
|
||||||
projects: [],
|
total: 0,
|
||||||
currentProject: null,
|
projects: [],
|
||||||
treeNodes: [],
|
currentProject: null,
|
||||||
selectNodeIds: [],
|
treeNodes: [],
|
||||||
selectParentNodes: [],
|
selectNodeIds: [],
|
||||||
testCaseReadOnly: true,
|
selectParentNodes: [],
|
||||||
selectNode: {},
|
testCaseReadOnly: true,
|
||||||
nodeTreeDraggable: true,
|
selectNode: {},
|
||||||
|
nodeTreeDraggable: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.init(this.$route);
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'$route'(to, from) {
|
||||||
|
this.init(to);
|
||||||
|
},
|
||||||
|
currentProject() {
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init(route) {
|
||||||
|
let path = route.path;
|
||||||
|
if (path.indexOf("/track/case/edit") >= 0 || path.indexOf("/track/case/create") >= 0) {
|
||||||
|
this.getProjects();
|
||||||
|
this.testCaseReadOnly = false;
|
||||||
|
if (!checkoutTestManagerOrTestUser()) {
|
||||||
|
this.testCaseReadOnly = true;
|
||||||
|
}
|
||||||
|
let caseId = this.$route.params.caseId;
|
||||||
|
this.openRecentTestCaseEditDialog(caseId);
|
||||||
|
this.$router.push('/track/case/all');
|
||||||
|
} else if (route.params.projectId) {
|
||||||
|
this.getProjects();
|
||||||
|
this.getProjectById(route.params.projectId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
getProjects() {
|
||||||
this.init(this.$route);
|
this.$get("/project/listAll", (response) => {
|
||||||
},
|
this.projects = response.data;
|
||||||
watch: {
|
let lastProject = JSON.parse(localStorage.getItem(CURRENT_PROJECT));
|
||||||
'$route'(to, from) {
|
if (lastProject) {
|
||||||
this.init(to);
|
let hasCurrentProject = false;
|
||||||
},
|
for (let i = 0; i < this.projects.length; i++) {
|
||||||
currentProject() {
|
if (this.projects[i].id == lastProject.id) {
|
||||||
this.refresh();
|
this.currentProject = lastProject;
|
||||||
}
|
hasCurrentProject = true;
|
||||||
},
|
break;
|
||||||
methods: {
|
}
|
||||||
init(route) {
|
}
|
||||||
let path = route.path;
|
if (!hasCurrentProject) {
|
||||||
if (path.indexOf("/track/case/edit") >= 0 || path.indexOf("/track/case/create") >= 0){
|
this.setCurrentProject(this.projects[0]);
|
||||||
this.getProjects();
|
|
||||||
this.testCaseReadOnly = false;
|
|
||||||
if (!checkoutTestManagerOrTestUser()) {
|
|
||||||
this.testCaseReadOnly = true;
|
|
||||||
}
|
}
|
||||||
let caseId = this.$route.params.caseId;
|
|
||||||
this.openRecentTestCaseEditDialog(caseId);
|
|
||||||
this.$router.push('/track/case/all');
|
|
||||||
} else if (route.params.projectId){
|
|
||||||
this.getProjects();
|
|
||||||
this.getProjectById(route.params.projectId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getProjects() {
|
|
||||||
this.$get("/project/listAll", (response) => {
|
|
||||||
this.projects = response.data;
|
|
||||||
let lastProject = JSON.parse(localStorage.getItem(CURRENT_PROJECT));
|
|
||||||
if (lastProject) {
|
|
||||||
let hasCurrentProject = false;
|
|
||||||
for (let i = 0; i < this.projects.length; i++) {
|
|
||||||
if (this.projects[i].id == lastProject.id) {
|
|
||||||
this.currentProject = lastProject;
|
|
||||||
hasCurrentProject = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasCurrentProject) {
|
|
||||||
this.setCurrentProject(this.projects[0]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(this.projects.length > 0){
|
|
||||||
this.setCurrentProject(this.projects[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// this.checkProject();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
checkProject() {
|
|
||||||
if(this.currentProject === null) {
|
|
||||||
this.$alert(this.$t('test_track.case.no_project'), {
|
|
||||||
confirmButtonText: this.$t('project.create'),
|
|
||||||
callback: action => {
|
|
||||||
this.$router.push("/track/project/create");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeProject(project) {
|
|
||||||
this.setCurrentProject(project);
|
|
||||||
},
|
|
||||||
nodeChange(nodeIds, pNodes) {
|
|
||||||
this.selectNodeIds = nodeIds;
|
|
||||||
this.selectParentNodes = pNodes;
|
|
||||||
},
|
|
||||||
refreshTable() {
|
|
||||||
this.$refs.testCaseList.initTableData();
|
|
||||||
},
|
|
||||||
editTestCase(testCase) {
|
|
||||||
this.testCaseReadOnly = false;
|
|
||||||
if (this.treeNodes.length < 1) {
|
|
||||||
this.$warning(this.$t('test_track.case.create_module_first'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.$refs.testCaseEditDialog.open(testCase);
|
|
||||||
},
|
|
||||||
copyTestCase(testCase) {
|
|
||||||
this.testCaseReadOnly = false;
|
|
||||||
let item = {};
|
|
||||||
Object.assign(item, testCase);
|
|
||||||
item.name = '';
|
|
||||||
item.isCopy = true;
|
|
||||||
this.$refs.testCaseEditDialog.open(item);
|
|
||||||
},
|
|
||||||
showTestCaseDetail(testCase) {
|
|
||||||
this.testCaseReadOnly = true;
|
|
||||||
this.$refs.testCaseEditDialog.open(testCase);
|
|
||||||
},
|
|
||||||
getProjectByCaseId(caseId) {
|
|
||||||
return this.$get('/test/case/project/' + caseId, async response => {
|
|
||||||
this.setCurrentProject(response.data);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
refresh() {
|
|
||||||
this.selectNodeIds = [];
|
|
||||||
this.selectParentNodes = [];
|
|
||||||
this.selectNode = {};
|
|
||||||
this.$refs.testCaseList.initTableData();
|
|
||||||
this.getNodeTree();
|
|
||||||
},
|
|
||||||
openRecentTestCaseEditDialog(caseId) {
|
|
||||||
if (caseId) {
|
|
||||||
this.getProjectByCaseId(caseId);
|
|
||||||
this.$get('/test/case/get/' + caseId, response => {
|
|
||||||
if (response.data) {
|
|
||||||
this.$refs.testCaseEditDialog.open(response.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
this.$refs.testCaseEditDialog.open();
|
if (this.projects.length > 0) {
|
||||||
|
this.setCurrentProject(this.projects[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
// this.checkProject();
|
||||||
getProjectById(id) {
|
});
|
||||||
if (id && id != 'all') {
|
},
|
||||||
this.$get('/project/get/' + id, response => {
|
checkProject() {
|
||||||
let project = response.data;
|
if (this.currentProject === null) {
|
||||||
this.setCurrentProject(project);
|
this.$alert(this.$t('test_track.case.no_project'), {
|
||||||
// this.$router.push('/track/case/all');
|
confirmButtonText: this.$t('project.create'),
|
||||||
});
|
callback: action => {
|
||||||
}
|
this.$router.push("/track/project/create");
|
||||||
if (id === 'all') {
|
}
|
||||||
this.refresh();
|
});
|
||||||
}
|
|
||||||
},
|
|
||||||
setCurrentProject(project) {
|
|
||||||
if (project) {
|
|
||||||
this.currentProject = project;
|
|
||||||
localStorage.setItem(CURRENT_PROJECT, JSON.stringify(project));
|
|
||||||
}
|
|
||||||
this.refresh();
|
|
||||||
},
|
|
||||||
getNodeTree() {
|
|
||||||
if (!hasRoles(ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
|
||||||
this.nodeTreeDraggable = false;
|
|
||||||
}
|
|
||||||
if (this.currentProject) {
|
|
||||||
this.result = this.$get("/case/node/list/" + this.currentProject.id, response => {
|
|
||||||
this.treeNodes = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
moveToNode(selectIds) {
|
|
||||||
if (selectIds.size < 1) {
|
|
||||||
this.$warning(this.$t('test_track.plan_view.select_manipulate'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.$refs.testCaseEditDialog.getModuleOptions();
|
|
||||||
this.$refs.testCaseMove.open(this.$refs.testCaseEditDialog.moduleOptions, selectIds);
|
|
||||||
},
|
|
||||||
batchMove(selectIds) {
|
|
||||||
this.$refs.testBatchMove.open(this.treeNodes, selectIds,this.$refs.testCaseEditDialog.moduleOptions);
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
changeProject(project) {
|
||||||
|
this.setCurrentProject(project);
|
||||||
|
},
|
||||||
|
nodeChange(nodeIds, pNodes) {
|
||||||
|
this.selectNodeIds = nodeIds;
|
||||||
|
this.selectParentNodes = pNodes;
|
||||||
|
},
|
||||||
|
refreshTable() {
|
||||||
|
this.$refs.testCaseList.initTableData();
|
||||||
|
},
|
||||||
|
editTestCase(testCase) {
|
||||||
|
this.testCaseReadOnly = false;
|
||||||
|
if (this.treeNodes.length < 1) {
|
||||||
|
this.$warning(this.$t('test_track.case.create_module_first'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$refs.testCaseEditDialog.open(testCase);
|
||||||
|
},
|
||||||
|
copyTestCase(testCase) {
|
||||||
|
this.testCaseReadOnly = false;
|
||||||
|
let item = {};
|
||||||
|
Object.assign(item, testCase);
|
||||||
|
item.name = '';
|
||||||
|
item.isCopy = true;
|
||||||
|
this.$refs.testCaseEditDialog.open(item);
|
||||||
|
},
|
||||||
|
showTestCaseDetail(testCase) {
|
||||||
|
this.testCaseReadOnly = true;
|
||||||
|
this.$refs.testCaseEditDialog.open(testCase);
|
||||||
|
},
|
||||||
|
getProjectByCaseId(caseId) {
|
||||||
|
return this.$get('/test/case/project/' + caseId, async response => {
|
||||||
|
this.setCurrentProject(response.data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
refresh() {
|
||||||
|
this.selectNodeIds = [];
|
||||||
|
this.selectParentNodes = [];
|
||||||
|
this.selectNode = {};
|
||||||
|
this.$refs.testCaseList.initTableData();
|
||||||
|
this.getNodeTree();
|
||||||
|
},
|
||||||
|
openRecentTestCaseEditDialog(caseId) {
|
||||||
|
if (caseId) {
|
||||||
|
this.getProjectByCaseId(caseId);
|
||||||
|
this.$get('/test/case/get/' + caseId, response => {
|
||||||
|
if (response.data) {
|
||||||
|
this.$refs.testCaseEditDialog.open(response.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.$refs.testCaseEditDialog.open();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getProjectById(id) {
|
||||||
|
if (id && id != 'all') {
|
||||||
|
this.$get('/project/get/' + id, response => {
|
||||||
|
let project = response.data;
|
||||||
|
this.setCurrentProject(project);
|
||||||
|
// this.$router.push('/track/case/all');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (id === 'all') {
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setCurrentProject(project) {
|
||||||
|
if (project) {
|
||||||
|
this.currentProject = project;
|
||||||
|
localStorage.setItem(CURRENT_PROJECT, JSON.stringify(project));
|
||||||
|
}
|
||||||
|
this.refresh();
|
||||||
|
},
|
||||||
|
getNodeTree() {
|
||||||
|
if (!hasRoles(ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
||||||
|
this.nodeTreeDraggable = false;
|
||||||
|
}
|
||||||
|
if (this.currentProject) {
|
||||||
|
this.result = this.$get("/case/node/list/" + this.currentProject.id, response => {
|
||||||
|
this.treeNodes = response.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
moveToNode(selectIds) {
|
||||||
|
if (selectIds.size < 1) {
|
||||||
|
this.$warning(this.$t('test_track.plan_view.select_manipulate'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$refs.testCaseEditDialog.getModuleOptions();
|
||||||
|
this.$refs.testCaseMove.open(this.$refs.testCaseEditDialog.moduleOptions, selectIds);
|
||||||
|
},
|
||||||
|
batchMove(selectIds) {
|
||||||
|
this.$refs.testBatchMove.open(this.treeNodes, selectIds, this.$refs.testCaseEditDialog.moduleOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.el-main {
|
.el-main {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -161,6 +161,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
result: {},
|
result: {},
|
||||||
|
testCase: {},
|
||||||
dialogFormVisible: false,
|
dialogFormVisible: false,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
form: {
|
form: {
|
||||||
|
@ -190,9 +191,15 @@ export default {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$get('test/case/get/' + this.testCaseId, response => {
|
||||||
|
this.testCase = response.data;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {},
|
||||||
props: {
|
props: {
|
||||||
testCase: {
|
testCaseId: {
|
||||||
type: Object
|
type: String
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,9 +256,9 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import {TokenKey, WORKSPACE_ID} from '../../../../../common/js/constants';
|
import {TokenKey, WORKSPACE_ID} from '@/common/js/constants';
|
||||||
import MsDialogFooter from '../../../common/components/MsDialogFooter'
|
import MsDialogFooter from '../../../common/components/MsDialogFooter'
|
||||||
import {listenGoBack, removeGoBackListener} from "../../../../../common/js/utils";
|
import {listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
||||||
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||||
import {Message} from "element-ui";
|
import {Message} from "element-ui";
|
||||||
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
|
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
@filter-change="filter"
|
@filter-change="filter"
|
||||||
@select-all="handleSelectAll"
|
@select-all="handleSelectAll"
|
||||||
@select="handleSelectionChange"
|
@select="handleSelectionChange"
|
||||||
|
@cell-mouse-enter="showPopover"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
class="test-content adjust-table">
|
class="test-content adjust-table">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
|
@ -65,7 +66,7 @@
|
||||||
width="60%"
|
width="60%"
|
||||||
trigger="hover"
|
trigger="hover"
|
||||||
>
|
>
|
||||||
<test-case-detail :test-case="scope.row"/>
|
<test-case-detail v-if="currentCaseId === scope.row.id" :test-case-id="currentCaseId"/>
|
||||||
<span slot="reference">{{ scope.row.name }}</span>
|
<span slot="reference">{{ scope.row.name }}</span>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</template>
|
</template>
|
||||||
|
@ -166,11 +167,11 @@ import MethodTableItem from "../../common/tableItems/planview/MethodTableItem";
|
||||||
import MsTableOperator from "../../../common/components/MsTableOperator";
|
import MsTableOperator from "../../../common/components/MsTableOperator";
|
||||||
import MsTableOperatorButton from "../../../common/components/MsTableOperatorButton";
|
import MsTableOperatorButton from "../../../common/components/MsTableOperatorButton";
|
||||||
import MsTableButton from "../../../common/components/MsTableButton";
|
import MsTableButton from "../../../common/components/MsTableButton";
|
||||||
import {_filter, _sort} from "../../../../../common/js/utils";
|
import {_filter, _sort} from "@/common/js/utils";
|
||||||
import {TEST_CASE_CONFIGS} from "../../../common/components/search/search-components";
|
import {TEST_CASE_CONFIGS} from "../../../common/components/search/search-components";
|
||||||
import ShowMoreBtn from "./ShowMoreBtn";
|
import ShowMoreBtn from "./ShowMoreBtn";
|
||||||
import BatchEdit from "./BatchEdit";
|
import BatchEdit from "./BatchEdit";
|
||||||
import {WORKSPACE_ID} from "../../../../../common/js/constants";
|
import {WORKSPACE_ID} from "@/common/js/constants";
|
||||||
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||||
import StatusTableItem from "@/business/components/track/common/tableItems/planview/StatusTableItem";
|
import StatusTableItem from "@/business/components/track/common/tableItems/planview/StatusTableItem";
|
||||||
import TestCaseDetail from "./TestCaseDetail";
|
import TestCaseDetail from "./TestCaseDetail";
|
||||||
|
@ -187,336 +188,342 @@ export default {
|
||||||
PriorityTableItem,
|
PriorityTableItem,
|
||||||
MsCreateBox,
|
MsCreateBox,
|
||||||
TestCaseImport,
|
TestCaseImport,
|
||||||
TestCaseExport,
|
TestCaseExport,
|
||||||
MsTablePagination,
|
MsTablePagination,
|
||||||
NodeBreadcrumb,
|
NodeBreadcrumb,
|
||||||
MsTableHeader,
|
MsTableHeader,
|
||||||
ShowMoreBtn,
|
ShowMoreBtn,
|
||||||
BatchEdit,
|
BatchEdit,
|
||||||
StatusTableItem,
|
StatusTableItem,
|
||||||
TestCaseDetail,
|
TestCaseDetail,
|
||||||
ReviewStatus
|
ReviewStatus
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
result: {},
|
result: {},
|
||||||
deletePath: "/test/case/delete",
|
deletePath: "/test/case/delete",
|
||||||
condition: {
|
condition: {
|
||||||
components: TEST_CASE_CONFIGS
|
components: TEST_CASE_CONFIGS
|
||||||
},
|
},
|
||||||
tableData: [],
|
tableData: [],
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
total: 0,
|
||||||
selectRows: new Set(),
|
selectRows: new Set(),
|
||||||
priorityFilters: [
|
priorityFilters: [
|
||||||
{text: 'P0', value: 'P0'},
|
{text: 'P0', value: 'P0'},
|
||||||
{text: 'P1', value: 'P1'},
|
{text: 'P1', value: 'P1'},
|
||||||
{text: 'P2', value: 'P2'},
|
{text: 'P2', value: 'P2'},
|
||||||
{text: 'P3', value: 'P3'}
|
{text: 'P3', value: 'P3'}
|
||||||
],
|
],
|
||||||
methodFilters: [
|
methodFilters: [
|
||||||
{text: this.$t('test_track.case.manual'), value: 'manual'},
|
{text: this.$t('test_track.case.manual'), value: 'manual'},
|
||||||
{text: this.$t('test_track.case.auto'), value: 'auto'}
|
{text: this.$t('test_track.case.auto'), value: 'auto'}
|
||||||
],
|
],
|
||||||
typeFilters: [
|
typeFilters: [
|
||||||
{text: this.$t('commons.functional'), value: 'functional'},
|
{text: this.$t('commons.functional'), value: 'functional'},
|
||||||
{text: this.$t('commons.performance'), value: 'performance'},
|
{text: this.$t('commons.performance'), value: 'performance'},
|
||||||
{text: this.$t('commons.api'), value: 'api'}
|
{text: this.$t('commons.api'), value: 'api'}
|
||||||
],
|
],
|
||||||
statusFilters: [
|
statusFilters: [
|
||||||
{text: this.$t('test_track.case.status_prepare'), value: 'Prepare'},
|
{text: this.$t('test_track.case.status_prepare'), value: 'Prepare'},
|
||||||
{text: this.$t('test_track.case.status_pass'), value: 'Pass'},
|
{text: this.$t('test_track.case.status_pass'), value: 'Pass'},
|
||||||
{text: this.$t('test_track.case.status_un_pass'), value: 'UnPass'},
|
{text: this.$t('test_track.case.status_un_pass'), value: 'UnPass'},
|
||||||
],
|
],
|
||||||
showMore: false,
|
showMore: false,
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
name: this.$t('test_track.case.batch_edit_case'), handleClick: this.handleBatchEdit
|
name: this.$t('test_track.case.batch_edit_case'), handleClick: this.handleBatchEdit
|
||||||
}, {
|
}, {
|
||||||
name: this.$t('test_track.case.batch_move_case'), handleClick: this.handleBatchMove
|
name: this.$t('test_track.case.batch_move_case'), handleClick: this.handleBatchMove
|
||||||
}, {
|
}, {
|
||||||
name: this.$t('test_track.case.batch_delete_case'), handleClick: this.handleDeleteBatch
|
name: this.$t('test_track.case.batch_delete_case'), handleClick: this.handleDeleteBatch
|
||||||
}
|
|
||||||
],
|
|
||||||
typeArr: [
|
|
||||||
{id: 'priority', name: this.$t('test_track.case.priority')},
|
|
||||||
{id: 'type', name: this.$t('test_track.case.type')},
|
|
||||||
{id: 'method', name: this.$t('test_track.case.method')},
|
|
||||||
{id: 'maintainer', name: this.$t('test_track.case.maintainer')},
|
|
||||||
],
|
|
||||||
valueArr: {
|
|
||||||
priority: [
|
|
||||||
{name: 'P0', id: 'P0'},
|
|
||||||
{name: 'P1', id: 'P1'},
|
|
||||||
{name: 'P2', id: 'P2'},
|
|
||||||
{name: 'P3', id: 'P3'}
|
|
||||||
],
|
|
||||||
type: [
|
|
||||||
{name: this.$t('commons.functional'), id: 'functional'},
|
|
||||||
{name: this.$t('commons.performance'), id: 'performance'},
|
|
||||||
{name: this.$t('commons.api'), id: 'api'}
|
|
||||||
],
|
|
||||||
method: [
|
|
||||||
{name: this.$t('test_track.case.manual'), id: 'manual'},
|
|
||||||
{name: this.$t('test_track.case.auto'), id: 'auto'}
|
|
||||||
],
|
|
||||||
maintainer: [],
|
|
||||||
}
|
}
|
||||||
}
|
],
|
||||||
},
|
typeArr: [
|
||||||
props: {
|
{id: 'priority', name: this.$t('test_track.case.priority')},
|
||||||
currentProject: {
|
{id: 'type', name: this.$t('test_track.case.type')},
|
||||||
type: Object
|
{id: 'method', name: this.$t('test_track.case.method')},
|
||||||
|
{id: 'maintainer', name: this.$t('test_track.case.maintainer')},
|
||||||
|
],
|
||||||
|
valueArr: {
|
||||||
|
priority: [
|
||||||
|
{name: 'P0', id: 'P0'},
|
||||||
|
{name: 'P1', id: 'P1'},
|
||||||
|
{name: 'P2', id: 'P2'},
|
||||||
|
{name: 'P3', id: 'P3'}
|
||||||
|
],
|
||||||
|
type: [
|
||||||
|
{name: this.$t('commons.functional'), id: 'functional'},
|
||||||
|
{name: this.$t('commons.performance'), id: 'performance'},
|
||||||
|
{name: this.$t('commons.api'), id: 'api'}
|
||||||
|
],
|
||||||
|
method: [
|
||||||
|
{name: this.$t('test_track.case.manual'), id: 'manual'},
|
||||||
|
{name: this.$t('test_track.case.auto'), id: 'auto'}
|
||||||
|
],
|
||||||
|
maintainer: [],
|
||||||
},
|
},
|
||||||
selectNodeIds: {
|
currentCaseId: null
|
||||||
type: Array
|
}
|
||||||
},
|
},
|
||||||
selectParentNodes: {
|
props: {
|
||||||
type: Array
|
currentProject: {
|
||||||
}
|
type: Object
|
||||||
},
|
},
|
||||||
created: function () {
|
selectNodeIds: {
|
||||||
|
type: Array
|
||||||
|
},
|
||||||
|
selectParentNodes: {
|
||||||
|
type: Array
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created: function () {
|
||||||
|
this.initTableData();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
currentProject() {
|
||||||
this.initTableData();
|
this.initTableData();
|
||||||
},
|
},
|
||||||
watch: {
|
selectNodeIds() {
|
||||||
currentProject() {
|
this.currentPage = 1;
|
||||||
this.initTableData();
|
this.initTableData();
|
||||||
},
|
}
|
||||||
selectNodeIds() {
|
},
|
||||||
this.currentPage = 1;
|
methods: {
|
||||||
this.initTableData();
|
initTableData() {
|
||||||
|
if (this.planId) {
|
||||||
|
// param.planId = this.planId;
|
||||||
|
this.condition.planId = this.planId;
|
||||||
|
}
|
||||||
|
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
||||||
|
// param.nodeIds = this.selectNodeIds;
|
||||||
|
this.condition.nodeIds = this.selectNodeIds;
|
||||||
|
}
|
||||||
|
if (this.currentProject) {
|
||||||
|
this.condition.projectId = this.currentProject.id;
|
||||||
|
this.result = this.$post(this.buildPagePath('/test/case/list'), this.condition, response => {
|
||||||
|
let data = response.data;
|
||||||
|
this.total = data.itemCount;
|
||||||
|
this.tableData = data.listObject;
|
||||||
|
// this.selectIds.clear();
|
||||||
|
this.selectRows.clear();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
search() {
|
||||||
initTableData() {
|
this.initTableData();
|
||||||
if (this.planId) {
|
},
|
||||||
// param.planId = this.planId;
|
buildPagePath(path) {
|
||||||
this.condition.planId = this.planId;
|
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||||
}
|
},
|
||||||
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
testCaseCreate() {
|
||||||
// param.nodeIds = this.selectNodeIds;
|
this.$emit('testCaseEdit');
|
||||||
this.condition.nodeIds = this.selectNodeIds;
|
},
|
||||||
}
|
handleEdit(testCase) {
|
||||||
this.getData();
|
this.$get('test/case/get/' + testCase.id, response => {
|
||||||
},
|
let testCase = response.data;
|
||||||
getData() {
|
|
||||||
if (this.currentProject) {
|
|
||||||
this.condition.projectId = this.currentProject.id;
|
|
||||||
this.result = this.$post(this.buildPagePath('/test/case/list'), this.condition, response => {
|
|
||||||
let data = response.data;
|
|
||||||
this.total = data.itemCount;
|
|
||||||
this.tableData = data.listObject;
|
|
||||||
// this.selectIds.clear();
|
|
||||||
this.selectRows.clear();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
search() {
|
|
||||||
this.initTableData();
|
|
||||||
},
|
|
||||||
buildPagePath(path) {
|
|
||||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
|
||||||
},
|
|
||||||
testCaseCreate() {
|
|
||||||
this.$emit('testCaseEdit');
|
|
||||||
},
|
|
||||||
handleEdit(testCase) {
|
|
||||||
this.$emit('testCaseEdit', testCase);
|
this.$emit('testCaseEdit', testCase);
|
||||||
},
|
});
|
||||||
handleCopy(testCase) {
|
},
|
||||||
|
handleCopy(testCase) {
|
||||||
|
this.$get('test/case/get/' + testCase.id, response => {
|
||||||
|
let testCase = response.data;
|
||||||
this.$emit('testCaseCopy', testCase);
|
this.$emit('testCaseCopy', testCase);
|
||||||
},
|
});
|
||||||
handleDelete(testCase) {
|
},
|
||||||
this.$alert(this.$t('test_track.case.delete_confirm') + '\'' + testCase.name + '\'' + "?", '', {
|
handleDelete(testCase) {
|
||||||
confirmButtonText: this.$t('commons.confirm'),
|
this.$alert(this.$t('test_track.case.delete_confirm') + '\'' + testCase.name + '\'' + "?", '', {
|
||||||
callback: (action) => {
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
if (action === 'confirm') {
|
callback: (action) => {
|
||||||
this._handleDelete(testCase);
|
if (action === 'confirm') {
|
||||||
}
|
this._handleDelete(testCase);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
},
|
});
|
||||||
handleDeleteBatch() {
|
},
|
||||||
this.$alert(this.$t('test_track.case.delete_confirm') + "?", '', {
|
handleDeleteBatch() {
|
||||||
confirmButtonText: this.$t('commons.confirm'),
|
this.$alert(this.$t('test_track.case.delete_confirm') + "?", '', {
|
||||||
callback: (action) => {
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
if (action === 'confirm') {
|
callback: (action) => {
|
||||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
if (action === 'confirm') {
|
||||||
this.$post('/test/case/batch/delete', {ids: ids}, () => {
|
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||||
this.selectRows.clear();
|
this.$post('/test/case/batch/delete', {ids: ids}, () => {
|
||||||
this.$emit("refresh");
|
this.selectRows.clear();
|
||||||
this.$success(this.$t('commons.delete_success'));
|
this.$emit("refresh");
|
||||||
// 发送广播,刷新 head 上的最新列表
|
this.$success(this.$t('commons.delete_success'));
|
||||||
TrackEvent.$emit(LIST_CHANGE);
|
// 发送广播,刷新 head 上的最新列表
|
||||||
});
|
TrackEvent.$emit(LIST_CHANGE);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_handleDelete(testCase) {
|
||||||
|
let testCaseId = testCase.id;
|
||||||
|
this.$post('/test/case/delete/' + testCaseId, {}, () => {
|
||||||
|
this.initTableData();
|
||||||
|
this.$success(this.$t('commons.delete_success'));
|
||||||
|
// 发送广播,刷新 head 上的最新列表
|
||||||
|
TrackEvent.$emit(LIST_CHANGE);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
refresh() {
|
||||||
|
this.condition = {components: TEST_CASE_CONFIGS};
|
||||||
|
// this.selectIds.clear();
|
||||||
|
this.selectRows.clear();
|
||||||
|
this.$emit('refresh');
|
||||||
|
},
|
||||||
|
showDetail(row, event, column) {
|
||||||
|
this.$emit('testCaseDetail', row);
|
||||||
|
},
|
||||||
|
handleSelectAll(selection) {
|
||||||
|
if (selection.length > 0) {
|
||||||
|
this.tableData.forEach(item => {
|
||||||
|
this.$set(item, "showMore", true);
|
||||||
|
this.selectRows.add(item);
|
||||||
});
|
});
|
||||||
},
|
} else {
|
||||||
_handleDelete(testCase) {
|
|
||||||
let testCaseId = testCase.id;
|
|
||||||
this.$post('/test/case/delete/' + testCaseId, {}, () => {
|
|
||||||
this.initTableData();
|
|
||||||
this.$success(this.$t('commons.delete_success'));
|
|
||||||
// 发送广播,刷新 head 上的最新列表
|
|
||||||
TrackEvent.$emit(LIST_CHANGE);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
refresh() {
|
|
||||||
this.condition = {components: TEST_CASE_CONFIGS};
|
|
||||||
// this.selectIds.clear();
|
|
||||||
this.selectRows.clear();
|
this.selectRows.clear();
|
||||||
this.$emit('refresh');
|
this.tableData.forEach(row => {
|
||||||
},
|
|
||||||
showAll() {
|
|
||||||
this.condition = {components: TEST_CASE_CONFIGS};
|
|
||||||
this.getData();
|
|
||||||
},
|
|
||||||
showDetail(row, event, column) {
|
|
||||||
this.$emit('testCaseDetail', row);
|
|
||||||
},
|
|
||||||
handleSelectAll(selection) {
|
|
||||||
if (selection.length > 0) {
|
|
||||||
this.tableData.forEach(item => {
|
|
||||||
this.$set(item, "showMore", true);
|
|
||||||
this.selectRows.add(item);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.selectRows.clear();
|
|
||||||
this.tableData.forEach(row => {
|
|
||||||
this.$set(row, "showMore", false);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleSelectionChange(selection, row) {
|
|
||||||
if (this.selectRows.has(row)) {
|
|
||||||
this.$set(row, "showMore", false);
|
this.$set(row, "showMore", false);
|
||||||
this.selectRows.delete(row);
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSelectionChange(selection, row) {
|
||||||
|
if (this.selectRows.has(row)) {
|
||||||
|
this.$set(row, "showMore", false);
|
||||||
|
this.selectRows.delete(row);
|
||||||
|
} else {
|
||||||
|
this.$set(row, "showMore", true);
|
||||||
|
this.selectRows.add(row);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
importTestCase() {
|
||||||
|
this.$refs.testCaseImport.open();
|
||||||
|
},
|
||||||
|
exportTestCase() {
|
||||||
|
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||||
|
let config = {
|
||||||
|
url: '/test/case/export/testcase',
|
||||||
|
method: 'post',
|
||||||
|
responseType: 'blob',
|
||||||
|
// data: {ids: [...this.selectIds]}
|
||||||
|
data: {ids: ids, projectId: this.currentProject.id}
|
||||||
|
};
|
||||||
|
this.result = this.$request(config).then(response => {
|
||||||
|
const filename = this.$t('test_track.case.test_case') + ".xlsx";
|
||||||
|
const blob = new Blob([response.data]);
|
||||||
|
if ("download" in document.createElement("a")) {
|
||||||
|
let aTag = document.createElement('a');
|
||||||
|
aTag.download = filename;
|
||||||
|
aTag.href = URL.createObjectURL(blob);
|
||||||
|
aTag.click();
|
||||||
|
URL.revokeObjectURL(aTag.href)
|
||||||
} else {
|
} else {
|
||||||
this.$set(row, "showMore", true);
|
navigator.msSaveBlob(blob, filename);
|
||||||
this.selectRows.add(row);
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
importTestCase() {
|
},
|
||||||
this.$refs.testCaseImport.open();
|
handleBatch(type) {
|
||||||
},
|
|
||||||
exportTestCase() {
|
|
||||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
|
||||||
let config = {
|
|
||||||
url: '/test/case/export/testcase',
|
|
||||||
method: 'post',
|
|
||||||
responseType: 'blob',
|
|
||||||
// data: {ids: [...this.selectIds]}
|
|
||||||
data: {ids: ids, projectId: this.currentProject.id}
|
|
||||||
};
|
|
||||||
this.result = this.$request(config).then(response => {
|
|
||||||
const filename = this.$t('test_track.case.test_case') + ".xlsx";
|
|
||||||
const blob = new Blob([response.data]);
|
|
||||||
if ("download" in document.createElement("a")) {
|
|
||||||
let aTag = document.createElement('a');
|
|
||||||
aTag.download = filename;
|
|
||||||
aTag.href = URL.createObjectURL(blob);
|
|
||||||
aTag.click();
|
|
||||||
URL.revokeObjectURL(aTag.href)
|
|
||||||
} else {
|
|
||||||
navigator.msSaveBlob(blob, filename);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleBatch(type) {
|
|
||||||
|
|
||||||
if (this.selectRows.size < 1) {
|
if (this.selectRows.size < 1) {
|
||||||
if (type === 'export') {
|
if (type === 'export') {
|
||||||
this.$alert(this.$t('test_track.case.export_all_cases'), '', {
|
this.$alert(this.$t('test_track.case.export_all_cases'), '', {
|
||||||
confirmButtonText: this.$t('commons.confirm'),
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
callback: (action) => {
|
callback: (action) => {
|
||||||
if (action === 'confirm') {
|
if (action === 'confirm') {
|
||||||
this.exportTestCase();
|
this.exportTestCase();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
return;
|
})
|
||||||
} else {
|
return;
|
||||||
this.$warning(this.$t('test_track.plan_view.select_manipulate'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type === 'move') {
|
|
||||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
|
||||||
this.$emit('moveToNode', ids);
|
|
||||||
} else if (type === 'delete') {
|
|
||||||
this.handleDeleteBatch();
|
|
||||||
} else {
|
} else {
|
||||||
this.exportTestCase();
|
this.$warning(this.$t('test_track.plan_view.select_manipulate'));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
batchEdit(form) {
|
if (type === 'move') {
|
||||||
let arr = Array.from(this.selectRows);
|
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||||
let ids = arr.map(row => row.id);
|
this.$emit('moveToNode', ids);
|
||||||
let param = {};
|
} else if (type === 'delete') {
|
||||||
param[form.type] = form.value;
|
this.handleDeleteBatch();
|
||||||
param.ids = ids;
|
} else {
|
||||||
this.$post('/test/case/batch/edit', param, () => {
|
this.exportTestCase();
|
||||||
this.$success(this.$t('commons.save_success'));
|
}
|
||||||
this.refresh();
|
},
|
||||||
// 发送广播,刷新 head 上的最新列表
|
batchEdit(form) {
|
||||||
TrackEvent.$emit(LIST_CHANGE);
|
let arr = Array.from(this.selectRows);
|
||||||
});
|
let ids = arr.map(row => row.id);
|
||||||
},
|
let param = {};
|
||||||
filter(filters) {
|
param[form.type] = form.value;
|
||||||
_filter(filters, this.condition);
|
param.ids = ids;
|
||||||
this.initTableData();
|
this.$post('/test/case/batch/edit', param, () => {
|
||||||
},
|
this.$success(this.$t('commons.save_success'));
|
||||||
sort(column) {
|
this.refresh();
|
||||||
// 每次只对一个字段排序
|
// 发送广播,刷新 head 上的最新列表
|
||||||
if (this.condition.orders) {
|
TrackEvent.$emit(LIST_CHANGE);
|
||||||
this.condition.orders = [];
|
});
|
||||||
}
|
},
|
||||||
_sort(column, this.condition);
|
filter(filters) {
|
||||||
this.initTableData();
|
_filter(filters, this.condition);
|
||||||
},
|
this.initTableData();
|
||||||
handleBatchEdit() {
|
},
|
||||||
this.getMaintainerOptions();
|
sort(column) {
|
||||||
this.$refs.batchEdit.open();
|
// 每次只对一个字段排序
|
||||||
},
|
if (this.condition.orders) {
|
||||||
handleBatchMove() {
|
this.condition.orders = [];
|
||||||
this.$emit("batchMove", Array.from(this.selectRows).map(row => row.id));
|
}
|
||||||
},
|
_sort(column, this.condition);
|
||||||
getMaintainerOptions() {
|
this.initTableData();
|
||||||
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
},
|
||||||
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
|
handleBatchEdit() {
|
||||||
this.valueArr.maintainer = response.data;
|
this.getMaintainerOptions();
|
||||||
});
|
this.$refs.batchEdit.open();
|
||||||
|
},
|
||||||
|
handleBatchMove() {
|
||||||
|
this.$emit("batchMove", Array.from(this.selectRows).map(row => row.id));
|
||||||
|
},
|
||||||
|
getMaintainerOptions() {
|
||||||
|
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
||||||
|
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
|
||||||
|
this.valueArr.maintainer = response.data;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
showPopover(row, column, cell) {
|
||||||
|
if (column.property === 'name') {
|
||||||
|
console.log(row, column);
|
||||||
|
this.currentCaseId = row.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.table-page {
|
.table-page {
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
margin-right: -9px;
|
margin-right: -9px;
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.operate-button {
|
.operate-button {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.operate-button > div {
|
.operate-button > div {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search {
|
.search {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
width: 240px;
|
width: 240px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table {
|
.el-table {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue