大表功能完成
This commit is contained in:
1112
cdTMP/package-lock.json
generated
1112
cdTMP/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@arco-design/color": "^0.4.0",
|
"@arco-design/color": "^0.4.0",
|
||||||
"@arco-design/web-vue": "^2.57.0",
|
"@arco-design/web-vue": "^2.57.0",
|
||||||
"@tanstack/vue-query": "^5.74.9",
|
"@tanstack/vue-query": "^5.75.6",
|
||||||
"@tinymce/tinymce-vue": "^6.1.0",
|
"@tinymce/tinymce-vue": "^6.1.0",
|
||||||
"@vueuse/core": "^13.1.0",
|
"@vueuse/core": "^13.1.0",
|
||||||
"axios": "^1.9.0",
|
"axios": "^1.9.0",
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"file2md5": "^1.3.0",
|
"file2md5": "^1.3.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"lucide-vue-next": "^0.503.0",
|
"lucide-vue-next": "^0.509.0",
|
||||||
"mammoth": "^1.9.0",
|
"mammoth": "^1.9.0",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
@@ -32,35 +32,35 @@
|
|||||||
"qs": "^6.14.0",
|
"qs": "^6.14.0",
|
||||||
"tailwind-merge": "^3.2.0",
|
"tailwind-merge": "^3.2.0",
|
||||||
"tinymce": "^7.8.0",
|
"tinymce": "^7.8.0",
|
||||||
"tw-animate-css": "^1.2.8",
|
"tw-animate-css": "^1.2.9",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-clipboard3": "^2.0.0",
|
"vue-clipboard3": "^2.0.0",
|
||||||
"vue-color-kit": "^1.0.6",
|
"vue-color-kit": "^1.0.6",
|
||||||
"vue-data-ui": "^2.6.41",
|
"vue-data-ui": "^2.6.45",
|
||||||
"vue-router": "^4.5.1",
|
"vue-router": "^4.5.1",
|
||||||
"vuedraggable": "^2.24.3"
|
"vuedraggable": "^2.24.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4.1.4",
|
"@tailwindcss/postcss": "^4.1.6",
|
||||||
"@tailwindcss/vite": "^4.1.4",
|
"@tailwindcss/vite": "^4.1.6",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^22.15.3",
|
"@types/node": "^22.15.17",
|
||||||
"@types/nprogress": "^0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
"@types/qs": "^6.9.18",
|
"@types/qs": "^6.9.18",
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^5.2.4",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
||||||
"@vue/babel-plugin-jsx": "^1.4.0",
|
"@vue/babel-plugin-jsx": "^1.4.0",
|
||||||
"browserslist": "^4.24.4",
|
"browserslist": "^4.24.5",
|
||||||
"eslint": "^9.25.1",
|
"eslint": "^9.26.0",
|
||||||
"eslint-plugin-vue": "^10.0.1",
|
"eslint-plugin-vue": "^10.1.0",
|
||||||
"less": "^4.3.0",
|
"less": "^4.3.0",
|
||||||
"less-loader": "^12.2.0",
|
"less-loader": "^12.3.0",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"rollup-plugin-visualizer": "^5.14.0",
|
"rollup-plugin-visualizer": "^5.14.0",
|
||||||
"tailwindcss": "^4.1.4",
|
"tailwindcss": "^4.1.6",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vite": "^6.3.3",
|
"vite": "^6.3.5",
|
||||||
"vue-eslint-parser": "^10.1.3"
|
"vue-eslint-parser": "^10.1.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,16 @@ export default {
|
|||||||
params
|
params
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 查询单个测试项-id
|
||||||
|
* @returns 单个测试项数据
|
||||||
|
*/
|
||||||
|
getCaseOneById(id) {
|
||||||
|
return request({
|
||||||
|
url: `project/getCaseOneById?id=${id}`,
|
||||||
|
method: "get"
|
||||||
|
})
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 添加测试用例
|
* 添加测试用例
|
||||||
* @returns
|
* @returns
|
||||||
@@ -88,5 +98,38 @@ export default {
|
|||||||
method: "get",
|
method: "get",
|
||||||
params
|
params
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 提交选择的行、列,被替换内容,替换内容,请求后端替换
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
replace(data) {
|
||||||
|
return request({
|
||||||
|
url: "/project/case/replace/",
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 批量修改设计人员、执行人员、审核人员
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
personReplace(data = { selectRows: [], designPerson: "不替换", testPerson: "不替换", monitorPerson: "不替换" }) {
|
||||||
|
return request({
|
||||||
|
url: "/project/case/personReplace/",
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 批量替换事件
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
exetimeReplace(data = { selectRows: [], exetime: "" }) {
|
||||||
|
return request({
|
||||||
|
url: "/project/case/timeReplace/",
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 查询单个设计需求
|
* 查询单个设计需求-传统
|
||||||
* @returns 单个设计需求数据
|
* @returns 单个设计需求数据
|
||||||
*/
|
*/
|
||||||
getDesignDemandOne(params = {}) {
|
getDesignDemandOne(params = {}) {
|
||||||
@@ -23,6 +23,16 @@ export default {
|
|||||||
params
|
params
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 查询单个设计需求-id
|
||||||
|
* @returns 单个设计需求数据
|
||||||
|
*/
|
||||||
|
getDesignOneById(id) {
|
||||||
|
return request({
|
||||||
|
url: `project/getDesignOneById?id=${id}`,
|
||||||
|
method: "get"
|
||||||
|
})
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 编辑设计需求
|
* 编辑设计需求
|
||||||
* @returns 成功编辑或失败
|
* @returns 成功编辑或失败
|
||||||
@@ -88,5 +98,16 @@ export default {
|
|||||||
method: "get",
|
method: "get",
|
||||||
params
|
params
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 提交选择的行、列,被替换内容,替换内容,请求后端替换
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
replace(data) {
|
||||||
|
return request({
|
||||||
|
url: "/project/designDemand/replace/",
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,16 @@ export default {
|
|||||||
params
|
params
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 查询单个设计需求-根据id
|
||||||
|
* @returns 单个设计需求数据
|
||||||
|
*/
|
||||||
|
getDutOneById(id) {
|
||||||
|
return request({
|
||||||
|
url: `project/getDutOneById?id=${id}`,
|
||||||
|
method: "get"
|
||||||
|
})
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 添加被测件
|
* 添加被测件
|
||||||
* @returns
|
* @returns
|
||||||
|
|||||||
@@ -22,6 +22,16 @@ export default {
|
|||||||
params
|
params
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 查询单个测试项-id
|
||||||
|
* @returns 单个测试项数据
|
||||||
|
*/
|
||||||
|
getDemandOneById(id) {
|
||||||
|
return request({
|
||||||
|
url: `project/getTestDemandOneById?id=${id}`,
|
||||||
|
method: "get"
|
||||||
|
})
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 添加被测件
|
* 添加被测件
|
||||||
* @returns
|
* @returns
|
||||||
@@ -98,5 +108,16 @@ export default {
|
|||||||
method: "post",
|
method: "post",
|
||||||
data: params
|
data: params
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 提交选择的行、列,被替换内容,替换内容,请求后端替换
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
replace(data) {
|
||||||
|
return request({
|
||||||
|
url: "/project/testDemand/replace/",
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,18 @@ export default {
|
|||||||
params
|
params
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// ~~~~~~大表页面使用~~~~~~
|
||||||
|
/**
|
||||||
|
* 获取用户信息列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
getProjectList(project_id) {
|
||||||
|
return request({
|
||||||
|
url: "system/user/list",
|
||||||
|
method: "get",
|
||||||
|
params: { project_id }
|
||||||
|
})
|
||||||
|
},
|
||||||
// ~~~~~~usermanage~~~~~~页面的
|
// ~~~~~~usermanage~~~~~~页面的
|
||||||
/**
|
/**
|
||||||
* 添加用户
|
* 添加用户
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<a-descriptions-item
|
<a-descriptions-item
|
||||||
v-for="item in descriptions"
|
v-for="item in descriptions"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
:span="isArray(item.value) ? props.column : 1"
|
:span="item.span ? item.span : isArray(item.value) ? props.column : 1"
|
||||||
>
|
>
|
||||||
<template v-if="item.formType === 'upload'">
|
<template v-if="item.formType === 'upload'">
|
||||||
<a-image-preview-group infinite v-if="isArray(item.value)">
|
<a-image-preview-group infinite v-if="isArray(item.value)">
|
||||||
@@ -27,6 +27,25 @@
|
|||||||
<template v-else-if="item.infoSlot">
|
<template v-else-if="item.infoSlot">
|
||||||
<slot :name="item.dataIndex" :row="item" :data="data"></slot>
|
<slot :name="item.dataIndex" :row="item" :data="data"></slot>
|
||||||
</template>
|
</template>
|
||||||
|
<!-- 修改源码-如果dataIndex为testContent -->
|
||||||
|
<template v-else-if="item.dataIndex === 'testContent'">
|
||||||
|
<div class="overflow-y-auto max-h-80">
|
||||||
|
<template v-if="item.value.length > 0">
|
||||||
|
<template v-for="(sub, idx) in item.value" :key="idx">
|
||||||
|
<!-- 这是每个测试子项 -->
|
||||||
|
<div class="subTitle mt-1">{{ idx + 1 }}.{{ sub.subName }}</div>
|
||||||
|
<template v-for="(step, index) in sub.subStep" :key="index">
|
||||||
|
<span class="text-amber-700">步骤{{ index + 1 }})</span>
|
||||||
|
<div class="operation">
|
||||||
|
<span class="text-bold">操作:</span>{{ step.operation }}
|
||||||
|
</div>
|
||||||
|
<div class="mb-1"><span class="text-bold">预期:</span>{{ step.expect }}</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else>暂无信息</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<template
|
<template
|
||||||
v-else-if="item.formType === 'radio' || item.formType === 'select' || item.formType === 'checkbox'"
|
v-else-if="item.formType === 'radio' || item.formType === 'select' || item.formType === 'checkbox'"
|
||||||
>
|
>
|
||||||
@@ -46,7 +65,7 @@
|
|||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<div v-else>{{ item.value }} {{ item?.textAppend }}</div>
|
<div v-else><div class="white-space-change" v-html="item.value"></div></div>
|
||||||
</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
</a-descriptions>
|
</a-descriptions>
|
||||||
</a-space>
|
</a-space>
|
||||||
@@ -139,4 +158,8 @@ watch(
|
|||||||
defineExpose({ reset })
|
defineExpose({ reset })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped>
|
||||||
|
.white-space-change {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -86,6 +86,38 @@
|
|||||||
"
|
"
|
||||||
@click="() => handleRoundEditClick(nodeData)"
|
@click="() => handleRoundEditClick(nodeData)"
|
||||||
/></a-tooltip>
|
/></a-tooltip>
|
||||||
|
<a-tooltip content="综合阅览该轮次下问题单"
|
||||||
|
><icon-bug
|
||||||
|
style="
|
||||||
|
position: absolute;
|
||||||
|
right: 60px;
|
||||||
|
font-size: 12px;
|
||||||
|
top: 8px;
|
||||||
|
color: #3370ff;
|
||||||
|
"
|
||||||
|
@click="handleProblemShowClick"
|
||||||
|
/></a-tooltip>
|
||||||
|
<a-tooltip content="轮次数据管理视图"
|
||||||
|
><icon-storage
|
||||||
|
style="
|
||||||
|
position: absolute;
|
||||||
|
right: 77px;
|
||||||
|
font-size: 12px;
|
||||||
|
top: 8px;
|
||||||
|
color: #3370ff;
|
||||||
|
"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
router.push({
|
||||||
|
name: 'opeSets',
|
||||||
|
query: {
|
||||||
|
...route.query,
|
||||||
|
key: nodeData.key
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/></a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<!-- 设计节点的图标 -->
|
<!-- 设计节点的图标 -->
|
||||||
@@ -122,13 +154,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</a-layout-sider>
|
</a-layout-sider>
|
||||||
<a-layout class="layout-content myhcalc my-custom">
|
<a-layout class="layout-content myhcalc my-custom">
|
||||||
<a-layout-content class="work-area project-layout">
|
<!-- 右侧界面是该元素决定滚动条overflow-y:auto -->
|
||||||
|
<a-layout-content class="work-area project-layout" id="basic-scroll-container">
|
||||||
<PageLayout ref="routeViewRef" />
|
<PageLayout ref="routeViewRef" />
|
||||||
</a-layout-content>
|
</a-layout-content>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
|
<a-back-top target-container="#basic-scroll-container" :style="{ position: 'absolute' }">
|
||||||
|
<a-popover title="回到顶部">
|
||||||
|
<a-button type="primary" shape="circle">
|
||||||
|
<template #icon>
|
||||||
|
<icon-arrow-rise />
|
||||||
|
</template>
|
||||||
|
</a-button>
|
||||||
|
</a-popover>
|
||||||
|
</a-back-top>
|
||||||
<ma-form-modal
|
<ma-form-modal
|
||||||
ref="maFormModalRef"
|
ref="maFormModalRef"
|
||||||
:title="title"
|
:title="title"
|
||||||
@@ -249,7 +291,7 @@ import MaFormModal from "@/components/ma-form-modal/index.vue"
|
|||||||
import roundRight from "./treeComponents/roundRight.vue"
|
import roundRight from "./treeComponents/roundRight.vue"
|
||||||
// 问题单ma-crud
|
// 问题单ma-crud
|
||||||
import ProblemChoose from "@/views/project/case/components/ProblemChoose.vue"
|
import ProblemChoose from "@/views/project/case/components/ProblemChoose.vue"
|
||||||
import { useRoute } from "vue-router"
|
import { useRoute, useRouter } from "vue-router"
|
||||||
import { useTreeDataStore } from "@/store"
|
import { useTreeDataStore } from "@/store"
|
||||||
import { storeToRefs } from "pinia"
|
import { storeToRefs } from "pinia"
|
||||||
import Progress from "@/views/testmanage/projmanage/cpns/progress.vue"
|
import Progress from "@/views/testmanage/projmanage/cpns/progress.vue"
|
||||||
@@ -274,6 +316,7 @@ provide("rightViewRef", routeViewRef)
|
|||||||
const treeDataStore = useTreeDataStore()
|
const treeDataStore = useTreeDataStore()
|
||||||
const { treeData, currentNode } = storeToRefs(treeDataStore)
|
const { treeData, currentNode } = storeToRefs(treeDataStore)
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
const treeRef = ref()
|
const treeRef = ref()
|
||||||
const projectInfo = ref({ ...route.query })
|
const projectInfo = ref({ ...route.query })
|
||||||
const projectId = ref(route.query.id)
|
const projectId = ref(route.query.id)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { appRoutes } from "./routes"
|
|||||||
import { REDIRECT_MAIN, NOT_FOUND_ROUTE, PROJECT_LAYOUT } from "./routes/base"
|
import { REDIRECT_MAIN, NOT_FOUND_ROUTE, PROJECT_LAYOUT } from "./routes/base"
|
||||||
import createRouteGuard from "@/router/guard/index"
|
import createRouteGuard from "@/router/guard/index"
|
||||||
|
|
||||||
|
|
||||||
// 定义工作区路由名称,为了不写死
|
// 定义工作区路由名称,为了不写死
|
||||||
export const WORK_AREA_NAME = "project"
|
export const WORK_AREA_NAME = "project"
|
||||||
|
|
||||||
@@ -110,6 +109,18 @@ const router = createRouter({
|
|||||||
locale: "问题单详情",
|
locale: "问题单详情",
|
||||||
icon: "icon-arrow-right"
|
icon: "icon-arrow-right"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "opeSets",
|
||||||
|
name: "opeSets",
|
||||||
|
component: () => import("@/views/project/opeSets/index.vue"),
|
||||||
|
meta: {
|
||||||
|
requiresAuth: true,
|
||||||
|
ignoreCache: true,
|
||||||
|
roles: ["*"],
|
||||||
|
locale: "操作集合",
|
||||||
|
icon: "icon-arrow-right"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -72,4 +72,23 @@ const renameKeyInArray = (arr, oldKey, newKey) => {
|
|||||||
|
|
||||||
tool.renameKeyInArray = renameKeyInArray
|
tool.renameKeyInArray = renameKeyInArray
|
||||||
|
|
||||||
|
tool.chnRoundNameArray = [
|
||||||
|
"首轮",
|
||||||
|
"第二轮",
|
||||||
|
"第三轮",
|
||||||
|
"第四轮",
|
||||||
|
"第五轮",
|
||||||
|
"第六轮",
|
||||||
|
"第七轮",
|
||||||
|
"第八轮",
|
||||||
|
"第九轮",
|
||||||
|
"第十轮",
|
||||||
|
"第十一轮",
|
||||||
|
"第十二轮",
|
||||||
|
"第十三轮",
|
||||||
|
"第十四轮",
|
||||||
|
"第十五轮",
|
||||||
|
"第十六轮"
|
||||||
|
]
|
||||||
|
|
||||||
export default tool
|
export default tool
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-modal v-model:visible="visible" width="1200px" :footer="false" draggable>
|
<a-modal v-model:visible="visible" width="1200px" :footer="false" :mask-closable="false">
|
||||||
<template #title>{{ title }}</template>
|
<template #title>{{ title }}</template>
|
||||||
<!-- crud组件 -->
|
<!-- crud组件 -->
|
||||||
<div class="lg:w-full w-full">
|
<div class="lg:w-full w-full">
|
||||||
@@ -258,7 +258,7 @@ const crudOptions = ref({
|
|||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
title: "名称",
|
title: "名称",
|
||||||
align: "left",
|
align: "center",
|
||||||
search: true,
|
search: true,
|
||||||
dataIndex: "name",
|
dataIndex: "name",
|
||||||
commonRules: [{ required: true, message: "名称是必填" }],
|
commonRules: [{ required: true, message: "名称是必填" }],
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ export default function (crudOrFormRef: any) {
|
|||||||
placeholder: "对应测试项描述标题,和测试方法的标题",
|
placeholder: "对应测试项描述标题,和测试方法的标题",
|
||||||
rules: [{ required: true, message: "测试子项名称必填" }],
|
rules: [{ required: true, message: "测试子项名称必填" }],
|
||||||
onChange: (ev: any) => {
|
onChange: (ev: any) => {
|
||||||
|
if (crudOrFormRef) {
|
||||||
// 取出子项的对象数组
|
// 取出子项的对象数组
|
||||||
const subItemFormData = crudOrFormRef.value.getFormData().testContent
|
const subItemFormData = crudOrFormRef.value.getFormData().testContent
|
||||||
// 取出充分性条件字段字符串
|
// 取出充分性条件字段字符串
|
||||||
@@ -116,6 +117,7 @@ export default function (crudOrFormRef: any) {
|
|||||||
"、"
|
"、"
|
||||||
)}子项要求的全部内容。\n所有用例执行完毕,对于未执行的用例说明未执行原因。`
|
)}子项要求的全部内容。\n所有用例执行完毕,对于未执行的用例说明未执行原因。`
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "操作与预期",
|
title: "操作与预期",
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="jsx">
|
<script setup>
|
||||||
import { ref } from "vue"
|
import { ref } from "vue"
|
||||||
import useCrudOptions from "@/views/project/dut/hooks/useCrudOptions"
|
import useCrudOptions from "@/views/project/dut/hooks/useCrudOptions"
|
||||||
import useColumns from "./hooks/useColumns"
|
import useColumns from "./hooks/useColumns"
|
||||||
|
|||||||
31
cdTMP/src/views/project/opeSets/ProTable/index.vue
Normal file
31
cdTMP/src/views/project/opeSets/ProTable/index.vue
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<div class="pro-table-container">
|
||||||
|
<component :is="mapColumn[type]"></component>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import DesignTable from "../components/DesignTable/index.vue"
|
||||||
|
import DemandTable from "../components/DemandTable/index.vue"
|
||||||
|
import CaseTable from "../components/CaseTable/index.vue"
|
||||||
|
|
||||||
|
/* 导入columns看能不能行 */
|
||||||
|
// useColumns使用对应关系
|
||||||
|
const mapColumn = {
|
||||||
|
design: DesignTable,
|
||||||
|
demand: DemandTable,
|
||||||
|
case: CaseTable
|
||||||
|
}
|
||||||
|
// props
|
||||||
|
const { type } = defineProps<{
|
||||||
|
type: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
// query - 根据不同类型进行请求,传递轮次
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.pro-table-container{
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-container">
|
||||||
|
<a-modal v-model:visible="visible" width="70%" unmount-on-close ok-text="更新" :on-before-ok="handleBeforeOk">
|
||||||
|
<template #title>测试项-{{ modalTitle }}</template>
|
||||||
|
<ma-form v-model="form" ref="formRef" :columns="columnOptions" :options="options">
|
||||||
|
<template #inputPrepend-ident> XQ_XX </template>
|
||||||
|
</ma-form>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
import useOptions from "@/views/project/design-demand/DemandSubForm/useOptions"
|
||||||
|
import demandApi from "@/api/project/testDemand"
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
|
||||||
|
// route
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// refs
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
// emits
|
||||||
|
const emit = defineEmits(["refresh"])
|
||||||
|
|
||||||
|
// columns/options
|
||||||
|
const { options, columnOptions } = useOptions(formRef)
|
||||||
|
|
||||||
|
// modal-visible
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
// form-data
|
||||||
|
const form = ref({})
|
||||||
|
|
||||||
|
// 暴露给外部open函数
|
||||||
|
const modalTitle = ref("")
|
||||||
|
const open = async (rowData: any) => {
|
||||||
|
// 请求数据
|
||||||
|
try {
|
||||||
|
// 设置表单名称
|
||||||
|
modalTitle.value = rowData.title
|
||||||
|
const res = await demandApi.getDemandOneById(rowData.id)
|
||||||
|
// 更新表单
|
||||||
|
form.value = res.data
|
||||||
|
visible.value = true
|
||||||
|
} catch (e) {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 异步确认按钮点击
|
||||||
|
const handleBeforeOk = async () => {
|
||||||
|
const isValidated = await (formRef.value as any).validateForm()
|
||||||
|
if (isValidated) {
|
||||||
|
// 失败
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
// 成功 **变化**
|
||||||
|
const round = (form.value as any).key.split("-")[0]
|
||||||
|
const dut_key = (form.value as any).key.split("-")[1]
|
||||||
|
const designDemand = (form.value as any).key.split("-")[2]
|
||||||
|
await demandApi.update((form.value as any).id, {
|
||||||
|
project_id: route.query.id,
|
||||||
|
round,
|
||||||
|
designDemand,
|
||||||
|
...form.value,
|
||||||
|
dut: dut_key
|
||||||
|
})
|
||||||
|
// 刷新table
|
||||||
|
emit("refresh")
|
||||||
|
Message.success("修改成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// out use
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 注意该组件强制绑定caseTable页面,不要使用在其他地方了 -->
|
||||||
|
<div class="replace-person-container">
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="visible"
|
||||||
|
width="40%"
|
||||||
|
unmount-on-close
|
||||||
|
ok-text="替换执行时间"
|
||||||
|
cancel-text="关闭"
|
||||||
|
draggable
|
||||||
|
:on-before-ok="submitReplace"
|
||||||
|
>
|
||||||
|
<template #title>替换执行时间</template>
|
||||||
|
<div class="content-container">
|
||||||
|
<a-form ref="exeTime" :model="formData" scroll-to-first-error>
|
||||||
|
<a-form-item field="designPerson" label="执行时间">
|
||||||
|
<a-date-picker v-model="exetime" style="width: 200px" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
import caseApi from "@/api/project/case"
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
const formData = ref({})
|
||||||
|
const exetime = ref("")
|
||||||
|
// props
|
||||||
|
const { selectRows } = defineProps<{ selectRows: any }>()
|
||||||
|
|
||||||
|
// 2.异步执行替换操作,返回boolean-true则关闭弹窗
|
||||||
|
const submitReplace = async () => {
|
||||||
|
// 不再非受控验证,手动验证
|
||||||
|
if (exetime.value === "") {
|
||||||
|
Message.error("请选择时间后,进行替换操作")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (selectRows.length && selectRows.length > 0) {
|
||||||
|
// 判断是否选择了行
|
||||||
|
// 请求后台执行
|
||||||
|
await caseApi.exetimeReplace({
|
||||||
|
selectRows: selectRows,
|
||||||
|
exetime: exetime.value
|
||||||
|
})
|
||||||
|
Message.success("批量替换成功...")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
Message.error("请在表格中选择行...")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他:打开modal
|
||||||
|
const open = () => {
|
||||||
|
exetime.value = ""
|
||||||
|
visible.value = true
|
||||||
|
}
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 注意该组件强制绑定caseTable页面,不要使用在其他地方了 -->
|
||||||
|
<div class="replace-person-container">
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="visible"
|
||||||
|
width="40%"
|
||||||
|
unmount-on-close
|
||||||
|
ok-text="执行替换人员"
|
||||||
|
cancel-text="关闭"
|
||||||
|
draggable
|
||||||
|
:on-before-ok="submitReplace"
|
||||||
|
>
|
||||||
|
<template #title>替换人员</template>
|
||||||
|
<div class="content-container">
|
||||||
|
<a-form ref="formRef" :model="formData" scroll-to-first-error>
|
||||||
|
<a-form-item field="designPerson" label="设计人员">
|
||||||
|
<a-select v-model="designPerson">
|
||||||
|
<a-option v-for="person in persons" :key="person" :value="person">
|
||||||
|
{{ person }}
|
||||||
|
</a-option>
|
||||||
|
<a-option value="不替换">不替换</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="testPerson" label="执行人员">
|
||||||
|
<a-select v-model="testPerson">
|
||||||
|
<a-option v-for="person in persons" :key="person" :value="person">
|
||||||
|
{{ person }}
|
||||||
|
</a-option>
|
||||||
|
<a-option value="不替换">不替换</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="monitorPerson" label="审核人员">
|
||||||
|
<a-select v-model="monitorPerson">
|
||||||
|
<a-option v-for="person in persons" :key="person" :value="person">
|
||||||
|
{{ person }}
|
||||||
|
</a-option>
|
||||||
|
<a-option value="不替换">不替换</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
import userApi from "@/api/system/user"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
import caseApi from "@/api/project/case"
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const visible = ref(false)
|
||||||
|
const formData = ref({})
|
||||||
|
const designPerson = ref("不替换")
|
||||||
|
const testPerson = ref("不替换")
|
||||||
|
const monitorPerson = ref("不替换")
|
||||||
|
// props
|
||||||
|
const { selectRows } = defineProps<{ selectRows: any }>()
|
||||||
|
|
||||||
|
// 1.在created时候直接请求后端项目人员信息
|
||||||
|
const persons = ref([])
|
||||||
|
async function fetchPersonByProject() {
|
||||||
|
const res = await userApi.getProjectList(route.query.id)
|
||||||
|
persons.value = res.data.map((it: { name: string }) => it.name)
|
||||||
|
}
|
||||||
|
fetchPersonByProject()
|
||||||
|
|
||||||
|
// 2.异步执行替换操作,返回boolean-true则关闭弹窗
|
||||||
|
const submitReplace = async () => {
|
||||||
|
// 如果都选择不替换,则不请求
|
||||||
|
if (designPerson.value === "不替换" && testPerson.value === "不替换" && monitorPerson.value === "不替换") {
|
||||||
|
Message.error("至少选择一项替换")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (selectRows.length && selectRows.length > 0) {
|
||||||
|
// 判断是否选择了行
|
||||||
|
// 请求后台执行
|
||||||
|
await caseApi.personReplace({
|
||||||
|
selectRows: selectRows,
|
||||||
|
designPerson: designPerson.value,
|
||||||
|
testPerson: testPerson.value,
|
||||||
|
monitorPerson: monitorPerson.value
|
||||||
|
})
|
||||||
|
Message.success("批量替换成功...")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
Message.error("请在表格中选择行...")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他:打开modal
|
||||||
|
const open = () => {
|
||||||
|
designPerson.value = "不替换"
|
||||||
|
testPerson.value = "不替换"
|
||||||
|
monitorPerson.value = "不替换"
|
||||||
|
visible.value = true
|
||||||
|
}
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 该组件是表格查看上级节点的列(a-table-column) -->
|
||||||
|
<div class="trigger-container">
|
||||||
|
<a-trigger position="left" auto-fit-position update-at-scroll>
|
||||||
|
<a-link @click="(formRef as any).open(demandInfoJudge)">
|
||||||
|
{{ demandInfoJudge.title }}
|
||||||
|
<template #icon>
|
||||||
|
<icon-edit />
|
||||||
|
</template>
|
||||||
|
</a-link>
|
||||||
|
<template #content>
|
||||||
|
<div class="trigger-content">
|
||||||
|
<ma-info :columns="columns" :data="demandInfoJudge"></ma-info>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
|
<!-- dutForm组件 -->
|
||||||
|
<DemandForm ref="formRef" v-bind="$attrs" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from "vue"
|
||||||
|
import MaInfo from "@/components/ma-info/index.vue"
|
||||||
|
import DemandForm from "./DemandForm.vue"
|
||||||
|
import useColumn from "@/views/project/design-demand/hooks/useColumns"
|
||||||
|
|
||||||
|
// refs
|
||||||
|
const formRef = ref(null)
|
||||||
|
// 0.props-表示不通用代码
|
||||||
|
const { demandInfo } = defineProps<{ demandInfo: any }>()
|
||||||
|
// 计算属性单独处理
|
||||||
|
const demandInfoJudge = computed(() => {
|
||||||
|
return demandInfo
|
||||||
|
})
|
||||||
|
|
||||||
|
// 1.导入crud的columns属性,然后去掉不需要展示的内容,给ma-info传递信息
|
||||||
|
const originColumns = useColumn(undefined)
|
||||||
|
const columns = computed(() => {
|
||||||
|
return originColumns.value
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.trigger-content {
|
||||||
|
padding: 10px;
|
||||||
|
width: 50vw;
|
||||||
|
background-color: var(--color-bg-popup);
|
||||||
|
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-container">
|
||||||
|
<a-modal v-model:visible="visible" width="80%" unmount-on-close ok-text="更新" :on-before-ok="handleBeforeOk">
|
||||||
|
<template #title>测试用例-{{ modalTitle }}</template>
|
||||||
|
<ma-form v-model="form" ref="formRef" :columns="columnOptions" :options="options">
|
||||||
|
<template #inputPrepend-ident> YL-XX- </template>
|
||||||
|
</ma-form>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
import useOptions from "@/views/project/testDemand/CaseSubForm/useOptions"
|
||||||
|
import caseApi from "@/api/project/case"
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
|
||||||
|
// route
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// refs
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
// emits
|
||||||
|
const emit = defineEmits(["refresh"])
|
||||||
|
|
||||||
|
// columns/options
|
||||||
|
const { options, columnOptions } = useOptions(formRef)
|
||||||
|
|
||||||
|
// modal-visible
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
// form-data
|
||||||
|
const form = ref({})
|
||||||
|
|
||||||
|
// 暴露给外部open函数
|
||||||
|
const modalTitle = ref("")
|
||||||
|
const open = async (rowData: any) => {
|
||||||
|
// 请求数据
|
||||||
|
try {
|
||||||
|
// 设置表单名称
|
||||||
|
modalTitle.value = rowData.title
|
||||||
|
const res = await caseApi.getCaseOneById(rowData.id)
|
||||||
|
// 更新表单
|
||||||
|
form.value = res.data
|
||||||
|
visible.value = true
|
||||||
|
} catch (e) {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 异步确认按钮点击
|
||||||
|
const handleBeforeOk = async () => {
|
||||||
|
const isValidated = await (formRef.value as any).validateForm()
|
||||||
|
if (isValidated) {
|
||||||
|
// 失败
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
// 成功 **变化**
|
||||||
|
const round = (form.value as any).key.split("-")[0]
|
||||||
|
const dut = (form.value as any).key.split("-")[1]
|
||||||
|
const designDemand = (form.value as any).key.split("-")[2]
|
||||||
|
const testDemand = (form.value as any).key.split("-")[2]
|
||||||
|
await caseApi.update((form.value as any).id, {
|
||||||
|
project_id: route.query.id,
|
||||||
|
...form.value,
|
||||||
|
round,
|
||||||
|
designDemand,
|
||||||
|
testDemand,
|
||||||
|
dut: dut
|
||||||
|
})
|
||||||
|
// 刷新table
|
||||||
|
emit("refresh")
|
||||||
|
Message.success("修改成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// out use
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
285
cdTMP/src/views/project/opeSets/components/CaseTable/index.vue
Normal file
285
cdTMP/src/views/project/opeSets/components/CaseTable/index.vue
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
<template>
|
||||||
|
<div class="case-table-container">
|
||||||
|
<search v-show="searchVisible" @submit="searchSubmit" />
|
||||||
|
<div class="lg:flex justify-between mb-2">
|
||||||
|
<a-space>
|
||||||
|
<a-popconfirm
|
||||||
|
content="确定要删除数据吗? 这会删除全部下级数据!"
|
||||||
|
position="bottom"
|
||||||
|
@ok="deletesMultipleAction"
|
||||||
|
>
|
||||||
|
<a-button type="primary" status="danger">
|
||||||
|
批量删除
|
||||||
|
<template #icon><icon-delete /></template>
|
||||||
|
</a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
<a-button type="primary" @click="handleOpenReplaceModal">
|
||||||
|
批量替换
|
||||||
|
<template #icon><icon-swap /></template>
|
||||||
|
</a-button>
|
||||||
|
<a-divider direction="vertical"></a-divider>
|
||||||
|
<a-button type="primary" @click="handlePerpleModal">批量修改人员</a-button>
|
||||||
|
<a-button type="primary" @click="handleExetimeModal">批量修改时间</a-button>
|
||||||
|
</a-space>
|
||||||
|
<a-space>
|
||||||
|
<a-space class="lg:mt-0 mt-2">
|
||||||
|
<slot name="tools"></slot>
|
||||||
|
<a-tooltip content="刷新表格">
|
||||||
|
<a-button shape="circle" @click="fetchData()"><icon-refresh /></a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip content="显隐搜索" @click="searchVisible = !searchVisible">
|
||||||
|
<a-button shape="circle"><icon-search /></a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip content="设置">
|
||||||
|
<a-button shape="circle" @click="clickSetting"><icon-settings /></a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
<a-table
|
||||||
|
id="basic-table-case"
|
||||||
|
v-bind="options"
|
||||||
|
hoverable
|
||||||
|
column-resizable
|
||||||
|
ref="tableRef"
|
||||||
|
:scroll="{ x: '100%' }"
|
||||||
|
:row-selection="{ type: 'checkbox', showCheckedAll: true, onlyCurrent: true }"
|
||||||
|
row-key="id"
|
||||||
|
v-model:selectedKeys="selecteds"
|
||||||
|
:loading="isFetching"
|
||||||
|
:data="tableData"
|
||||||
|
:pagination="{
|
||||||
|
showTotal: true,
|
||||||
|
showPageSize: true,
|
||||||
|
total: total,
|
||||||
|
pageSizeOptions: [10, 20, 50, 1000],
|
||||||
|
hideOnSinglePage: false
|
||||||
|
}"
|
||||||
|
@page-change="pageChange"
|
||||||
|
@page-size-change="pageSizeChange"
|
||||||
|
>
|
||||||
|
<template #columns>
|
||||||
|
<!-- 数据列 -->
|
||||||
|
<template v-for="column in columns" :key="column.dataIndex">
|
||||||
|
<template v-if="!column.hide">
|
||||||
|
<!-- 专门为dataIndex===testStep构造的数据列 -->
|
||||||
|
<a-table-column v-bind="column" v-if="column.dataIndex === 'testStep'">
|
||||||
|
<template #cell="{ record }">
|
||||||
|
<div v-for="(step, index) in record[column.dataIndex]" :key="index">
|
||||||
|
<span class="text-amber-700">步骤{{ index + 1 }})</span>
|
||||||
|
<div class="operation">
|
||||||
|
<span class="text-lime-700">操作:</span>
|
||||||
|
<div v-html="step.operation"></div>
|
||||||
|
</div>
|
||||||
|
<div class="expect">
|
||||||
|
<span class="text-teal-700">预期:</span>
|
||||||
|
<div>{{ step.expect }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="expect">
|
||||||
|
<span class="text-rose-700">执行结果:</span>
|
||||||
|
<div v-html="step.result"></div>
|
||||||
|
</div>
|
||||||
|
<template v-if="record[column.dataIndex].length !== index + 1">
|
||||||
|
<a-divider></a-divider>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<!-- 正常的数据列 -->
|
||||||
|
<a-table-column v-bind="column" v-else tooltip>
|
||||||
|
<!-- 如果column有isHyperText属性,则直接渲染html -->
|
||||||
|
<template #cell="{ record }" v-if="column.isHyperText">
|
||||||
|
<div v-html="record[column.dataIndex]"></div>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<!-- 上级节点列 -->
|
||||||
|
<a-table-column title="对应测试项" align="center" :width="120" fixed="right">
|
||||||
|
<template #cell="{ record, column, rowIndex }">
|
||||||
|
<Trigger :demandInfo="record.test" @refresh="fetchData()" />
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<!-- 操作列 -->
|
||||||
|
<a-table-column title="操作" align="center" :width="100" fixed="right">
|
||||||
|
<template #cell="{ record }">
|
||||||
|
<a-scrollbar type="track" style="overflow: auto">
|
||||||
|
<a-space size="mini">
|
||||||
|
<a-link @click="(formRef as any).open(record)">
|
||||||
|
修改
|
||||||
|
<template #icon>
|
||||||
|
<icon-edit />
|
||||||
|
</template>
|
||||||
|
</a-link>
|
||||||
|
</a-space>
|
||||||
|
</a-scrollbar>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
<!-- 测试用例-表单页面 -->
|
||||||
|
<Form ref="formRef" @refresh="fetchData()"></Form>
|
||||||
|
<!-- 表格设置 -->
|
||||||
|
<my-setting ref="settingRef" @onChangeColumnHide="changeColumn"></my-setting>
|
||||||
|
<!-- 批量替换组件 -->
|
||||||
|
<replace-modal
|
||||||
|
ref="replaceModal"
|
||||||
|
:selectRows="selecteds"
|
||||||
|
:api="caseApi.replace"
|
||||||
|
:columns="columns"
|
||||||
|
key="modal-case"
|
||||||
|
popup-key="case"
|
||||||
|
@replaceSuccess="replaceSuccessHandle"
|
||||||
|
/>
|
||||||
|
<!-- 批量替换人员组件 -->
|
||||||
|
<replace-person :selectRows="selecteds" ref="replacePersonModalRef" />
|
||||||
|
<!-- 批量替换时间 -->
|
||||||
|
<replace-exetime :selectRows="selecteds" ref="replaceExetimeModalRef" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, provide } from "vue"
|
||||||
|
import caseApi from "@/api/project/case"
|
||||||
|
import type { ISearchFormCase } from "@/views/project/opeSets/components/DesignTable/types"
|
||||||
|
import useSettings from "@/views/project/opeSets/components/DesignTable/useSettings"
|
||||||
|
import MySetting from "@/views/project/opeSets/components/TableCommonComponent/Setting.vue"
|
||||||
|
import useFetchData from "@/views/project/opeSets/hooks/useFetchData"
|
||||||
|
import Search from "@/views/project/opeSets/components/DesignTable/Search.vue"
|
||||||
|
import Form from "./form.vue"
|
||||||
|
import Trigger from "./Trigger.vue"
|
||||||
|
import useDelete from "@/views/project/opeSets/components/DesignTable/useDelete"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
import ReplaceModal from "@/views/project/opeSets/components/DesignTable/ReplaceModal.vue"
|
||||||
|
// case专属组件
|
||||||
|
import ReplacePerson from "./ReplacePerson.vue"
|
||||||
|
import ReplaceExetime from "./ReplaceExetime.vue"
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: "标识",
|
||||||
|
dataIndex: "ident",
|
||||||
|
align: "center",
|
||||||
|
width: 80,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: true,
|
||||||
|
search: true,
|
||||||
|
formType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "名称",
|
||||||
|
dataIndex: "name",
|
||||||
|
align: "left",
|
||||||
|
width: 120,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: true,
|
||||||
|
search: true,
|
||||||
|
formType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "用例综述",
|
||||||
|
dataIndex: "summarize",
|
||||||
|
align: "left",
|
||||||
|
width: 150,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: false,
|
||||||
|
search: false, // 不搜索
|
||||||
|
formType: "input", // 搜索输入框形式
|
||||||
|
isHyperText: false,
|
||||||
|
bodyCellClass: "hyperTextCell-table-chen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 这是单独处理的字段,只声明Search组件相关属性
|
||||||
|
title: "测试步骤",
|
||||||
|
dataIndex: "testStep",
|
||||||
|
align: "left",
|
||||||
|
width: 400,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: false,
|
||||||
|
search: false, // 要搜索
|
||||||
|
formType: "input", // 搜索输入框形式
|
||||||
|
bodyCellClass: "hyperTextCell-table-chen"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
provide("columns", columns)
|
||||||
|
|
||||||
|
// 3.query查询和分页相关
|
||||||
|
const { tableData, isFetching, fetchData, total, pageChange, pageSizeChange, searchParams } = useFetchData(
|
||||||
|
caseApi.getCaseList,
|
||||||
|
columns
|
||||||
|
)
|
||||||
|
|
||||||
|
// 4.表单相关
|
||||||
|
const formRef = ref<InstanceType<typeof Form> | null>(null)
|
||||||
|
|
||||||
|
// 5.表格设置相关
|
||||||
|
const { options, clickSetting, changeColumn, settingRef } = useSettings()
|
||||||
|
|
||||||
|
// 6.行选择器相关-注意在fetchData时候没有清空(一定注意!!!)
|
||||||
|
const selecteds = ref([])
|
||||||
|
|
||||||
|
// 7.1.批量删除相关
|
||||||
|
const { deletesMultipleAction } = useDelete(caseApi.delete, fetchData, selecteds)
|
||||||
|
|
||||||
|
// 7.2.批量替换相关
|
||||||
|
const replaceModal = ref<InstanceType<typeof ReplaceModal> | null>(null)
|
||||||
|
const handleOpenReplaceModal = () => {
|
||||||
|
replaceModal.value?.open()
|
||||||
|
}
|
||||||
|
const replaceSuccessHandle = async (count: number) => {
|
||||||
|
Message.success(`批量更新成功,尝试更新行数:${count}`)
|
||||||
|
// 批量更新后刷新表格(疑问?是否要清除行选择?)
|
||||||
|
await fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8.搜索组件相关-注意这里submit其实就是给维护的搜索参数传参
|
||||||
|
const searchVisible = ref(true)
|
||||||
|
const searchSubmit = (data: ISearchFormCase) => {
|
||||||
|
searchParams.value = { ...data }
|
||||||
|
fetchData(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9.批量修改人员
|
||||||
|
const replacePersonModalRef = ref<InstanceType<typeof ReplacePerson>>()
|
||||||
|
const handlePerpleModal = () => {
|
||||||
|
replacePersonModalRef.value.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10.批量修改事件
|
||||||
|
const replaceExetimeModalRef = ref<InstanceType<typeof ReplacePerson>>()
|
||||||
|
const handleExetimeModal = () => {
|
||||||
|
replaceExetimeModalRef.value.open()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
/* 下面让modal的蒙层不交互,让用户可以复制table的文字 */
|
||||||
|
:deep(.arco-modal-container) {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
:deep(.arco-modal.arco-modal-draggable) {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search根组件
|
||||||
|
.search-container {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.hyperTextCell-table-chen {
|
||||||
|
.arco-table-td-content {
|
||||||
|
max-height: 15em;
|
||||||
|
overflow-y: auto;
|
||||||
|
line-height: 1.5em;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.arco-tabs-content-list {
|
||||||
|
height: 120%;
|
||||||
|
}
|
||||||
|
.arco-table-pagination {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-container">
|
||||||
|
<a-modal v-model:visible="visible" width="70%" unmount-on-close ok-text="更新" :on-before-ok="handleBeforeOk">
|
||||||
|
<template #title>设计需求-{{ modalTitle }}</template>
|
||||||
|
<ma-form v-model="form" ref="formRef" :columns="columnOptions" :options="options">
|
||||||
|
<template #inputPrepend-ident> SJ_XX </template>
|
||||||
|
</ma-form>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
import useOptions from "@/views/project/dut/DesignSubForm/useOptions"
|
||||||
|
import designApi from "@/api/project/designDemand"
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
|
||||||
|
// route
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// refs
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
// emits
|
||||||
|
const emit = defineEmits(["refresh"])
|
||||||
|
|
||||||
|
// columns/options
|
||||||
|
const { options, columnOptions } = useOptions(formRef)
|
||||||
|
|
||||||
|
// modal-visible
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
// form-data
|
||||||
|
const form = ref({})
|
||||||
|
|
||||||
|
// 暴露给外部open函数
|
||||||
|
const modalTitle = ref("")
|
||||||
|
const open = async (rowData: any) => {
|
||||||
|
// 请求数据
|
||||||
|
try {
|
||||||
|
// 设置表单名称
|
||||||
|
modalTitle.value = rowData.title
|
||||||
|
const res = await designApi.getDesignOneById(rowData.id)
|
||||||
|
// 更新表单
|
||||||
|
form.value = res.data
|
||||||
|
visible.value = true
|
||||||
|
} catch (e) {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 异步确认按钮点击
|
||||||
|
const handleBeforeOk = async () => {
|
||||||
|
const isValidated = await (formRef.value as any).validateForm()
|
||||||
|
if (isValidated) {
|
||||||
|
// 失败
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
// 成功 **变化**
|
||||||
|
const round = (form.value as any).key.split("-")[0]
|
||||||
|
const dut_key = (form.value as any).key.split("-")[1]
|
||||||
|
await designApi.update((form.value as any).id, {
|
||||||
|
project_id: route.query.id,
|
||||||
|
round,
|
||||||
|
...form.value,
|
||||||
|
dut: dut_key
|
||||||
|
})
|
||||||
|
// 刷新table
|
||||||
|
emit("refresh")
|
||||||
|
Message.success("修改成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// out use
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 该组件是表格查看上级节点的列(a-table-column) -->
|
||||||
|
<div class="trigger-container">
|
||||||
|
<a-trigger position="left" auto-fit-position update-at-scroll>
|
||||||
|
<a-link @click="(formRef as any).open(designInfo)">
|
||||||
|
{{ designInfo.title }}
|
||||||
|
<template #icon>
|
||||||
|
<icon-edit />
|
||||||
|
</template>
|
||||||
|
</a-link>
|
||||||
|
<template #content>
|
||||||
|
<div class="trigger-content">
|
||||||
|
<ma-info :columns="columns" :data="designInfoJudge"></ma-info>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
|
<!-- dutForm组件 -->
|
||||||
|
<DesignForm ref="formRef" v-bind="$attrs" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from "vue"
|
||||||
|
import MaInfo from "@/components/ma-info/index.vue"
|
||||||
|
import DesignForm from "./DesignForm.vue"
|
||||||
|
import useColumn from "@/views/project/dut/hooks/useColumns"
|
||||||
|
|
||||||
|
// refs
|
||||||
|
const formRef = ref(null)
|
||||||
|
// 0.props-表示不通用代码
|
||||||
|
const { designInfo } = defineProps<{ designInfo: any }>()
|
||||||
|
// 计算属性单独处理
|
||||||
|
const designInfoJudge = computed(() => {
|
||||||
|
return designInfo
|
||||||
|
})
|
||||||
|
|
||||||
|
// 1.导入crud的columns属性,然后去掉不需要展示的内容,给ma-info传递信息
|
||||||
|
const originColumns = useColumn(undefined)
|
||||||
|
const columns = computed(() => {
|
||||||
|
return originColumns.value
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.trigger-content {
|
||||||
|
padding: 10px;
|
||||||
|
width: 50vw;
|
||||||
|
background-color: var(--color-bg-popup);
|
||||||
|
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-container">
|
||||||
|
<a-modal v-model:visible="visible" width="80%" unmount-on-close ok-text="更新" :on-before-ok="handleBeforeOk">
|
||||||
|
<template #title>测试项-{{ modalTitle }}</template>
|
||||||
|
<ma-form v-model="form" ref="formRef" :columns="columnOptions" :options="options">
|
||||||
|
<template #inputPrepend-ident> XQ-XX- </template>
|
||||||
|
</ma-form>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
import useOptions from "@/views/project/design-demand/DemandSubForm/useOptions"
|
||||||
|
import demandApi from "@/api/project/testDemand"
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
|
||||||
|
// route
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// refs
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
// emits
|
||||||
|
const emit = defineEmits(["refresh"])
|
||||||
|
|
||||||
|
// columns/options
|
||||||
|
const { options, columnOptions } = useOptions(formRef)
|
||||||
|
|
||||||
|
// modal-visible
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
// form-data
|
||||||
|
const form = ref({})
|
||||||
|
|
||||||
|
// 暴露给外部open函数
|
||||||
|
const modalTitle = ref("")
|
||||||
|
const open = async (rowData: any) => {
|
||||||
|
// 请求数据
|
||||||
|
try {
|
||||||
|
// 设置表单名称
|
||||||
|
modalTitle.value = rowData.title
|
||||||
|
const res = await demandApi.getDemandOneById(rowData.id)
|
||||||
|
// 更新表单
|
||||||
|
form.value = res.data
|
||||||
|
visible.value = true
|
||||||
|
} catch (e) {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 异步确认按钮点击
|
||||||
|
const handleBeforeOk = async () => {
|
||||||
|
const isValidated = await (formRef.value as any).validateForm()
|
||||||
|
if (isValidated) {
|
||||||
|
// 失败
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
// 成功 **变化**
|
||||||
|
const round = (form.value as any).key.split("-")[0]
|
||||||
|
const dut = (form.value as any).key.split("-")[1]
|
||||||
|
const designDemand = (form.value as any).key.split("-")[2]
|
||||||
|
await demandApi.update((form.value as any).id, {
|
||||||
|
project_id: route.query.id,
|
||||||
|
...form.value,
|
||||||
|
round,
|
||||||
|
designDemand,
|
||||||
|
dut: dut
|
||||||
|
})
|
||||||
|
// 刷新table
|
||||||
|
emit("refresh")
|
||||||
|
Message.success("修改成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// out use
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
319
cdTMP/src/views/project/opeSets/components/DemandTable/index.vue
Normal file
319
cdTMP/src/views/project/opeSets/components/DemandTable/index.vue
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
<template>
|
||||||
|
<div class="demand-table-container">
|
||||||
|
<search v-show="searchVisible" @submit="searchSubmit" />
|
||||||
|
<div class="lg:flex justify-between mb-2">
|
||||||
|
<a-space>
|
||||||
|
<a-popconfirm
|
||||||
|
content="确定要删除数据吗? 这会删除全部下级数据!"
|
||||||
|
position="bottom"
|
||||||
|
@ok="deletesMultipleAction"
|
||||||
|
>
|
||||||
|
<a-button type="primary" status="danger">
|
||||||
|
批量删除
|
||||||
|
<template #icon><icon-delete /></template>
|
||||||
|
</a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
<a-button type="primary" @click="handleOpenReplaceModal">
|
||||||
|
批量替换
|
||||||
|
<template #icon><icon-swap /></template>
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
<a-space>
|
||||||
|
<a-space class="lg:mt-0 mt-2">
|
||||||
|
<slot name="tools"></slot>
|
||||||
|
<a-tooltip content="刷新表格">
|
||||||
|
<a-button shape="circle" @click="fetchData()"><icon-refresh /></a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip content="显隐搜索" @click="searchVisible = !searchVisible">
|
||||||
|
<a-button shape="circle"><icon-search /></a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip content="设置">
|
||||||
|
<a-button shape="circle" @click="clickSetting"><icon-settings /></a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
<a-table
|
||||||
|
id="basic-table-demand"
|
||||||
|
v-bind="options"
|
||||||
|
hoverable
|
||||||
|
column-resizable
|
||||||
|
ref="tableRef"
|
||||||
|
:scroll="{ x: '100%' }"
|
||||||
|
:row-selection="{ type: 'checkbox', showCheckedAll: true, onlyCurrent: true }"
|
||||||
|
row-key="id"
|
||||||
|
v-model:selectedKeys="selecteds"
|
||||||
|
:loading="isFetching"
|
||||||
|
:data="tableData"
|
||||||
|
:pagination="{
|
||||||
|
showTotal: true,
|
||||||
|
showPageSize: true,
|
||||||
|
total: total,
|
||||||
|
pageSizeOptions: [10, 20, 50, 1000],
|
||||||
|
hideOnSinglePage: false
|
||||||
|
}"
|
||||||
|
@page-change="pageChange"
|
||||||
|
@page-size-change="pageSizeChange"
|
||||||
|
>
|
||||||
|
<template #columns>
|
||||||
|
<!-- 数据列 -->
|
||||||
|
<template v-for="column in columns" :key="column.dataIndex">
|
||||||
|
<template v-if="!column.hide">
|
||||||
|
<!-- 正常的数据列 -->
|
||||||
|
<a-table-column
|
||||||
|
v-bind="column"
|
||||||
|
v-if="!column.showType && column.dataIndex !== 'testContent'"
|
||||||
|
tooltip
|
||||||
|
>
|
||||||
|
<!-- 如果column有isHyperText属性,则直接渲染html -->
|
||||||
|
<template #cell="{ record }" v-if="column.isHyperText">
|
||||||
|
<div v-html="record[column.dataIndex]"></div>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<!-- 对testContent单独渲染,区别很大!!! -->
|
||||||
|
<a-table-column v-bind="column" v-else-if="column.dataIndex === 'testContent'">
|
||||||
|
<template #cell="{ record }">
|
||||||
|
<div v-if="record[column.dataIndex].length > 0">
|
||||||
|
<!-- 如果有测试子项即subStep -->
|
||||||
|
<template v-for="(sub, idx) in record[column.dataIndex]" :key="idx">
|
||||||
|
<!-- 这是每个测试子项 -->
|
||||||
|
<div class="subTitle mt-1">{{ idx + 1 }}.{{ sub.subName }}</div>
|
||||||
|
<template v-for="(step, index) in sub.subStep" :key="index">
|
||||||
|
<span class="text-amber-700">步骤{{ index + 1 }})</span>
|
||||||
|
<div class="operation">
|
||||||
|
<span class="text-bold">操作:</span>{{ step.operation }}
|
||||||
|
</div>
|
||||||
|
<div class="mb-1">
|
||||||
|
<span class="text-bold">预期:</span>{{ step.expect }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<!-- 表示有showType字段 -->
|
||||||
|
<a-table-column v-bind="column" v-else-if="column.dataIndex === 'priority'" ellipsis tooltip>
|
||||||
|
<template #cell="{ record }">
|
||||||
|
{{ showType(record) }}
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column v-bind="column" v-else-if="column.dataIndex === 'testType'" ellipsis tooltip>
|
||||||
|
<template #cell="{ record }">
|
||||||
|
{{ showTestType(record) }}
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<!-- 上级节点列 -->
|
||||||
|
<a-table-column title="对应设计需求" align="center" :width="120" fixed="right">
|
||||||
|
<template #cell="{ record, column, rowIndex }">
|
||||||
|
<Trigger :designInfo="record.design" @refresh="fetchData()" />
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<!-- 操作列 -->
|
||||||
|
<a-table-column title="操作" align="center" :width="100" fixed="right">
|
||||||
|
<template #cell="{ record }">
|
||||||
|
<a-scrollbar type="track" style="overflow: auto">
|
||||||
|
<a-space size="mini">
|
||||||
|
<a-link @click="(formRef as any).open(record)">
|
||||||
|
修改
|
||||||
|
<template #icon>
|
||||||
|
<icon-edit />
|
||||||
|
</template>
|
||||||
|
</a-link>
|
||||||
|
</a-space>
|
||||||
|
</a-scrollbar>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
<!-- 测试项-表单页面 -->
|
||||||
|
<Form ref="formRef" @refresh="fetchData()"></Form>
|
||||||
|
<!-- 表格设置 -->
|
||||||
|
<my-setting ref="settingRef" @onChangeColumnHide="changeColumn"></my-setting>
|
||||||
|
<!-- 批量替换组件 -->
|
||||||
|
<replace-modal
|
||||||
|
ref="replaceModal"
|
||||||
|
:selectRows="selecteds"
|
||||||
|
:api="demandApi.replace"
|
||||||
|
:columns="columns"
|
||||||
|
key="modal-demand"
|
||||||
|
popup-key="demand"
|
||||||
|
@replaceSuccess="replaceSuccessHandle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { provide, ref } from "vue"
|
||||||
|
import type { ISearchFormDemand } from "@/views/project/opeSets/components/DesignTable/types"
|
||||||
|
import useSettings from "@/views/project/opeSets/components/DesignTable/useSettings"
|
||||||
|
import MySetting from "@/views/project/opeSets/components/TableCommonComponent/Setting.vue"
|
||||||
|
import useFetchData from "@/views/project/opeSets/hooks/useFetchData"
|
||||||
|
import demandApi from "@/api/project/testDemand"
|
||||||
|
import useShowType from "@/views/project/opeSets/components/DesignTable/useShowType"
|
||||||
|
import Form from "./form.vue"
|
||||||
|
import Trigger from "./Trigger.vue"
|
||||||
|
import Search from "@/views/project/opeSets/components/DesignTable/Search.vue"
|
||||||
|
import useDelete from "@/views/project/opeSets/components/DesignTable/useDelete"
|
||||||
|
import ReplaceModal from "@/views/project/opeSets/components/DesignTable/ReplaceModal.vue"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
|
||||||
|
// 0.[不同]定义列字段
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: "标识",
|
||||||
|
dataIndex: "ident",
|
||||||
|
align: "center",
|
||||||
|
width: 80,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: true,
|
||||||
|
search: true,
|
||||||
|
formType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "名称",
|
||||||
|
dataIndex: "name",
|
||||||
|
align: "left",
|
||||||
|
width: 120,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: true,
|
||||||
|
search: true,
|
||||||
|
formType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "优先级",
|
||||||
|
dataIndex: "priority",
|
||||||
|
align: "center",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: true,
|
||||||
|
search: true,
|
||||||
|
formType: "select",
|
||||||
|
dict: true,
|
||||||
|
// 只是指明a-table-column渲染v-if
|
||||||
|
showType: (text: string) => {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "测试类型",
|
||||||
|
dataIndex: "testType",
|
||||||
|
align: "center",
|
||||||
|
width: 80,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: true,
|
||||||
|
search: true,
|
||||||
|
formType: "select",
|
||||||
|
dict: true,
|
||||||
|
showType: (text: string) => {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "测项描述",
|
||||||
|
dataIndex: "testDesciption",
|
||||||
|
align: "left",
|
||||||
|
width: 200,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: false,
|
||||||
|
search: false, // 不搜索
|
||||||
|
formType: "input", // 搜索输入框形式
|
||||||
|
isHyperText: false,
|
||||||
|
bodyCellClass: "hyperTextCell-table-chen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 这是单独处理的字段,只声明Search组件相关属性
|
||||||
|
title: "测试子项",
|
||||||
|
dataIndex: "testContent",
|
||||||
|
align: "left",
|
||||||
|
width: 400,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: false,
|
||||||
|
search: false, // 要搜索
|
||||||
|
formType: "input", // 搜索输入框形式
|
||||||
|
bodyCellClass: "hyperTextCell-table-chen"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
provide("columns", columns)
|
||||||
|
|
||||||
|
// 2.获取demandType的名称
|
||||||
|
const showType = useShowType("priority")
|
||||||
|
const showTestType = useShowType("testType")
|
||||||
|
|
||||||
|
// 3.query查询和分页相关
|
||||||
|
const { tableData, isFetching, fetchData, total, pageChange, pageSizeChange, searchParams } = useFetchData(
|
||||||
|
demandApi.getTestDemandList,
|
||||||
|
columns
|
||||||
|
)
|
||||||
|
|
||||||
|
// 4.表单相关
|
||||||
|
const formRef = ref<InstanceType<typeof Form> | null>(null)
|
||||||
|
|
||||||
|
// 5.表格设置相关
|
||||||
|
const { options, clickSetting, changeColumn, settingRef } = useSettings()
|
||||||
|
|
||||||
|
// 6.行选择器相关-注意在fetchData时候没有清空(一定注意!!!)
|
||||||
|
const selecteds = ref([])
|
||||||
|
|
||||||
|
// 7.1.批量删除相关
|
||||||
|
const { deletesMultipleAction } = useDelete(demandApi.delete, fetchData, selecteds)
|
||||||
|
|
||||||
|
// 7.2.批量替换相关
|
||||||
|
const replaceModal = ref<InstanceType<typeof ReplaceModal> | null>(null)
|
||||||
|
const handleOpenReplaceModal = () => {
|
||||||
|
replaceModal.value?.open()
|
||||||
|
}
|
||||||
|
const replaceSuccessHandle = async (count: number) => {
|
||||||
|
Message.success(`批量更新成功,尝试更新行数:${count}`)
|
||||||
|
// 批量更新后刷新表格(疑问?是否要清除行选择?)
|
||||||
|
await fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8.搜索组件相关-注意这里submit其实就是给维护的搜索参数传参
|
||||||
|
const searchVisible = ref(true)
|
||||||
|
const searchSubmit = (data: ISearchFormDemand) => {
|
||||||
|
searchParams.value = { ...data }
|
||||||
|
fetchData(true)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
/* 下面让modal的蒙层不交互,让用户可以复制table的文字 */
|
||||||
|
:deep(.arco-modal-container) {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
:deep(.arco-modal.arco-modal-draggable) {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search根组件
|
||||||
|
.search-container {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.hyperTextCell-table-chen {
|
||||||
|
.arco-table-td-content {
|
||||||
|
max-height: 15em;
|
||||||
|
overflow-y: auto;
|
||||||
|
line-height: 1.5em;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.arco-tabs-content-list {
|
||||||
|
height: 120%;
|
||||||
|
}
|
||||||
|
.arco-table-pagination {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
// 对测试项子项步骤进行显示
|
||||||
|
.subTitle {
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.text-bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-container">
|
||||||
|
<a-modal v-model:visible="visible" width="40%" unmount-on-close ok-text="更新" :on-before-ok="handleBeforeOk">
|
||||||
|
<template #title>被测件-{{ modalTitle }}</template>
|
||||||
|
<ma-form v-model="form" ref="formRef" :columns="columnOptions" :options="options">
|
||||||
|
<template #inputPrepend-version> V </template>
|
||||||
|
</ma-form>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
import useOptions from "@/views/project/round/DutSubForm/useOptions"
|
||||||
|
import dutApi from "@/api/project/dut"
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
|
||||||
|
// route
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// refs
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
// emits
|
||||||
|
const emit = defineEmits(["refresh"])
|
||||||
|
|
||||||
|
// columns/options
|
||||||
|
const { options, columnOptions } = useOptions(formRef)
|
||||||
|
|
||||||
|
// modal-visible
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
// form-data
|
||||||
|
const form = ref({})
|
||||||
|
|
||||||
|
// 暴露给外部open函数
|
||||||
|
const modalTitle = ref("")
|
||||||
|
const open = async (rowData: any) => {
|
||||||
|
// 请求数据
|
||||||
|
try {
|
||||||
|
// 设置表单名称
|
||||||
|
modalTitle.value = rowData.title
|
||||||
|
const res = await dutApi.getDutOneById(rowData.id)
|
||||||
|
// 更新表单
|
||||||
|
form.value = res.data
|
||||||
|
visible.value = true
|
||||||
|
} catch (e) {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 异步确认按钮点击
|
||||||
|
const handleBeforeOk = async () => {
|
||||||
|
const isValidated = await (formRef.value as any).validateForm()
|
||||||
|
if (isValidated) {
|
||||||
|
// 失败
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
// 成功 **变化**
|
||||||
|
const round = (form.value as any).key.split("-")[0]
|
||||||
|
const dut = (form.value as any).key.split("-")[1]
|
||||||
|
await dutApi.update((form.value as any).id, {
|
||||||
|
project_id: route.query.id,
|
||||||
|
round,
|
||||||
|
dut,
|
||||||
|
...form.value
|
||||||
|
})
|
||||||
|
// 刷新table
|
||||||
|
emit("refresh")
|
||||||
|
Message.success("修改成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// out use
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
<template>
|
||||||
|
<div class="replace-modal-container">
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="visible"
|
||||||
|
:mask="false"
|
||||||
|
width="40%"
|
||||||
|
unmount-on-close
|
||||||
|
ok-text="替换选择的行和列"
|
||||||
|
cancel-text="关闭"
|
||||||
|
:popup-container="`#basic-table-${popupKey}`"
|
||||||
|
draggable
|
||||||
|
:on-before-ok="submitReplace"
|
||||||
|
:modal-style="{
|
||||||
|
boxShadow: '0 0 10px rgba(0, 0, 0, 0.5)'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #title>替换选择行和列</template>
|
||||||
|
<div class="content-container">
|
||||||
|
<a-form ref="formRef" :model="formData" scroll-to-first-error>
|
||||||
|
<a-form-item
|
||||||
|
field="selectColumn"
|
||||||
|
label="选择列"
|
||||||
|
show-colon
|
||||||
|
:rules="[{ type: 'array', required: true, message: '至少选择一列数据进行替换' }]"
|
||||||
|
>
|
||||||
|
<a-checkbox-group v-model="formData.selectColumn">
|
||||||
|
<a-checkbox
|
||||||
|
v-for="columnItem in columns"
|
||||||
|
:value="columnItem.dataIndex"
|
||||||
|
:key="columnItem.dataIndex"
|
||||||
|
>
|
||||||
|
{{ columnItem.title }}
|
||||||
|
</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
field="originText"
|
||||||
|
label="替换内容"
|
||||||
|
show-colon
|
||||||
|
:rules="[{ required: true, message: '请输入被替换文字' }]"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
>
|
||||||
|
<a-input v-model="formData.originText" placeholder="请输入替换内容" allow-clear />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="replaceText" label="替换为" :validate-trigger="['change', 'input']" show-colon>
|
||||||
|
<a-input
|
||||||
|
v-model="formData.replaceText"
|
||||||
|
placeholder="请输入替换为的内容,支持空格则替换为空格"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
import { Form, Message } from "@arco-design/web-vue"
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
|
||||||
|
// refs
|
||||||
|
const visible = ref(false)
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// ref
|
||||||
|
const formRef = ref<InstanceType<typeof Form>>(null)
|
||||||
|
|
||||||
|
// props
|
||||||
|
/// 已选择的行数据的id列表
|
||||||
|
const { selectRows, columns, api, popupKey } = defineProps<{
|
||||||
|
selectRows: number[]
|
||||||
|
columns: any[]
|
||||||
|
api: Function
|
||||||
|
popupKey: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
// emits
|
||||||
|
const emit = defineEmits(["replaceSuccess"])
|
||||||
|
|
||||||
|
// 1.form表单相关内容
|
||||||
|
/// 表单初始化数据
|
||||||
|
const initialFormData = {
|
||||||
|
selectColumn: [], // 选择影响的列
|
||||||
|
originText: "", // 被替换的文本
|
||||||
|
replaceText: "" // 替换的文本
|
||||||
|
}
|
||||||
|
/// 定义表单数据
|
||||||
|
const formData = ref(initialFormData)
|
||||||
|
|
||||||
|
// 2.提交替换申请
|
||||||
|
const submitReplace = async () => {
|
||||||
|
// 验证表单
|
||||||
|
const validate = await formRef.value.validate()
|
||||||
|
if (!validate) {
|
||||||
|
// 进入这里表示验证通过,手动验证是否选择了行
|
||||||
|
if (selectRows.length < 1) {
|
||||||
|
// 提示用户需要先选择table的行
|
||||||
|
Message.error("请先在表格中选择行进行替换")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 都验证后提交给后端操作
|
||||||
|
try {
|
||||||
|
const res = await api({
|
||||||
|
project_id: route.query.id,
|
||||||
|
round_key: route.query.key,
|
||||||
|
selectRows,
|
||||||
|
...formData.value
|
||||||
|
})
|
||||||
|
// 批量修改成功放出信号给父组件更新表格
|
||||||
|
emit("replaceSuccess", res.data.count)
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// expose functions
|
||||||
|
const open = () => {
|
||||||
|
// 每次打开初始化表单数据
|
||||||
|
formData.value = {
|
||||||
|
...initialFormData
|
||||||
|
}
|
||||||
|
visible.value = true
|
||||||
|
}
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less"></style>
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
<template>
|
||||||
|
<div class="search-container">
|
||||||
|
<a-spin :loading="searchLoading" class="w-full" tip="正在加载中...">
|
||||||
|
<a-form :model="searchForm" layout="inline" label-align="right" ref="searchRef" @submit="handlerSearch">
|
||||||
|
<div class="grid w-full lg:grid-cols-3">
|
||||||
|
<template v-for="column in columns" :key="column.dataIndex">
|
||||||
|
<a-form-item
|
||||||
|
class="w-full"
|
||||||
|
:field="column.dataIndex"
|
||||||
|
:label="column.title"
|
||||||
|
:label-col-style="{ minWidth: '80px' }"
|
||||||
|
>
|
||||||
|
<slot :name="`${column.dataIndex}`" v-bind="{ searchForm, column }">
|
||||||
|
<component
|
||||||
|
:is="getComponentName(column.searchFormType ?? column.formType)"
|
||||||
|
:component="column"
|
||||||
|
/>
|
||||||
|
</slot>
|
||||||
|
</a-form-item>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class="text-right mt-1 mr-6 w-full">
|
||||||
|
<a-space>
|
||||||
|
<a-button html-type="submit" type="primary">
|
||||||
|
<template #icon><icon-search /></template>
|
||||||
|
搜索
|
||||||
|
</a-button>
|
||||||
|
<a-button type="outline" @click="resetSearchForm">
|
||||||
|
<template #icon><icon-refresh /></template>
|
||||||
|
重置
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</a-form>
|
||||||
|
</a-spin>
|
||||||
|
<a-divider></a-divider>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { inject, markRaw, provide, ref } from "vue"
|
||||||
|
import { Form } from "@arco-design/web-vue"
|
||||||
|
import MaFormInput from "@/components/ma-crud/components/searchFormItem/form-input.vue"
|
||||||
|
import MaFormSelect from "@/components/ma-crud/components/searchFormItem/form-select.vue"
|
||||||
|
import dictApi from "@/api/system/dict"
|
||||||
|
import type { ISearchForm } from "./types"
|
||||||
|
|
||||||
|
const columns = inject("columns") as any // 传入的列信息
|
||||||
|
|
||||||
|
const emit = defineEmits(["submit"])
|
||||||
|
|
||||||
|
const searchLoading = ref(false)
|
||||||
|
const searchRef = ref<InstanceType<typeof Form>>()
|
||||||
|
|
||||||
|
const searchForm = ref({}) // 搜索表单数据
|
||||||
|
provide("searchForm", searchForm)
|
||||||
|
|
||||||
|
// 点击搜索按钮
|
||||||
|
const handlerSearch = (data: { values: ISearchForm }) => {
|
||||||
|
emit("submit", data.values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击重置按钮
|
||||||
|
const resetSearchForm = () => {
|
||||||
|
searchRef.value.resetFields()
|
||||||
|
emit("submit", searchForm.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5.获取搜索框的类型组件
|
||||||
|
const componentList = ref({
|
||||||
|
MaFormInput: markRaw(MaFormInput),
|
||||||
|
MaFormSelect: markRaw(MaFormSelect)
|
||||||
|
})
|
||||||
|
|
||||||
|
const getComponentName = (formType: string) => {
|
||||||
|
if (["select", "radio", "checkbox", "transfer"].includes(formType)) {
|
||||||
|
return componentList.value["MaFormSelect"]
|
||||||
|
} else {
|
||||||
|
return componentList.value["MaFormInput"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6.dicts - 需要根据dict来请求后端
|
||||||
|
const dicts = ref({})
|
||||||
|
provide("dicts", dicts)
|
||||||
|
columns.value.map(async (it: any) => {
|
||||||
|
searchLoading.value = true
|
||||||
|
// 处理带dict和formType为select的
|
||||||
|
if (it.dict && it.formType === "select") {
|
||||||
|
const res = await dictApi.getDictByCode({ code: it.dataIndex })
|
||||||
|
dicts.value[it.dataIndex] = res.data.map((it) => ({
|
||||||
|
label: it.title,
|
||||||
|
value: it.key
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
searchLoading.value = false
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
div:deep(.arco-form-layout-inline) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.lg\:grid-cols-1 {
|
||||||
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-2 {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-3 {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-4 {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-5 {
|
||||||
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-6 {
|
||||||
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-7 {
|
||||||
|
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-8 {
|
||||||
|
grid-template-columns: repeat(8, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-9 {
|
||||||
|
grid-template-columns: repeat(9, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-10 {
|
||||||
|
grid-template-columns: repeat(10, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-11 {
|
||||||
|
grid-template-columns: repeat(11, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.lg\:grid-cols-12 {
|
||||||
|
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 该组件是表格查看上级节点的列(a-table-column) -->
|
||||||
|
<div class="trigger-container">
|
||||||
|
<a-trigger position="left" auto-fit-position update-at-scroll>
|
||||||
|
<a-link @click="(formRef as any).open(dutInfo)">
|
||||||
|
{{ dutInfo.title }}
|
||||||
|
<template #icon>
|
||||||
|
<icon-edit />
|
||||||
|
</template>
|
||||||
|
</a-link>
|
||||||
|
<template #content>
|
||||||
|
<div class="trigger-content">
|
||||||
|
<ma-info :columns="columns" :data="dutInfoJudge"></ma-info>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
|
<!-- dutForm组件 -->
|
||||||
|
<DutForm ref="formRef" v-bind="$attrs" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from "vue"
|
||||||
|
import MaInfo from "@/components/ma-info/index.vue"
|
||||||
|
import DutForm from "./DutForm.vue"
|
||||||
|
|
||||||
|
// refs
|
||||||
|
const formRef = ref(null)
|
||||||
|
// 0.props-表示不通用代码
|
||||||
|
const { dutInfo } = defineProps<{ dutInfo: any }>()
|
||||||
|
// 计算属性单独处理
|
||||||
|
const dutInfoJudge = computed(() => {
|
||||||
|
if (dutInfo.type === "SO") {
|
||||||
|
// 计算注释率:注释行/总行数
|
||||||
|
dutInfo.comment_percent = (dutInfo.comment_lines / dutInfo.total_lines) * 100 + "%"
|
||||||
|
} else {
|
||||||
|
// 如果是非源代码被测件行数均填写:“不适用”
|
||||||
|
dutInfo.comment_lines = "不适用"
|
||||||
|
dutInfo.comment_percent = "不适用"
|
||||||
|
dutInfo.effective_lines = "不适用"
|
||||||
|
dutInfo.total_lines = "不适用"
|
||||||
|
}
|
||||||
|
return dutInfo
|
||||||
|
})
|
||||||
|
|
||||||
|
// 1.导入crud的columns属性,然后去掉不需要展示的内容
|
||||||
|
import useColumn from "@/views/project/round/hooks/useColumn"
|
||||||
|
const originColumns = useColumn(undefined)
|
||||||
|
const columns = computed(() => {
|
||||||
|
// 去掉上传源代码字段
|
||||||
|
const quUploadColumns = originColumns.value.filter((it) => it.dataIndex !== "upload")
|
||||||
|
// 判断是否为源代码被测件
|
||||||
|
return quUploadColumns
|
||||||
|
})
|
||||||
|
|
||||||
|
// 2.异步获取数据
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.trigger-content {
|
||||||
|
padding: 10px;
|
||||||
|
width: 30vw;
|
||||||
|
background-color: var(--color-bg-popup);
|
||||||
|
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-container">
|
||||||
|
<a-modal v-model:visible="visible" width="80%" unmount-on-close ok-text="更新" :on-before-ok="handleBeforeOk">
|
||||||
|
<template #title>设计需求-{{ modalTitle }}</template>
|
||||||
|
<ma-form v-model="form" ref="formRef" :columns="columnOptions" :options="options">
|
||||||
|
<template #inputPrepend-ident> SJ-XX- </template>
|
||||||
|
</ma-form>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
import useOptions from "@/views/project/dut/DesignSubForm/useOptions"
|
||||||
|
import designApi from "@/api/project/designDemand"
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
|
||||||
|
// route
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// refs
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
// emits
|
||||||
|
const emit = defineEmits(["refresh"])
|
||||||
|
|
||||||
|
// columns/options
|
||||||
|
const { options, columnOptions } = useOptions(formRef)
|
||||||
|
|
||||||
|
// modal-visible
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
// form-data
|
||||||
|
const form = ref({})
|
||||||
|
|
||||||
|
// 暴露给外部open函数
|
||||||
|
const modalTitle = ref("")
|
||||||
|
const open = async (rowData: any) => {
|
||||||
|
// 请求数据
|
||||||
|
try {
|
||||||
|
// 设置表单名称
|
||||||
|
modalTitle.value = rowData.title
|
||||||
|
const res = await designApi.getDesignOneById(rowData.id)
|
||||||
|
// 更新表单
|
||||||
|
form.value = res.data
|
||||||
|
visible.value = true
|
||||||
|
} catch (e) {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 异步确认按钮点击
|
||||||
|
const handleBeforeOk = async () => {
|
||||||
|
const isValidated = await (formRef.value as any).validateForm()
|
||||||
|
if (isValidated) {
|
||||||
|
// 失败
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
// 成功 **变化**
|
||||||
|
const round = (form.value as any).key.split("-")[0]
|
||||||
|
const dut = (form.value as any).key.split("-")[1]
|
||||||
|
await designApi.update((form.value as any).id, {
|
||||||
|
project_id: route.query.id,
|
||||||
|
...form.value,
|
||||||
|
round,
|
||||||
|
dut: dut
|
||||||
|
})
|
||||||
|
// 刷新table
|
||||||
|
emit("refresh")
|
||||||
|
Message.success("修改成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// out use
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
263
cdTMP/src/views/project/opeSets/components/DesignTable/index.vue
Normal file
263
cdTMP/src/views/project/opeSets/components/DesignTable/index.vue
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
<template>
|
||||||
|
<div class="design-table-container">
|
||||||
|
<search v-show="searchVisible" @submit="searchSubmit" />
|
||||||
|
<div class="lg:flex justify-between mb-2">
|
||||||
|
<a-space>
|
||||||
|
<a-popconfirm
|
||||||
|
content="确定要删除数据吗? 这会删除全部下级数据!"
|
||||||
|
position="bottom"
|
||||||
|
@ok="deletesMultipleAction"
|
||||||
|
>
|
||||||
|
<a-button type="primary" status="danger">
|
||||||
|
批量删除
|
||||||
|
<template #icon><icon-delete /></template>
|
||||||
|
</a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
<a-button type="primary" @click="handleOpenReplaceModal">
|
||||||
|
批量替换
|
||||||
|
<template #icon><icon-swap /></template>
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
<a-space>
|
||||||
|
<a-space class="lg:mt-0 mt-2">
|
||||||
|
<slot name="tools"></slot>
|
||||||
|
<a-tooltip content="刷新表格">
|
||||||
|
<a-button shape="circle" @click="fetchData()"><icon-refresh /></a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip content="显隐搜索" @click="searchVisible = !searchVisible">
|
||||||
|
<a-button shape="circle"><icon-search /></a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip content="设置">
|
||||||
|
<a-button shape="circle" @click="clickSetting"><icon-settings /></a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
<a-table
|
||||||
|
id="basic-table-design"
|
||||||
|
v-bind="options"
|
||||||
|
hoverable
|
||||||
|
column-resizable
|
||||||
|
ref="tableRef"
|
||||||
|
:scroll="{ x: '100%' }"
|
||||||
|
:row-selection="{ type: 'checkbox', showCheckedAll: true, onlyCurrent: true }"
|
||||||
|
row-key="id"
|
||||||
|
v-model:selectedKeys="selecteds"
|
||||||
|
:loading="isFetching"
|
||||||
|
:data="tableData"
|
||||||
|
:pagination="{
|
||||||
|
showTotal: true,
|
||||||
|
showPageSize: true,
|
||||||
|
total: total,
|
||||||
|
pageSizeOptions: [10, 20, 50, 1000],
|
||||||
|
hideOnSinglePage: false
|
||||||
|
}"
|
||||||
|
@page-change="pageChange"
|
||||||
|
@page-size-change="pageSizeChange"
|
||||||
|
>
|
||||||
|
<template #columns>
|
||||||
|
<!-- 数据列 -->
|
||||||
|
<template v-for="column in columns" :key="column.dataIndex">
|
||||||
|
<template v-if="!column.hide">
|
||||||
|
<!-- 正常的数据列 -->
|
||||||
|
<a-table-column v-bind="column" v-if="!column.showType" tooltip>
|
||||||
|
<!-- 如果column有isHyperText属性,则直接渲染html -->
|
||||||
|
<template #cell="{ record }" v-if="column.isHyperText">
|
||||||
|
<div v-html="record[column.dataIndex]"></div>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column v-bind="column" v-else ellipsis tooltip>
|
||||||
|
<template #cell="{ record }">
|
||||||
|
{{ showType(record) }}
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<!-- 上级节点列 -->
|
||||||
|
<a-table-column title="对应被测件" align="center" :width="150" fixed="right">
|
||||||
|
<template #cell="{ record, column, rowIndex }">
|
||||||
|
<Trigger :dutInfo="record.dut" @refresh="fetchData()" />
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<!-- 操作列 -->
|
||||||
|
<a-table-column title="操作" align="center" :width="100" fixed="right">
|
||||||
|
<template #cell="{ record }">
|
||||||
|
<a-scrollbar type="track" style="overflow: auto">
|
||||||
|
<a-space size="mini">
|
||||||
|
<a-link @click="(formRef as any).open(record)">
|
||||||
|
修改
|
||||||
|
<template #icon>
|
||||||
|
<icon-edit />
|
||||||
|
</template>
|
||||||
|
</a-link>
|
||||||
|
</a-space>
|
||||||
|
</a-scrollbar>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
<!-- 设计需求-表单页面 -->
|
||||||
|
<Form ref="formRef" @refresh="fetchData()"></Form>
|
||||||
|
<!-- 表格设置 -->
|
||||||
|
<my-setting ref="settingRef" @onChangeColumnHide="changeColumn"></my-setting>
|
||||||
|
<!-- 批量替换组件 -->
|
||||||
|
<replace-modal
|
||||||
|
ref="replaceModal"
|
||||||
|
:selectRows="selecteds"
|
||||||
|
:api="designApi.replace"
|
||||||
|
:columns="columns"
|
||||||
|
key="modal-design"
|
||||||
|
popup-key="design"
|
||||||
|
@replaceSuccess="replaceSuccessHandle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { provide, ref } from "vue"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
import designApi from "@/api/project/designDemand"
|
||||||
|
import useShowType from "@/views/project/opeSets/components/DesignTable/useShowType"
|
||||||
|
import useFetchData from "@/views/project/opeSets/hooks/useFetchData"
|
||||||
|
import Form from "./form.vue" // 表单组件
|
||||||
|
import Trigger from "./Trigger.vue" // 查看上级节点的触发器组件\
|
||||||
|
// 表格用户设置相关
|
||||||
|
import useSettings from "@/views/project/opeSets/components/DesignTable/useSettings"
|
||||||
|
import MySetting from "@/views/project/opeSets/components/TableCommonComponent/Setting.vue"
|
||||||
|
import useDelete from "@/views/project/opeSets/components/DesignTable/useDelete"
|
||||||
|
// 批量替换弹窗组件
|
||||||
|
import ReplaceModal from "@/views/project/opeSets/components/DesignTable/ReplaceModal.vue"
|
||||||
|
import Search from "@/views/project/opeSets/components/DesignTable/Search.vue"
|
||||||
|
import type { ISearchForm } from "./types"
|
||||||
|
|
||||||
|
// 1.数据columns相关
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: "名称",
|
||||||
|
dataIndex: "name",
|
||||||
|
align: "left",
|
||||||
|
width: 120,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: true,
|
||||||
|
search: true,
|
||||||
|
formType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "标识",
|
||||||
|
dataIndex: "ident",
|
||||||
|
align: "center",
|
||||||
|
width: 100,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: true,
|
||||||
|
search: true,
|
||||||
|
formType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "章节号",
|
||||||
|
dataIndex: "chapter",
|
||||||
|
align: "center",
|
||||||
|
width: 80,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: true,
|
||||||
|
search: true,
|
||||||
|
formType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "类型",
|
||||||
|
dataIndex: "demandType",
|
||||||
|
align: "center",
|
||||||
|
width: 150,
|
||||||
|
hide: false,
|
||||||
|
ellipsis: true,
|
||||||
|
search: true,
|
||||||
|
formType: "select",
|
||||||
|
showType: (text: string) => {
|
||||||
|
return text
|
||||||
|
},
|
||||||
|
dict: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "需求描述",
|
||||||
|
dataIndex: "description",
|
||||||
|
align: "left",
|
||||||
|
hide: false,
|
||||||
|
ellipsis: false,
|
||||||
|
formType: "input",
|
||||||
|
// 设置内容单元格样式-注意作用与<td>
|
||||||
|
bodyCellClass: "hyperTextCell-table-chen",
|
||||||
|
isHyperText: true
|
||||||
|
}
|
||||||
|
])
|
||||||
|
provide("columns", columns)
|
||||||
|
|
||||||
|
// 2.获取demandType的名称
|
||||||
|
const showType = useShowType("demandType")
|
||||||
|
|
||||||
|
// 3.query查询和分页相关
|
||||||
|
const { tableData, isFetching, fetchData, total, pageChange, pageSizeChange, searchParams } = useFetchData(
|
||||||
|
designApi.getDesignDemandList,
|
||||||
|
columns
|
||||||
|
)
|
||||||
|
|
||||||
|
// 4.表单相关
|
||||||
|
const formRef = ref<InstanceType<typeof Form> | null>(null)
|
||||||
|
|
||||||
|
// 5.表格设置相关
|
||||||
|
const { options, clickSetting, changeColumn, settingRef } = useSettings()
|
||||||
|
|
||||||
|
// 6.行选择器相关-注意在fetchData时候没有清空(一定注意!!!)
|
||||||
|
const selecteds = ref([])
|
||||||
|
|
||||||
|
// 7.1.批量删除相关
|
||||||
|
const { deletesMultipleAction } = useDelete(designApi.delete, fetchData, selecteds)
|
||||||
|
|
||||||
|
// 7.2.批量替换相关
|
||||||
|
const replaceModal = ref<InstanceType<typeof ReplaceModal> | null>(null)
|
||||||
|
const handleOpenReplaceModal = () => {
|
||||||
|
replaceModal.value?.open()
|
||||||
|
}
|
||||||
|
const replaceSuccessHandle = async (count: number) => {
|
||||||
|
Message.success(`批量更新成功,尝试更新行数:${count}`)
|
||||||
|
// 批量更新后刷新表格(疑问?是否要清除行选择?)
|
||||||
|
await fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8.搜索组件相关-注意这里submit其实就是给维护的搜索参数传参
|
||||||
|
const searchVisible = ref(true)
|
||||||
|
const searchSubmit = (data: ISearchForm) => {
|
||||||
|
searchParams.value = { ...data }
|
||||||
|
fetchData(true)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
/* 下面让modal的蒙层不交互,让用户可以复制table的文字 */
|
||||||
|
div:deep(.arco-modal-container) {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
:deep(.arco-modal.arco-modal-draggable) {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search根组件
|
||||||
|
.search-container {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.hyperTextCell-table-chen {
|
||||||
|
.arco-table-td-content {
|
||||||
|
max-height: 15em;
|
||||||
|
overflow-y: auto;
|
||||||
|
line-height: 1.5em;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.arco-tabs-content-list {
|
||||||
|
height: 120%;
|
||||||
|
}
|
||||||
|
.arco-table-pagination {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// 设计需求搜索字段
|
||||||
|
export interface ISearchForm {
|
||||||
|
name: string
|
||||||
|
demandType: string
|
||||||
|
description: string
|
||||||
|
ident: string
|
||||||
|
chapter: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试项搜索字段
|
||||||
|
export interface ISearchFormDemand {
|
||||||
|
ident: string
|
||||||
|
name: string
|
||||||
|
testContent: string
|
||||||
|
testDesciption: string
|
||||||
|
testType: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用例搜索字段
|
||||||
|
export interface ISearchFormCase {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { Ref } from "vue"
|
||||||
|
import { Message } from "@arco-design/web-vue"
|
||||||
|
|
||||||
|
export default function useDelete(api: Function, resetApi: Function, selecteds: Ref<any[]>) {
|
||||||
|
const deletesMultipleAction = async () => {
|
||||||
|
if (selecteds.value && selecteds.value.length > 0) {
|
||||||
|
let data = {}
|
||||||
|
const response = await api(Object.assign({ ids: selecteds.value }, data))
|
||||||
|
response.success && Message.success(response.message || `删除成功!`)
|
||||||
|
selecteds.value = []
|
||||||
|
await resetApi()
|
||||||
|
} else {
|
||||||
|
Message.error("至少选择一条数据")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { deletesMultipleAction }
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { nextTick, provide, reactive, ref } from "vue"
|
||||||
|
import MySetting from "../TableCommonComponent/Setting.vue"
|
||||||
|
|
||||||
|
export default function useSettings() {
|
||||||
|
const settingRef = ref<InstanceType<typeof MySetting> | null>(null)
|
||||||
|
// 表格配置
|
||||||
|
const options = reactive({
|
||||||
|
bordered: {
|
||||||
|
wrapper: true,
|
||||||
|
cell: true
|
||||||
|
},
|
||||||
|
size: "small",
|
||||||
|
stripe: false
|
||||||
|
})
|
||||||
|
provide("options", options)
|
||||||
|
// 处理函数
|
||||||
|
const tableIsShow = ref(true)
|
||||||
|
const clickSetting = () => {
|
||||||
|
settingRef.value!.open()
|
||||||
|
}
|
||||||
|
const changeColumn = async () => {
|
||||||
|
tableIsShow.value = false
|
||||||
|
await nextTick(() => (tableIsShow.value = true))
|
||||||
|
}
|
||||||
|
return { options, clickSetting, changeColumn, settingRef }
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { ref } from "vue"
|
||||||
|
import commonApi from "@/api/common"
|
||||||
|
|
||||||
|
export default function useShowType(dictCode: string) {
|
||||||
|
const codeDict = ref<any>([])
|
||||||
|
;(function () {
|
||||||
|
commonApi.getDict(dictCode).then((res: any) => {
|
||||||
|
codeDict.value = res
|
||||||
|
})
|
||||||
|
})()
|
||||||
|
const showType = (record: any) => {
|
||||||
|
let len = codeDict.value.data.length
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
if (codeDict.value.data[i].key === record[dictCode]) {
|
||||||
|
let item = codeDict.value.data[i]
|
||||||
|
return item.title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return showType
|
||||||
|
}
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
<template>
|
||||||
|
<a-drawer :visible="visible" unmountOnClose :footer="false" width="55%" @cancel="onCancel">
|
||||||
|
<template #title>设置</template>
|
||||||
|
|
||||||
|
<a-space class="mt-3">
|
||||||
|
<span>表格大小:</span>
|
||||||
|
<a-radio-group type="button" v-model="options.size">
|
||||||
|
<a-radio value="mini">迷你</a-radio>
|
||||||
|
<a-radio value="small">小</a-radio>
|
||||||
|
<a-radio value="medium">中</a-radio>
|
||||||
|
<a-radio value="large">大</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
<span class="ml-3">表格边框:</span>
|
||||||
|
<a-radio-group type="button" v-model="bordered" @change="changeBordered">
|
||||||
|
<a-radio value="hide">不显示外边框</a-radio>
|
||||||
|
<a-radio value="show">全部显示</a-radio>
|
||||||
|
<a-radio value="row">不显示行</a-radio>
|
||||||
|
<a-radio value="column">不显示列</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
<a-checkbox v-model="options.stripe" class="ml-3">斑马纹</a-checkbox>
|
||||||
|
</a-space>
|
||||||
|
|
||||||
|
<a-table
|
||||||
|
:data="allowShowColumns"
|
||||||
|
:pagination="false"
|
||||||
|
:bordered="{ wrapper: true, cell: false }"
|
||||||
|
:draggable="{ type: 'handle', width: 40 }"
|
||||||
|
@change="onTableChange"
|
||||||
|
stripe
|
||||||
|
class="mt-3"
|
||||||
|
>
|
||||||
|
<template #columns>
|
||||||
|
<a-table-column title="列名称" data-index="title" align="center">
|
||||||
|
<template #cell="{ record }">{{ record.title }}</template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column title="宽度" data-index="width" align="center">
|
||||||
|
<template #cell="{ record }">
|
||||||
|
<a-input-number
|
||||||
|
v-if="!['__index', '__operation'].includes(record.dataIndex)"
|
||||||
|
style="width: 150px"
|
||||||
|
placeholder="列宽度"
|
||||||
|
v-model="record.width"
|
||||||
|
mode="button"
|
||||||
|
@change="changeColumn($event, 'width', record.dataIndex)"
|
||||||
|
/>
|
||||||
|
<span v-else> / </span>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column title="搜索隐藏" data-index="hide" align="center">
|
||||||
|
<template #cell="{ record }"
|
||||||
|
><a-checkbox v-model="record.search" @change="changeColumn($event, 'search', record.dataIndex)"
|
||||||
|
/></template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column title="表格隐藏" data-index="hide" align="center">
|
||||||
|
<template #cell="{ record }"
|
||||||
|
><a-checkbox v-model="record.hide" @change="changeColumn($event, 'hide', record.dataIndex)"
|
||||||
|
/></template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column title="固定" data-index="fixed" align="center">
|
||||||
|
<template #cell="{ record }">
|
||||||
|
<a-space v-if="!['__index', '__operation'].includes(record.dataIndex)">
|
||||||
|
<a-radio
|
||||||
|
v-model="record.fixed"
|
||||||
|
value=""
|
||||||
|
@change="changeColumn($event, 'fixed', record.dataIndex)"
|
||||||
|
>无</a-radio
|
||||||
|
>
|
||||||
|
<a-radio
|
||||||
|
v-model="record.fixed"
|
||||||
|
value="left"
|
||||||
|
@change="changeColumn($event, 'fixed', record.dataIndex)"
|
||||||
|
>左</a-radio
|
||||||
|
>
|
||||||
|
<a-radio
|
||||||
|
v-model="record.fixed"
|
||||||
|
value="right"
|
||||||
|
@change="changeColumn($event, 'fixed', record.dataIndex)"
|
||||||
|
>右</a-radio
|
||||||
|
>
|
||||||
|
</a-space>
|
||||||
|
<span v-else> / </span>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { inject, ref, toRef, watch } from "vue"
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
const bordered = ref("show")
|
||||||
|
const options = inject("options") as any
|
||||||
|
const columns = inject("columns") as any
|
||||||
|
const allowShowColumns = ref([])
|
||||||
|
|
||||||
|
// 设置列
|
||||||
|
const setShowColumns = () => {
|
||||||
|
allowShowColumns.value = columns.value.filter((item) => {
|
||||||
|
return !(item?.settingHide ?? false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 边框设置
|
||||||
|
const changeBordered = (v: string) => {
|
||||||
|
if (v === "hide") {
|
||||||
|
options.bordered = { wrapper: false, cell: false }
|
||||||
|
}
|
||||||
|
if (v === "show") {
|
||||||
|
options.bordered = { wrapper: true, cell: true }
|
||||||
|
}
|
||||||
|
if (v === "row") {
|
||||||
|
options.bordered = { wrapper: false, cell: true }
|
||||||
|
}
|
||||||
|
if (v === "column") {
|
||||||
|
options.bordered = { wrapper: true, cell: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onTableChange = (_data) => {
|
||||||
|
columns.value = _data
|
||||||
|
setShowColumns()
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
setShowColumns()
|
||||||
|
visible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(["onChangeSearchHide", "onChangeColumnHide"])
|
||||||
|
|
||||||
|
const changeColumn = (ev: string, type: any, name: any) => {
|
||||||
|
const column = columns.value.find((item: { dataIndex: any }) => item.dataIndex === name)
|
||||||
|
switch (type) {
|
||||||
|
case "hide":
|
||||||
|
emit("onChangeColumnHide")
|
||||||
|
break
|
||||||
|
case "search":
|
||||||
|
emit("onChangeSearchHide")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
54
cdTMP/src/views/project/opeSets/hooks/useFetchData.ts
Normal file
54
cdTMP/src/views/project/opeSets/hooks/useFetchData.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { onMounted, Ref, ref } from "vue"
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 该hook传入异步请求数据函数,返回isFetching和请求函数
|
||||||
|
* 该hook还处理分页数据和请求
|
||||||
|
*/
|
||||||
|
export default function useFetchData(fetchFn: Function, columns: Ref<any>) {
|
||||||
|
// 分页参数
|
||||||
|
const page = ref(1)
|
||||||
|
const pageSize = ref(10)
|
||||||
|
// 搜索参数
|
||||||
|
const searchParams = ref({})
|
||||||
|
for (const item of columns.value) {
|
||||||
|
searchParams.value[item.dataIndex] = ""
|
||||||
|
}
|
||||||
|
// 表格数据和isLoading数据
|
||||||
|
const route = useRoute()
|
||||||
|
const projectId = route.query.id
|
||||||
|
const round = route.query.key
|
||||||
|
const tableData = ref([]) // 表格数据
|
||||||
|
const total = ref(0)
|
||||||
|
const isFetching = ref(false)
|
||||||
|
const fetchData = async (isSearch: boolean = false) => {
|
||||||
|
if (isSearch) {
|
||||||
|
page.value = 1
|
||||||
|
}
|
||||||
|
isFetching.value = true
|
||||||
|
const res = await fetchFn({
|
||||||
|
projectId,
|
||||||
|
round,
|
||||||
|
page: page.value, // 不要忘记value
|
||||||
|
pageSize: pageSize.value, // 不要忘记value
|
||||||
|
...searchParams.value
|
||||||
|
})
|
||||||
|
tableData.value = res.data.items
|
||||||
|
total.value = res.data.pageInfo.total
|
||||||
|
isFetching.value = false
|
||||||
|
}
|
||||||
|
// 首次加载时触发一次
|
||||||
|
onMounted(() => {
|
||||||
|
fetchData()
|
||||||
|
})
|
||||||
|
// 定义a-table的分页改变函数
|
||||||
|
const pageChange = (current: number) => {
|
||||||
|
page.value = current
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
const pageSizeChange = (size: number) => {
|
||||||
|
pageSize.value = size
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
return { tableData, isFetching, fetchData, total, pageChange, pageSizeChange, searchParams }
|
||||||
|
}
|
||||||
40
cdTMP/src/views/project/opeSets/index.vue
Normal file
40
cdTMP/src/views/project/opeSets/index.vue
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<template>
|
||||||
|
<div class="ma-content-block lg:flex justify-between p-4">
|
||||||
|
<div class="lg:w-full w-full lg:ml-4 mt-5 lg:mt-0 h-full">
|
||||||
|
<!-- 1.标题:提示用户第几轮次 -->
|
||||||
|
<div class="heading-1">{{ title }}测试过程数据</div>
|
||||||
|
<!-- 2.容器:tab切换 -->
|
||||||
|
<a-tabs default-active-key="design" type="card-gutter" size="large" destroy-on-hide justify>
|
||||||
|
<a-tab-pane key="design" title="设计需求">
|
||||||
|
<ProTable type="design"></ProTable>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="demand" title="测试项">
|
||||||
|
<ProTable type="demand"></ProTable>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="case" title="测试用例">
|
||||||
|
<ProTable type="case"></ProTable>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
import tool from "@/utils/tool"
|
||||||
|
import ProTable from "./ProTable/index.vue"
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// 1.标题
|
||||||
|
const title: string = tool.chnRoundNameArray[+route.query.key!]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.heading-1 {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -9,10 +9,13 @@ export default function (crudOrFormRef: any) {
|
|||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
// 计算注释率计算crud/form的数据,判断
|
// 计算注释率计算crud/form的数据,判断
|
||||||
const calcPercent = () => {
|
const calcPercent = () => {
|
||||||
|
if (crudOrFormRef) {
|
||||||
const formData = crudOrFormRef.value.getFormData()
|
const formData = crudOrFormRef.value.getFormData()
|
||||||
const { total_lines, comment_lines } = formData
|
const { total_lines, comment_lines } = formData
|
||||||
formData.comment_percent = `${(comment_lines / total_lines).toFixed(2).toString()}%`
|
formData.comment_percent = `${(comment_lines / total_lines).toFixed(2).toString()}%`
|
||||||
}
|
}
|
||||||
|
return "无法计算注释率"
|
||||||
|
}
|
||||||
const crudColumns = ref([
|
const crudColumns = ref([
|
||||||
{
|
{
|
||||||
title: "ID",
|
title: "ID",
|
||||||
@@ -109,6 +112,7 @@ export default function (crudOrFormRef: any) {
|
|||||||
search: true,
|
search: true,
|
||||||
commonRules: [{ required: true, message: "单位必选" }],
|
commonRules: [{ required: true, message: "单位必选" }],
|
||||||
formType: "select",
|
formType: "select",
|
||||||
|
span: 3,
|
||||||
dict: { url: "system/contact/index", props: { label: "name", value: "name" }, translation: true }
|
dict: { url: "system/contact/index", props: { label: "name", value: "name" }, translation: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export default function (crudOrFormRef: any, problemFormRef?: any) {
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: "center",
|
align: "center",
|
||||||
addDisabled: true,
|
addDisabled: true,
|
||||||
|
disabled: true,
|
||||||
addDefaultValue: "用例标识自动生成,结构为YL_IO_XXXX_001",
|
addDefaultValue: "用例标识自动生成,结构为YL_IO_XXXX_001",
|
||||||
editDefaultValue: "用例标识自动生成,结构为YL_IO_XXXX_001",
|
editDefaultValue: "用例标识自动生成,结构为YL_IO_XXXX_001",
|
||||||
editDisabled: true,
|
editDisabled: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user