新增汇总页-问题单详情
This commit is contained in:
12
cdTMP/package-lock.json
generated
12
cdTMP/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "testplant",
|
||||
"version": "0.0.6",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "testplant",
|
||||
"version": "0.0.6",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@arco-design/color": "^0.4.0",
|
||||
"@arco-design/web-vue": "^2.57.0",
|
||||
@@ -32,7 +32,7 @@
|
||||
"vue": "^3.5.26",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-color-kit": "^1.0.6",
|
||||
"vue-data-ui": "^3.9.6",
|
||||
"vue-data-ui": "^3.9.12",
|
||||
"vue-router": "^4.6.4",
|
||||
"vuedraggable": "^2.24.3"
|
||||
},
|
||||
@@ -5469,9 +5469,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vue-data-ui": {
|
||||
"version": "3.9.6",
|
||||
"resolved": "https://registry.npmmirror.com/vue-data-ui/-/vue-data-ui-3.9.6.tgz",
|
||||
"integrity": "sha512-XpIqONAc6xYAWvjiR8snVTIjETbZUdxw2gV2vrHnwA71yXMS3Mso2MO+aE9mNhsUI7LThzOPtjylA+vniKANzQ==",
|
||||
"version": "3.9.12",
|
||||
"resolved": "https://registry.npmmirror.com/vue-data-ui/-/vue-data-ui-3.9.12.tgz",
|
||||
"integrity": "sha512-0gNNA9DJw9q9/o4KrK+tesZHHtUxMB6x1JhiGhILU6VS3J/kb+pXC/BQaOqmjK512xzDyE05SGCR5UkHTSNPpQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"jspdf": "^3.0.1",
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"vue": "^3.5.26",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-color-kit": "^1.0.6",
|
||||
"vue-data-ui": "^3.9.6",
|
||||
"vue-data-ui": "^3.9.12",
|
||||
"vue-router": "^4.6.4",
|
||||
"vuedraggable": "^2.24.3"
|
||||
},
|
||||
|
||||
@@ -136,7 +136,7 @@ export default {
|
||||
* 批量替换事件
|
||||
* @returns
|
||||
*/
|
||||
exetimeReplace(data = { selectRows: [], exetime: "" }) {
|
||||
exetimeReplace(data = { selectRows: [], exetime: [] }) {
|
||||
return request({
|
||||
url: "/project/case/timeReplace/",
|
||||
method: "post",
|
||||
|
||||
@@ -120,5 +120,16 @@ export default {
|
||||
method: "get",
|
||||
params
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 复制到当前dut下面,CRUD中操作列
|
||||
* @returns
|
||||
*/
|
||||
copy_current(params = {}) {
|
||||
return request({
|
||||
url: "/project/copy_current",
|
||||
method: "get",
|
||||
params
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,15 +36,15 @@ export default function (crudRef: Ref<InstanceType<typeof MaCrud>>) {
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} > ${(td[round_key] as any).title} > ${(td[round_key] as any).children[dut_key].title} >设计需求[${record.name}]-`
|
||||
return true
|
||||
},
|
||||
afterAdd: (res) => {
|
||||
afterAdd: (res: any) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateDesignDemandTreeData(res.data, id)
|
||||
},
|
||||
afterEdit: (res) => {
|
||||
afterEdit: (res: any) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateDesignDemandTreeData(res.data, id)
|
||||
},
|
||||
afterDelete: (res, record) => {
|
||||
afterDelete: (_: any, record: any) => {
|
||||
let id = projectId.value
|
||||
if (!record) {
|
||||
record = { key: route.query.key + "-X" }
|
||||
@@ -62,12 +62,12 @@ export default function (crudRef: Ref<InstanceType<typeof MaCrud>>) {
|
||||
rowSelection: { showCheckedAll: true },
|
||||
searchColNumber: 4,
|
||||
tablePagination: false,
|
||||
operationColumnWidth: 250,
|
||||
operationColumnWidth: 300,
|
||||
operationColumn: true,
|
||||
operationColumnAlign: "center",
|
||||
formOption: {
|
||||
width: 1200
|
||||
},
|
||||
}
|
||||
})
|
||||
return crudOptions
|
||||
}
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
<!-- 字段的前缀后缀的插槽 -->
|
||||
<!-- 版本字段的插槽 -->
|
||||
<template #inputPrepend-ident> SJ-XX- </template>
|
||||
<!-- 操作列前置插槽 -->
|
||||
<template #operationBeforeExtend="{ record }">
|
||||
<a-link @click="handleCopyCurrentNode($event, record)" :loading="copyLoading"><icon-copy />复制当前</a-link>
|
||||
</template>
|
||||
</ma-crud>
|
||||
</div>
|
||||
<file-input-modal ref="fileInputRef" @enterFinish="crudRef.refresh()"></file-input-modal>
|
||||
@@ -59,6 +63,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import useCrudOptions from "@/views/project/dut/hooks/useCrudOptions"
|
||||
import useColumns from "./hooks/useColumns"
|
||||
import { Message } from "@arco-design/web-vue"
|
||||
@@ -75,6 +80,7 @@ import BatchCaseCreate from "@/views/project/components/BatchCaseCreate/index.vu
|
||||
const route = useRoute()
|
||||
const crudRef = ref()
|
||||
const projectId = ref(route.query.id)
|
||||
const treeDataStore = useTreeDataStore()
|
||||
|
||||
// 5月28日新增功能:替换
|
||||
const replaceModal = ref()
|
||||
@@ -143,6 +149,23 @@ const handleBatchCaseCreate = () => {
|
||||
batchCreateCaseRef.value.open({})
|
||||
}
|
||||
|
||||
// 复制设计需求到当前dut
|
||||
const copyLoading = ref(false)
|
||||
const handleCopyCurrentNode = async (_, record) => {
|
||||
copyLoading.value = true
|
||||
try {
|
||||
await designApi.copy_current({ dut_id: record.dut.id, design_id: record.id })
|
||||
// 复制成功给提示
|
||||
Message.success("复制成功!")
|
||||
refreshCrudTable()
|
||||
treeDataStore.updateDesignDemandTreeData({ key: record.key }, projectId.value)
|
||||
} catch (e) {
|
||||
console.log("复制失败,后台打印错误:", e)
|
||||
} finally {
|
||||
copyLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const refreshCrudTable = () => {
|
||||
crudRef.value.refresh()
|
||||
}
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
import DesignTable from "../components/DesignTable/index.vue"
|
||||
import DemandTable from "../components/DemandTable/index.vue"
|
||||
import CaseTable from "../components/CaseTable/index.vue"
|
||||
import ProblemTable from "../components/ProblemTable/index.vue"
|
||||
|
||||
/* 导入columns看能不能行 */
|
||||
// useColumns使用对应关系
|
||||
const mapColumn = {
|
||||
design: DesignTable,
|
||||
demand: DemandTable,
|
||||
case: CaseTable
|
||||
case: CaseTable,
|
||||
problem: ProblemTable
|
||||
}
|
||||
// props
|
||||
const { type } = defineProps<{
|
||||
@@ -25,7 +27,7 @@ const { type } = defineProps<{
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.pro-table-container{
|
||||
.pro-table-container {
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
<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"
|
||||
>
|
||||
<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="exetime" label="执行时间">
|
||||
<a-date-picker v-model="exetime" style="width: 200px" />
|
||||
<a-range-picker v-model="exetime" style="width: 400px" :shortcuts="shortcuts" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
@@ -26,10 +18,12 @@
|
||||
import { ref } from "vue"
|
||||
import { Message } from "@arco-design/web-vue"
|
||||
import caseApi from "@/api/project/case"
|
||||
import { isEmpty } from "lodash-es"
|
||||
import dayjs from "dayjs"
|
||||
|
||||
const visible = ref(false)
|
||||
const formData = ref({})
|
||||
const exetime = ref("")
|
||||
const exetime = ref<string[]>([])
|
||||
const getSelectedsFunc = ref<any>(() => [])
|
||||
|
||||
// props
|
||||
@@ -41,7 +35,7 @@ const emit = defineEmits(["modifySuccess"])
|
||||
// 2.异步执行替换操作,返回boolean-true则关闭弹窗
|
||||
const submitReplace = async () => {
|
||||
// 不再非受控验证,手动验证
|
||||
if (exetime.value === "") {
|
||||
if (isEmpty(exetime.value)) {
|
||||
Message.error("请选择时间后,进行替换操作")
|
||||
return false
|
||||
}
|
||||
@@ -49,22 +43,42 @@ const submitReplace = async () => {
|
||||
if (selecteds.length && selecteds.length > 0) {
|
||||
// 判断是否选择了行
|
||||
// 请求后台执行
|
||||
try {
|
||||
await caseApi.exetimeReplace({
|
||||
selectRows: selecteds,
|
||||
exetime: exetime.value
|
||||
exetime: exetime.value as any
|
||||
})
|
||||
emit("modifySuccess")
|
||||
Message.success("批量替换成功...")
|
||||
return true
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
Message.error("请在表格中选择行...")
|
||||
return false
|
||||
}
|
||||
|
||||
// 给时间范围选择器的快捷选择数组
|
||||
const shortcuts = [
|
||||
{
|
||||
label: "后六天",
|
||||
value: () => [dayjs(), dayjs().add(6, "day")]
|
||||
},
|
||||
{
|
||||
label: "前六天",
|
||||
value: () => [dayjs(), dayjs().subtract(6, "day")]
|
||||
},
|
||||
{
|
||||
label: "前后各一周",
|
||||
value: () => [dayjs().subtract(7, "day"), dayjs().add(7, "day")]
|
||||
}
|
||||
]
|
||||
|
||||
// 其他:打开modal
|
||||
const open = (getFunc: (() => number[]) | undefined) => {
|
||||
if (getFunc) getSelectedsFunc.value = getFunc
|
||||
exetime.value = ""
|
||||
exetime.value = []
|
||||
visible.value = true
|
||||
}
|
||||
defineExpose({ open })
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
<search v-show="searchVisible" @submit="searchSubmit" />
|
||||
<div class="lg:flex justify-between mb-2">
|
||||
<a-space>
|
||||
<a-popconfirm
|
||||
content="确定要删除数据吗? 这会删除全部下级数据!"
|
||||
position="bottom"
|
||||
@ok="deletesMultipleAction"
|
||||
>
|
||||
<a-popconfirm content="确定要删除数据吗? 这会删除全部下级数据!" position="bottom" @ok="deletesMultipleAction">
|
||||
<a-button type="primary" status="danger">
|
||||
批量删除
|
||||
<template #icon><icon-delete /></template>
|
||||
@@ -164,7 +160,8 @@ const columns = ref([
|
||||
hide: false,
|
||||
ellipsis: true,
|
||||
search: true,
|
||||
formType: "input"
|
||||
formType: "input",
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "名称",
|
||||
@@ -174,7 +171,8 @@ const columns = ref([
|
||||
hide: false,
|
||||
ellipsis: true,
|
||||
search: true,
|
||||
formType: "input"
|
||||
formType: "input",
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "用例综述",
|
||||
@@ -186,7 +184,8 @@ const columns = ref([
|
||||
search: false, // 不搜索
|
||||
formType: "input", // 搜索输入框形式
|
||||
isHyperText: false,
|
||||
bodyCellClass: "hyperTextCell-table-chen"
|
||||
bodyCellClass: "hyperTextCell-table-chen",
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
// 这是单独处理的字段,只声明Search组件相关属性
|
||||
@@ -198,16 +197,14 @@ const columns = ref([
|
||||
ellipsis: false,
|
||||
search: false, // 要搜索
|
||||
formType: "input", // 搜索输入框形式
|
||||
bodyCellClass: "hyperTextCell-table-chen"
|
||||
bodyCellClass: "hyperTextCell-table-chen",
|
||||
fixed: ""
|
||||
}
|
||||
])
|
||||
provide("columns", columns)
|
||||
|
||||
// 3.query查询和分页相关
|
||||
const { tableData, isFetching, fetchData, total, pageChange, pageSizeChange, searchParams } = useFetchData(
|
||||
caseApi.getCaseList,
|
||||
columns
|
||||
)
|
||||
const { tableData, isFetching, fetchData, total, pageChange, pageSizeChange, searchParams } = useFetchData(caseApi.getCaseList, columns)
|
||||
|
||||
// 4.表单相关
|
||||
const formRef = ref<InstanceType<typeof Form> | null>(null)
|
||||
|
||||
@@ -163,7 +163,8 @@ const columns = ref([
|
||||
hide: false,
|
||||
ellipsis: true,
|
||||
search: true,
|
||||
formType: "input"
|
||||
formType: "input",
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "名称",
|
||||
@@ -173,7 +174,8 @@ const columns = ref([
|
||||
hide: false,
|
||||
ellipsis: true,
|
||||
search: true,
|
||||
formType: "input"
|
||||
formType: "input",
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "优先级",
|
||||
@@ -188,7 +190,8 @@ const columns = ref([
|
||||
// 只是指明a-table-column渲染v-if
|
||||
showType: (text: string) => {
|
||||
return text
|
||||
}
|
||||
},
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "测试类型",
|
||||
@@ -202,7 +205,8 @@ const columns = ref([
|
||||
dict: true,
|
||||
showType: (text: string) => {
|
||||
return text
|
||||
}
|
||||
},
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "测项描述",
|
||||
@@ -214,7 +218,8 @@ const columns = ref([
|
||||
search: false, // 不搜索
|
||||
formType: "input", // 搜索输入框形式
|
||||
isHyperText: false,
|
||||
bodyCellClass: "hyperTextCell-table-chen"
|
||||
bodyCellClass: "hyperTextCell-table-chen",
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
// 这是单独处理的字段,只声明Search组件相关属性
|
||||
@@ -226,7 +231,8 @@ const columns = ref([
|
||||
ellipsis: false,
|
||||
search: false, // 要搜索
|
||||
formType: "input", // 搜索输入框形式
|
||||
bodyCellClass: "hyperTextCell-table-chen"
|
||||
bodyCellClass: "hyperTextCell-table-chen",
|
||||
fixed: ""
|
||||
}
|
||||
])
|
||||
provide("columns", columns)
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
<search v-show="searchVisible" @submit="searchSubmit" />
|
||||
<div class="lg:flex justify-between mb-2">
|
||||
<a-space>
|
||||
<a-popconfirm
|
||||
content="确定要删除数据吗? 这会删除全部下级数据!"
|
||||
position="bottom"
|
||||
@ok="deletesMultipleAction"
|
||||
>
|
||||
<a-popconfirm content="确定要删除数据吗? 这会删除全部下级数据!" position="bottom" @ok="deletesMultipleAction">
|
||||
<a-button type="primary" status="danger">
|
||||
批量删除
|
||||
<template #icon><icon-delete /></template>
|
||||
@@ -140,7 +136,8 @@ const columns = ref([
|
||||
hide: false,
|
||||
ellipsis: true,
|
||||
search: true,
|
||||
formType: "input"
|
||||
formType: "input",
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "标识",
|
||||
@@ -150,7 +147,8 @@ const columns = ref([
|
||||
hide: false,
|
||||
ellipsis: true,
|
||||
search: true,
|
||||
formType: "input"
|
||||
formType: "input",
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "章节号",
|
||||
@@ -160,7 +158,8 @@ const columns = ref([
|
||||
hide: false,
|
||||
ellipsis: true,
|
||||
search: true,
|
||||
formType: "input"
|
||||
formType: "input",
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "类型",
|
||||
@@ -174,7 +173,8 @@ const columns = ref([
|
||||
showType: (text: string) => {
|
||||
return text
|
||||
},
|
||||
dict: true
|
||||
dict: true,
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "需求描述",
|
||||
@@ -185,7 +185,8 @@ const columns = ref([
|
||||
formType: "input",
|
||||
// 设置内容单元格样式-注意作用与<td>
|
||||
bodyCellClass: "hyperTextCell-table-chen",
|
||||
isHyperText: true
|
||||
isHyperText: true,
|
||||
fixed: ""
|
||||
}
|
||||
])
|
||||
provide("columns", columns)
|
||||
@@ -194,10 +195,7 @@ provide("columns", columns)
|
||||
const showType = useShowType("demandType")
|
||||
|
||||
// 3.query查询和分页相关
|
||||
const { tableData, isFetching, fetchData, total, pageChange, pageSizeChange, searchParams } = useFetchData(
|
||||
designApi.getDesignDemandList,
|
||||
columns
|
||||
)
|
||||
const { tableData, isFetching, fetchData, total, pageChange, pageSizeChange, searchParams } = useFetchData(designApi.getDesignDemandList, columns)
|
||||
|
||||
// 4.表单相关
|
||||
const formRef = ref<InstanceType<typeof Form> | null>(null)
|
||||
|
||||
@@ -20,3 +20,8 @@ export interface ISearchFormDemand {
|
||||
export interface ISearchFormCase {
|
||||
|
||||
}
|
||||
|
||||
// 问题单搜索字段
|
||||
export interface ISearchFormProblem {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div class="problem-form-container">
|
||||
<a-modal
|
||||
width="60%"
|
||||
draggable
|
||||
unmount-on-close
|
||||
ok-text="确认修改"
|
||||
cancel-text="关闭"
|
||||
v-model:visible="visible"
|
||||
title="修改问题单"
|
||||
:on-before-ok="handleSubmit"
|
||||
>
|
||||
<ma-form v-model="formData" :columns="columns" :options="options" ref="formRef">
|
||||
<template #form-ident> PT_{{ route.query.ident }}_{{ formData["ident"] }} </template>
|
||||
</ma-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import useFormColumns from "./formHooks/useFormColumns"
|
||||
import { ref } from "vue"
|
||||
import MaForm from "@/components/ma-form/index.vue"
|
||||
import problemApi from "@/api/project/problem"
|
||||
import { useRoute } from "vue-router"
|
||||
import { Message } from "@arco-design/web-vue"
|
||||
|
||||
const visible = ref(false)
|
||||
const formRef = ref<InstanceType<typeof MaForm> | null>(null)
|
||||
const route = useRoute()
|
||||
|
||||
// form数据
|
||||
const project_id = route.query.id
|
||||
const formData = ref<any>({})
|
||||
|
||||
const emit = defineEmits(["updateProblem"])
|
||||
|
||||
// modal提交按钮
|
||||
const handleSubmit = async () => {
|
||||
const isValidated = await formRef.value!.validateForm()
|
||||
if (isValidated) {
|
||||
return false
|
||||
}
|
||||
try {
|
||||
await problemApi.update(formData.value.id, { project_id, ...formData.value })
|
||||
emit("updateProblem")
|
||||
Message.success("修改成功")
|
||||
formData.value = {} // 清除已有数据,防止卡顿
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// options
|
||||
const options = ref({
|
||||
showButtons: false,
|
||||
labelAlign: "center"
|
||||
})
|
||||
|
||||
// columns
|
||||
const { columns } = useFormColumns()
|
||||
|
||||
const open = (record: any) => {
|
||||
visible.value = true
|
||||
formData.value = record
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,347 @@
|
||||
import { useRoute } from "vue-router"
|
||||
import { useUserStore } from "@/store"
|
||||
|
||||
export default function () {
|
||||
const route = useRoute()
|
||||
const userStore = useUserStore()
|
||||
const columns = [
|
||||
{
|
||||
title: "id",
|
||||
dataIndex: "id",
|
||||
display: false
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
customClass: ["mt-0"],
|
||||
cols: [
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "名称",
|
||||
align: "left",
|
||||
search: true,
|
||||
dataIndex: "name",
|
||||
rules: [{ required: true, message: "名称是必填" }],
|
||||
validateTrigger: "blur-sm"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "问题标识",
|
||||
align: "center",
|
||||
width: 140,
|
||||
search: true,
|
||||
disabled: true,
|
||||
dataIndex: "ident",
|
||||
validateTrigger: "blur-sm"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
customClass: ["ml-4"],
|
||||
cols: [
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "缺陷状态",
|
||||
align: "center",
|
||||
width: 80,
|
||||
search: true,
|
||||
dataIndex: "status",
|
||||
formType: "radio",
|
||||
rules: [{ required: true, message: "缺陷状态是必填" }],
|
||||
dict: {
|
||||
name: "problemStatu",
|
||||
translation: true,
|
||||
props: { label: "title", value: "key" },
|
||||
tagColors: { 1: "green", 2: "blue", 3: "#FF7D00", 4: "red" }
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "闭环方式",
|
||||
align: "center",
|
||||
width: 200,
|
||||
dataIndex: "closeMethod",
|
||||
search: true,
|
||||
formType: "checkbox",
|
||||
dict: {
|
||||
name: "closeMethod",
|
||||
translation: true,
|
||||
props: { label: "title", value: "key" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
customClass: ["ml-4"],
|
||||
cols: [
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "缺陷等级",
|
||||
align: "center",
|
||||
width: 80,
|
||||
dataIndex: "grade",
|
||||
search: true,
|
||||
formType: "radio",
|
||||
rules: [{ required: true, message: "缺陷等级必填" }],
|
||||
dict: {
|
||||
name: "problemGrade",
|
||||
translation: true,
|
||||
props: { label: "title", value: "key" }
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "缺陷类型",
|
||||
align: "center",
|
||||
width: 80,
|
||||
dataIndex: "type",
|
||||
search: true,
|
||||
formType: "radio",
|
||||
rules: [{ required: true, message: "缺陷类型必选" }],
|
||||
dict: {
|
||||
name: "problemType",
|
||||
translation: true,
|
||||
props: { label: "title", value: "key" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "divider"
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{
|
||||
span: 24,
|
||||
formList: [
|
||||
{
|
||||
title: "问题描述",
|
||||
hide: true,
|
||||
search: true,
|
||||
align: "center",
|
||||
dataIndex: "operation",
|
||||
formType: "editor"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{
|
||||
span: 24,
|
||||
formList: [
|
||||
{
|
||||
title: "问题影响",
|
||||
hide: true,
|
||||
align: "center",
|
||||
dataIndex: "result",
|
||||
formType: "textarea"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "divider"
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{
|
||||
span: 24,
|
||||
formList: [
|
||||
{
|
||||
title: "原因分析",
|
||||
hide: true,
|
||||
align: "center",
|
||||
dataIndex: "analysis",
|
||||
formType: "textarea"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{
|
||||
span: 24,
|
||||
formList: [
|
||||
{
|
||||
title: "影响域分析",
|
||||
hide: true,
|
||||
align: "center",
|
||||
dataIndex: "effect_scope",
|
||||
formType: "textarea"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{
|
||||
span: 24,
|
||||
formList: [
|
||||
{
|
||||
title: "改正措施",
|
||||
hide: true,
|
||||
align: "center",
|
||||
dataIndex: "solve",
|
||||
formType: "textarea"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "divider"
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{
|
||||
span: 24,
|
||||
formList: [
|
||||
{
|
||||
title: "回归结果",
|
||||
hide: true,
|
||||
align: "center",
|
||||
dataIndex: "verify_result",
|
||||
formType: "editor"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "divider",
|
||||
title: "人员信息"
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "测试人员",
|
||||
dataIndex: "postPerson",
|
||||
search: true,
|
||||
align: "center",
|
||||
formType: "select",
|
||||
rules: [{ required: true, message: "测试人员必填" }],
|
||||
dict: {
|
||||
url: "system/user/list",
|
||||
params: { project_id: route.query.id },
|
||||
translation: true,
|
||||
props: { label: "name", value: "name" }
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "测试日期",
|
||||
hide: true,
|
||||
dataIndex: "postDate",
|
||||
formType: "date"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "开发人员",
|
||||
hide: true,
|
||||
dataIndex: "designerPerson",
|
||||
formType: "input"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "开发方日期",
|
||||
hide: true,
|
||||
dataIndex: "designDate",
|
||||
formType: "date"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "回归人员",
|
||||
hide: true,
|
||||
dataIndex: "verifyPerson",
|
||||
formType: "select",
|
||||
dict: {
|
||||
url: "system/user/list",
|
||||
params: { project_id: route.query.id },
|
||||
translation: true,
|
||||
props: { label: "name", value: "name" }
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
span: 12,
|
||||
formList: [
|
||||
{
|
||||
title: "回归日期",
|
||||
hide: true,
|
||||
dataIndex: "verifyDate",
|
||||
formType: "date"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
return { columns }
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import { ref } from "vue"
|
||||
|
||||
export default function () {
|
||||
const columns = ref([
|
||||
{
|
||||
title: "名称",
|
||||
dataIndex: "name",
|
||||
slotName: "name",
|
||||
align: "left",
|
||||
hide: false,
|
||||
width: 250,
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "问题标识",
|
||||
dataIndex: "ident",
|
||||
slotName: "ident",
|
||||
align: "center",
|
||||
hide: false,
|
||||
width: 150,
|
||||
fixed: ""
|
||||
},
|
||||
{
|
||||
title: "缺陷状态",
|
||||
dataIndex: "problemStatu",
|
||||
slotName: "problemStatu",
|
||||
align: "center",
|
||||
hide: false,
|
||||
width: 100,
|
||||
fixed: "",
|
||||
formType: "select",
|
||||
dict: true
|
||||
},
|
||||
{
|
||||
title: "缺陷等级",
|
||||
dataIndex: "problemGrade",
|
||||
slotName: "problemGrade",
|
||||
align: "center",
|
||||
hide: false,
|
||||
width: 100,
|
||||
fixed: "",
|
||||
formType: "select",
|
||||
dict: true
|
||||
},
|
||||
{
|
||||
title: "问题描述",
|
||||
dataIndex: "operation",
|
||||
slotName: "operation",
|
||||
align: "left",
|
||||
hide: false,
|
||||
isHyperText: true,
|
||||
fixed: ""
|
||||
}
|
||||
])
|
||||
|
||||
return { columns }
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { computed, ref } from "vue"
|
||||
import dictApi from "@/api/system/dict"
|
||||
import { Message } from "@arco-design/web-vue"
|
||||
|
||||
export default function () {
|
||||
const loading = ref(false)
|
||||
const originOption = ref([])
|
||||
const gradeOptions = computed(() => {
|
||||
return Object.fromEntries(originOption.value.map(({ title, key }) => [key, title]))
|
||||
})
|
||||
// 请求字典中测试手段数据
|
||||
const fetchDictData = async () => {
|
||||
try {
|
||||
const res = await dictApi.getDictByCode({ code: "problemGrade" })
|
||||
originOption.value = res.data
|
||||
loading.value = true
|
||||
} catch (e) {
|
||||
Message.error("获取测试手段选项失败,请关闭后重新打开!")
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
// 一个工具函数
|
||||
const changeGradeColor = (status: "1" | "2" | "3" | "4") => {
|
||||
const colorDict = {
|
||||
"1": "blue",
|
||||
"2": "orange",
|
||||
"3": "green",
|
||||
"4": "red"
|
||||
}
|
||||
return colorDict[status]
|
||||
}
|
||||
fetchDictData()
|
||||
return { fetchDictData, loading, gradeOptions, changeGradeColor }
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { computed, ref } from "vue"
|
||||
import dictApi from "@/api/system/dict"
|
||||
import { Message } from "@arco-design/web-vue"
|
||||
|
||||
export default function () {
|
||||
const loading = ref(false)
|
||||
const originOption = ref([])
|
||||
const problemStatus = computed(() => {
|
||||
return Object.fromEntries(originOption.value.map(({ title, key }) => [key, title]))
|
||||
})
|
||||
|
||||
// 请求字典中测试手段数据
|
||||
const fetchDictData = async () => {
|
||||
try {
|
||||
const res = await dictApi.getDictByCode({ code: "problemStatu" })
|
||||
originOption.value = res.data
|
||||
loading.value = true
|
||||
} catch (e) {
|
||||
Message.error("获取测试手段选项失败,请关闭后重新打开!")
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
// 一个工具函数
|
||||
const changeColor = (status: "1" | "2" | "3" | "4") => {
|
||||
const colorDict = {
|
||||
"1": "green",
|
||||
"2": "red",
|
||||
"3": "magenta",
|
||||
"4": "arcoblue"
|
||||
}
|
||||
return colorDict[status]
|
||||
}
|
||||
|
||||
// 在组件挂载请求dict
|
||||
fetchDictData()
|
||||
|
||||
return { fetchDictData, loading, problemStatus, changeColor }
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<div class="problem-table-container">
|
||||
<search v-show="searchVisible" @submit="searchSubmit" />
|
||||
<div class="lg:flex justify-between mb-2">
|
||||
<a-space> </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-problem"
|
||||
v-bind="options"
|
||||
hoverable
|
||||
column-resizable
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:loading="isFetching || problemStatusLoading || problemGradeLoading"
|
||||
:data="tableData"
|
||||
:scroll="{ x: '100%' }"
|
||||
: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.dataIndex === 'operation'">
|
||||
<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 tooltip>
|
||||
<template #cell="{ record }">
|
||||
<template v-if="column.dataIndex === 'ident'"> PT_{{ route.query.ident }}_{{ record.ident }} </template>
|
||||
<template v-else-if="column.dataIndex === 'problemStatu'">
|
||||
<a-tag :color="changeColor(record.status)">
|
||||
{{ problemStatus[record.status] }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'problemGrade'">
|
||||
<a-tag :color="changeGradeColor(record.grade)">
|
||||
{{ gradeOptions[record.grade] }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ record[column.dataIndex] }}
|
||||
</template>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</template>
|
||||
<!-- 所属用例列 -->
|
||||
<a-table-column title="所属用例" align="center" :width="110" fixed="right">
|
||||
<template #cell="{ record }">
|
||||
<a-tag v-if="record.hang" color="red">无关联用例</a-tag>
|
||||
<a-button v-else color="green" type="primary" @click="seeRelatedCases(record)">
|
||||
<icon-eye />
|
||||
</a-button>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<!-- 操作列 -->
|
||||
<a-table-column title="操作" align="center" :width="120" fixed="right">
|
||||
<template #cell="{ record }">
|
||||
<a-link @click="handleOpenProblemModify(record)">
|
||||
修改
|
||||
<template #icon>
|
||||
<icon-edit />
|
||||
</template>
|
||||
</a-link>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
<!-- 问题单表单页面 -->
|
||||
<ProblemForm ref="problemRef" @updateProblem="refresh()" />
|
||||
<!-- 表格设置 -->
|
||||
<my-setting ref="settingRef" @onChangeColumnHide="changeColumn"></my-setting>
|
||||
<case-modal ref="caseModalRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { provide, ref } from "vue"
|
||||
import useColumns from "./hooks/useColumns"
|
||||
import useFetchData from "@/views/project/opeSets/hooks/useFetchData"
|
||||
import useSettings from "@/views/project/opeSets/components/DesignTable/useSettings"
|
||||
import problemApi from "@/api/project/problem"
|
||||
import { useRoute } from "vue-router"
|
||||
import useProblemStatu from "./hooks/useProblemStatu"
|
||||
import useProblemGrade from "./hooks/useProblemGrade"
|
||||
import problemSingleApi from "@/api/project/singleProblem"
|
||||
import CaseModal from "@/views/project/case/components/CaseModal.vue"
|
||||
import MySetting from "@/views/project/opeSets/components/TableCommonComponent/Setting.vue"
|
||||
import Search from "@/views/project/opeSets/components/DesignTable/Search.vue"
|
||||
import ProblemForm from "./form.vue"
|
||||
import type { ISearchFormProblem } from "../DesignTable/types"
|
||||
|
||||
const route = useRoute()
|
||||
const caseModalRef = ref<InstanceType<typeof CaseModal> | null>(null)
|
||||
const problemRef = ref<InstanceType<typeof ProblemForm> | null>(null)
|
||||
|
||||
// 加载初始字典数据
|
||||
const { loading: problemStatusLoading, problemStatus, changeColor } = useProblemStatu()
|
||||
const { loading: problemGradeLoading, gradeOptions, changeGradeColor } = useProblemGrade()
|
||||
|
||||
// 定义表格列
|
||||
const { columns } = useColumns()
|
||||
provide("columns", columns)
|
||||
|
||||
// 请求初始数据钩子
|
||||
const { tableData, isFetching, fetchData, total, pageChange, pageSizeChange, searchParams } = useFetchData(problemApi.searchAllProblem, columns)
|
||||
|
||||
// 查看关联用例
|
||||
const seeRelatedCases = async (record: any) => {
|
||||
const problemId = record.id
|
||||
const res = await problemSingleApi.getRelativeCases({ id: problemId })
|
||||
caseModalRef.value && caseModalRef.value.open(res.data)
|
||||
}
|
||||
|
||||
// 表格设置相关
|
||||
const { options, clickSetting, changeColumn, settingRef } = useSettings()
|
||||
|
||||
// 搜索相关内容
|
||||
const searchVisible = ref(true)
|
||||
const searchSubmit = (data: ISearchFormProblem) => {
|
||||
searchParams.value = { ...data }
|
||||
fetchData(true)
|
||||
}
|
||||
|
||||
// 点击修改
|
||||
const handleOpenProblemModify = (record: any) => {
|
||||
problemRef.value?.open(record)
|
||||
}
|
||||
|
||||
// 刷新表格显示
|
||||
const refresh = () => {
|
||||
fetchData()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.max-height-class {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
</style>
|
||||
@@ -14,6 +14,9 @@
|
||||
<a-tab-pane key="case" title="测试用例">
|
||||
<ProTable type="case"></ProTable>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="problem" title="本轮问题单">
|
||||
<ProTable type="problem"></ProTable>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { ref } from "vue"
|
||||
import { useRoute } from "vue-router"
|
||||
import tool from "@/utils/tool"
|
||||
|
||||
export default function (crudOrFormRef: any, problemFormRef?: any) {
|
||||
const title = ref("问题单表单")
|
||||
const route = useRoute()
|
||||
// 固定是否为FPGA
|
||||
const isFPGA = !tool.checkForCpuOrFPGA(route.query.plant_type)
|
||||
const crudColumns = ref([
|
||||
{
|
||||
title: "ID",
|
||||
@@ -154,7 +157,10 @@ export default function (crudOrFormRef: any, problemFormRef?: any) {
|
||||
hide: true,
|
||||
dataIndex: "timing_diagram",
|
||||
addDefaultValue: "",
|
||||
formType: "editor"
|
||||
formType: "editor",
|
||||
display: !isFPGA,
|
||||
editDisplay: !isFPGA,
|
||||
addDisplay: !isFPGA
|
||||
},
|
||||
{
|
||||
title: "测试步骤",
|
||||
|
||||
Reference in New Issue
Block a user