双击详情完成
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import { defineComponent } from "vue"
|
||||
import { TreeNodeData } from "@arco-design/web-vue"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import testDemandAPI from "@/api/project/testDemand"
|
||||
import useOptions from "./useOptions"
|
||||
import subFormHooks from "@/views/project/projPublicHooks/subFormHooks"
|
||||
|
||||
const DemandSubForm = defineComponent({
|
||||
name: "DemandSubFormForm",
|
||||
setup(_, { expose }) {
|
||||
// hook variable
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const { title, formData, formRef, modalOptions, project_id, visible } = subFormHooks(
|
||||
testDemandAPI.update,
|
||||
treeDataStore.updateTestDemandTreeData,
|
||||
"80%"
|
||||
)
|
||||
// hooks
|
||||
const { options, columnOptions } = useOptions(formRef) // **option里面变化**
|
||||
// 双击打开回调
|
||||
const open = async (nodeData: TreeNodeData) => {
|
||||
// 请求数据
|
||||
try {
|
||||
const key = nodeData.key as string
|
||||
// 设置表单名称
|
||||
title.value = nodeData.title!
|
||||
const res = await testDemandAPI.getTestDemandOne({ project_id, key }) // **API变化**
|
||||
// 更新表单
|
||||
formData.value = res.data // **属性变化**
|
||||
formData.value.round = key.split("-")[0]
|
||||
formData.value.dut = key.split("-")[1]
|
||||
formData.value.designDemand = key.split("-")[2]
|
||||
visible.value = true
|
||||
} catch (e) {
|
||||
visible.value = false
|
||||
}
|
||||
}
|
||||
// out use
|
||||
expose({ open })
|
||||
|
||||
// Dom
|
||||
return () => (
|
||||
// 注意v-model:visible是不能放在对象解构的
|
||||
<a-modal {...modalOptions} v-model:visible={visible.value}>
|
||||
{{
|
||||
title: () => <span>[设计需求]-{title.value}</span>,
|
||||
default: () => (
|
||||
<ma-form
|
||||
ref={formRef}
|
||||
v-model={formData.value}
|
||||
options={options.value}
|
||||
columns={columnOptions.value}
|
||||
>
|
||||
{{
|
||||
"inputPrepend-ident": () => <span>XQ_XX_</span>
|
||||
}}
|
||||
</ma-form>
|
||||
)
|
||||
}}
|
||||
</a-modal>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default DemandSubForm
|
||||
// 组件类型导出
|
||||
type DemandSubFormOrigin = InstanceType<typeof DemandSubForm>
|
||||
export interface DemandSubFormInstance extends DemandSubFormOrigin {
|
||||
open(nodeData: TreeNodeData): void
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { ref, computed } from "vue"
|
||||
import tool from "@/utils/tool"
|
||||
import useColumn from "../hooks/useColumns"
|
||||
|
||||
// demand在这里设置不同ma-form选项
|
||||
export default function useOptions(formRef: any) {
|
||||
const options = ref({
|
||||
showButtons: false,
|
||||
labelAlign: "center"
|
||||
})
|
||||
const crudColumns = useColumn(formRef)
|
||||
const columnOptions = computed(() => {
|
||||
return tool.renameKeyInArray(crudColumns.value, "commonRules", "rules")
|
||||
})
|
||||
return { options, columnOptions }
|
||||
}
|
||||
145
cdTMP/src/views/project/design-demand/hooks/useColumns.ts
Normal file
145
cdTMP/src/views/project/design-demand/hooks/useColumns.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import { ref } from "vue"
|
||||
import PinYinMatch from "pinyin-match"
|
||||
|
||||
export default function (crudOrFormRef: any) {
|
||||
const crudColumns = ref([
|
||||
{
|
||||
title: "ID",
|
||||
align: "center",
|
||||
hide: true,
|
||||
dataIndex: "id",
|
||||
display: false
|
||||
},
|
||||
{
|
||||
title: "测项标识",
|
||||
width: 150,
|
||||
dataIndex: "ident",
|
||||
sortable: { sortDirections: ["ascend"] },
|
||||
align: "center",
|
||||
search: true,
|
||||
validateTrigger: "blur",
|
||||
placeholder: "请填写测试项的标识,注意标识不能重复",
|
||||
commonRules: [{ required: true, message: "测试项标识必填" }],
|
||||
openPrepend: true
|
||||
},
|
||||
{
|
||||
title: "名称",
|
||||
dataIndex: "name",
|
||||
width: 120,
|
||||
align: "center",
|
||||
search: true,
|
||||
commonRules: [{ required: true, message: "名称是必填" }],
|
||||
validateTrigger: "blur"
|
||||
},
|
||||
{
|
||||
title: "优先级",
|
||||
dataIndex: "priority",
|
||||
search: true,
|
||||
formType: "radio",
|
||||
align: "center",
|
||||
addDefaultValue: "1",
|
||||
dict: {
|
||||
name: "priority",
|
||||
props: { label: "title", value: "key" },
|
||||
translation: true,
|
||||
tagColors: { 1: "red", 2: "blue", 3: "green" }
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "测试类型",
|
||||
dataIndex: "testType",
|
||||
search: true,
|
||||
align: "center",
|
||||
formType: "select",
|
||||
sortable: { sortDirections: ["ascend", "descend"] },
|
||||
addDefaultValue: "4",
|
||||
maxLength: 200,
|
||||
commonRules: [{ required: true, message: "测试类型必选" }],
|
||||
dict: { name: "testType", translation: true, props: { label: "title", value: "key" } },
|
||||
extra: "支持拼音搜索,例如:gn可以搜索出功能测试",
|
||||
// 这是arco的属性,所以在ma-crud和ma-form可以直接使用arco属性和事件(事件+onXXX)
|
||||
filterOption: function (inputValue, selectedOption) {
|
||||
if (inputValue) {
|
||||
let matchRes = PinYinMatch.match(selectedOption.label, inputValue)
|
||||
if (matchRes) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "测试手段",
|
||||
align: "center",
|
||||
dataIndex: "testMethod",
|
||||
formType: "select",
|
||||
multiple: true,
|
||||
dict: { name: "testMethod", props: { label: "title", value: "key" }, translation: true }
|
||||
},
|
||||
{
|
||||
title: "充分性要求",
|
||||
hide: true,
|
||||
dataIndex: "adequacy",
|
||||
formType: "textarea",
|
||||
maxLength: 256,
|
||||
commonRules: [{ required: true, message: "充分性描述必填" }],
|
||||
addDefaultValue:
|
||||
"测试用例覆盖XX子项名称1、XX子项名称2、XX子项名称3子项要求的全部内容。\n所有用例执行完毕,对于未执行的用例说明未执行原因。"
|
||||
},
|
||||
{
|
||||
title: "测试子项",
|
||||
hide: true,
|
||||
dataIndex: "testContent",
|
||||
commonRules: [{ required: true, message: "测试方法是必填的" }],
|
||||
formType: "children-form",
|
||||
formList: [
|
||||
{
|
||||
title: "子项名称",
|
||||
dataIndex: "subName",
|
||||
placeholder: "对应测试项描述标题,和测试方法的标题",
|
||||
rules: [{ required: true, message: "测试子项名称必填" }],
|
||||
onChange: (ev) => {
|
||||
// 取出子项的对象数组
|
||||
const subItemFormData = crudOrFormRef.value.getFormData().testContent
|
||||
// 取出充分性条件字段字符串
|
||||
const mapRes = subItemFormData.map((subItem) => subItem.subName)
|
||||
crudOrFormRef.value.getFormData().adequacy = `测试用例覆盖${mapRes.join(
|
||||
"、"
|
||||
)}子项要求的全部内容。\n所有用例执行完毕,对于未执行的用例说明未执行原因。`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "子项描述",
|
||||
dataIndex: "subDesc",
|
||||
formType: "textarea",
|
||||
placeholder: "对应大纲测试项表格的测试项描述",
|
||||
rules: [{ required: true, message: "测试子项描述必填" }]
|
||||
},
|
||||
{
|
||||
title: "条件",
|
||||
dataIndex: "condition",
|
||||
formType: "textarea",
|
||||
placeholder: "在什么环境和前置条件下"
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
dataIndex: "operation",
|
||||
formType: "textarea",
|
||||
placeholder: "通过xxx操作"
|
||||
},
|
||||
{
|
||||
title: "观察",
|
||||
dataIndex: "observe",
|
||||
formType: "textarea",
|
||||
placeholder: "查看xxx内容"
|
||||
},
|
||||
{
|
||||
title: "期望",
|
||||
dataIndex: "expect",
|
||||
formType: "textarea",
|
||||
placeholder: "xxx结果正确"
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
return crudColumns
|
||||
}
|
||||
131
cdTMP/src/views/project/design-demand/hooks/useCrudOpMore.ts
Normal file
131
cdTMP/src/views/project/design-demand/hooks/useCrudOpMore.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import MaCrud from "@/components/ma-crud/index.vue"
|
||||
import { type Ref, ref, getCurrentInstance } from "vue"
|
||||
import testDemandApi from "@/api/project/testDemand"
|
||||
import { useRoute } from "vue-router"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import { cloneDeep, isEqual } from "lodash-es"
|
||||
// types
|
||||
interface ITestContent {
|
||||
subName: string
|
||||
subDesc: string
|
||||
}
|
||||
/**
|
||||
* 测试项表格的Crud-options
|
||||
*/
|
||||
export default function (crudRef: Ref<InstanceType<typeof MaCrud>>) {
|
||||
// global
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const route = useRoute() as any
|
||||
// variable
|
||||
const roundNumber = (route.query.key as string)!.split("-")[0]
|
||||
const dutNumber = (route.query.key as string)!.split("-")[1]
|
||||
const designDemandNumber = (route.query.key as string)!.split("-")[2]
|
||||
// refs
|
||||
const projectId = ref(route.query.id)
|
||||
// 处理弹窗关闭事件:处理用户数据是否保留
|
||||
const app = getCurrentInstance()!.appContext.config.globalProperties
|
||||
let beforeFormContent: ITestContent[] | undefined = undefined
|
||||
const handleBeforeCancel = () => {
|
||||
if (!beforeFormContent) {
|
||||
return
|
||||
}
|
||||
const iuEqualValue = isEqual(crudRef.value.getFormData().testContent, beforeFormContent)
|
||||
!iuEqualValue &&
|
||||
app.$modal.confirm({
|
||||
title: "测试项步骤内容你已改动,是否保留您编写的测试项/测试用例步骤数据?",
|
||||
content: "",
|
||||
okText: "保留",
|
||||
cancelText: "恢复原数据",
|
||||
simple: true,
|
||||
onOk: () => null,
|
||||
onCancel: () => {
|
||||
crudRef.value.refresh()
|
||||
}
|
||||
})
|
||||
}
|
||||
const crudOptions = ref({
|
||||
api: testDemandApi.getTestDemandList,
|
||||
add: { show: true, api: testDemandApi.save, text: "新增测试项" },
|
||||
edit: { show: true, api: testDemandApi.update, text: "修改测试项" },
|
||||
delete: { show: true, api: testDemandApi.delete },
|
||||
showTools: false,
|
||||
beforeOpenAdd: function () {
|
||||
// 1.新增则将form的content数据变为undifined以便判断
|
||||
beforeFormContent = undefined
|
||||
// 2.设置标识
|
||||
let key_split = (route.query.key as string)!.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let design_key = key_split[2]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} > ${td[round_key].title} > ${td[round_key].children[dut_key].title} > ${td[round_key].children[dut_key].children[design_key].title} > 测试项-`
|
||||
return true
|
||||
},
|
||||
beforeOpenEdit: function (record) {
|
||||
// 1.储存打开前form的content数据到ref中,以便后续比较
|
||||
beforeFormContent = cloneDeep(record.testContent)
|
||||
// 2.处理标识
|
||||
let key_split = (route.query.key as string)!.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let design_key = key_split[2]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} > ${td[round_key].title} > ${td[round_key].children[dut_key].title} > ${td[round_key].children[dut_key].children[design_key].title} >测试项[${record.name}]-`
|
||||
return true
|
||||
},
|
||||
afterAdd: (res: any) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateTestDemandTreeData(res.data, id)
|
||||
},
|
||||
afterEdit: (res: any) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateTestDemandTreeData(res.data, id)
|
||||
},
|
||||
afterDelete: (_: any, record: any) => {
|
||||
let id = projectId.value
|
||||
if (!record) {
|
||||
record = { key: route.query.key + "-X" }
|
||||
}
|
||||
treeDataStore.updateTestDemandTreeData(record, id)
|
||||
// 清空选择
|
||||
crudRef.value.tableRef.selectAll(false)
|
||||
},
|
||||
parameters: {
|
||||
projectId: route.query.id,
|
||||
round: roundNumber,
|
||||
dut: dutNumber,
|
||||
designDemand: designDemandNumber
|
||||
},
|
||||
showIndex: false,
|
||||
rowSelection: { showCheckedAll: true },
|
||||
searchColNumber: 3,
|
||||
tablePagination: false,
|
||||
operationColumnWidth: 200,
|
||||
operationColumn: true,
|
||||
operationColumnAlign: "center",
|
||||
formOption: {
|
||||
width: 1200,
|
||||
layout: [
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{ span: 12, formList: [{ dataIndex: "ident" }] },
|
||||
{ span: 12, formList: [{ dataIndex: "name" }] }
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [{ span: 24, formList: [{ dataIndex: "priority" }] }]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{ span: 12, formList: [{ dataIndex: "testType" }] },
|
||||
{ span: 12, formList: [{ dataIndex: "testMethod" }] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
return { projectId, crudOptions, handleBeforeCancel }
|
||||
}
|
||||
@@ -1,280 +0,0 @@
|
||||
import { ref, getCurrentInstance } from "vue"
|
||||
import PinYinMatch from "pinyin-match"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import { useRoute } from "vue-router"
|
||||
import testDemandApi from "@/api/project/testDemand"
|
||||
import { isEqual, cloneDeep } from "lodash-es"
|
||||
interface ITestContent {
|
||||
subName: string
|
||||
subDesc: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 1.配置crud以及全组件使用变量
|
||||
* 2.另外包含一个测试项是否保留数据的功能,含一个ref以及一个事件处理函数
|
||||
*/
|
||||
export default function useCrudRef() {
|
||||
// global
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const route = useRoute()
|
||||
// variable
|
||||
const roundNumber = (route.query.key as string)!.split("-")[0]
|
||||
const dutNumber = (route.query.key as string)!.split("-")[1]
|
||||
const designDemandNumber = (route.query.key as string)!.split("-")[2]
|
||||
// refs
|
||||
const projectId = ref(route.query.id)
|
||||
const crudRef = ref()
|
||||
// 处理弹窗关闭事件:处理用户数据是否保留
|
||||
|
||||
const app = getCurrentInstance()!.appContext.config.globalProperties
|
||||
let beforeFormContent: ITestContent[] | undefined = undefined
|
||||
const handleBeforeCancel = () => {
|
||||
if (!beforeFormContent) {
|
||||
return
|
||||
}
|
||||
const iuEqualValue = isEqual(crudRef.value.getFormData().testContent, beforeFormContent)
|
||||
!iuEqualValue &&
|
||||
app.$modal.confirm({
|
||||
title: "测试项步骤内容你已改动,是否保留您编写的测试项/测试用例步骤数据?",
|
||||
content: "",
|
||||
okText: "保留",
|
||||
cancelText: "恢复原数据",
|
||||
simple: true,
|
||||
onOk: () => null,
|
||||
onCancel: () => {
|
||||
crudRef.value.refresh()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 配置
|
||||
// crud组件
|
||||
const crudOptions = ref({
|
||||
api: testDemandApi.getTestDemandList,
|
||||
add: { show: true, api: testDemandApi.save, text: "新增测试项" },
|
||||
edit: { show: true, api: testDemandApi.update, text: "修改测试项" },
|
||||
delete: { show: true, api: testDemandApi.delete },
|
||||
showTools: false,
|
||||
beforeOpenAdd: function () {
|
||||
// 1.新增则将form的content数据变为undifined以便判断
|
||||
beforeFormContent = undefined
|
||||
// 2.设置标识
|
||||
let key_split = (route.query.key as string)!.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let design_key = key_split[2]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} > ${td[round_key].title} > ${td[round_key].children[dut_key].title} > ${td[round_key].children[dut_key].children[design_key].title} > 测试项-`
|
||||
return true
|
||||
},
|
||||
beforeOpenEdit: function (record) {
|
||||
// 1.储存打开前form的content数据到ref中,以便后续比较
|
||||
beforeFormContent = cloneDeep(record.testContent)
|
||||
// 2.处理标识
|
||||
let key_split = (route.query.key as string)!.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let design_key = key_split[2]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} > ${td[round_key].title} > ${td[round_key].children[dut_key].title} > ${td[round_key].children[dut_key].children[design_key].title} >测试项[${record.name}]-`
|
||||
return true
|
||||
},
|
||||
afterAdd: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateTestDemandTreeData(res.data, id)
|
||||
},
|
||||
afterEdit: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateTestDemandTreeData(res.data, id)
|
||||
},
|
||||
afterDelete: (res, record) => {
|
||||
let id = projectId.value
|
||||
if (!record) {
|
||||
record = { key: route.query.key + "-X" }
|
||||
}
|
||||
treeDataStore.updateTestDemandTreeData(record, id)
|
||||
// 清空选择
|
||||
crudRef.value.tableRef.selectAll(false)
|
||||
},
|
||||
parameters: {
|
||||
projectId: route.query.id,
|
||||
round: roundNumber,
|
||||
dut: dutNumber,
|
||||
designDemand: designDemandNumber
|
||||
},
|
||||
showIndex: false,
|
||||
rowSelection: { showCheckedAll: true },
|
||||
searchColNumber: 3,
|
||||
tablePagination: false,
|
||||
operationColumnWidth: 200,
|
||||
operationColumn: true,
|
||||
operationColumnAlign: "center",
|
||||
formOption: {
|
||||
width: 1200,
|
||||
layout: [
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{ span: 12, formList: [{ dataIndex: "ident" }] },
|
||||
{ span: 12, formList: [{ dataIndex: "name" }] }
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [{ span: 24, formList: [{ dataIndex: "priority" }] }]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{ span: 12, formList: [{ dataIndex: "testType" }] },
|
||||
{ span: 12, formList: [{ dataIndex: "testMethod" }] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
const crudColumns = ref([
|
||||
{
|
||||
title: "ID",
|
||||
align: "center",
|
||||
hide: true,
|
||||
dataIndex: "id"
|
||||
},
|
||||
{
|
||||
title: "测项标识",
|
||||
width: 150,
|
||||
dataIndex: "ident",
|
||||
sortable: { sortDirections: ["ascend"] },
|
||||
align: "center",
|
||||
search: true,
|
||||
validateTrigger: "blur",
|
||||
placeholder: "请填写测试项的标识,注意标识不能重复",
|
||||
commonRules: [{ required: true, message: "测试项标识必填" }],
|
||||
openPrepend: true
|
||||
},
|
||||
{
|
||||
title: "名称",
|
||||
dataIndex: "name",
|
||||
width: 120,
|
||||
align: "center",
|
||||
search: true,
|
||||
commonRules: [{ required: true, message: "名称是必填" }],
|
||||
validateTrigger: "blur"
|
||||
},
|
||||
{
|
||||
title: "优先级",
|
||||
dataIndex: "priority",
|
||||
search: true,
|
||||
formType: "radio",
|
||||
align: "center",
|
||||
addDefaultValue: "1",
|
||||
dict: {
|
||||
name: "priority",
|
||||
props: { label: "title", value: "key" },
|
||||
translation: true,
|
||||
tagColors: { 1: "red", 2: "blue", 3: "green" }
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "测试类型",
|
||||
dataIndex: "testType",
|
||||
search: true,
|
||||
align: "center",
|
||||
formType: "select",
|
||||
sortable: { sortDirections: ["ascend", "descend"] },
|
||||
addDefaultValue: "4",
|
||||
maxLength: 200,
|
||||
commonRules: [{ required: true, message: "测试类型必选" }],
|
||||
dict: { name: "testType", translation: true, props: { label: "title", value: "key" } },
|
||||
extra: "支持拼音搜索,例如:gn可以搜索出功能测试",
|
||||
// 这是arco的属性,所以在ma-crud和ma-form可以直接使用arco属性和事件(事件+onXXX)
|
||||
filterOption: function (inputValue, selectedOption) {
|
||||
if (inputValue) {
|
||||
let matchRes = PinYinMatch.match(selectedOption.label, inputValue)
|
||||
if (matchRes) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "测试手段",
|
||||
align: "center",
|
||||
dataIndex: "testMethod",
|
||||
formType: "select",
|
||||
multiple: true,
|
||||
dict: { name: "testMethod", props: { label: "title", value: "key" }, translation: true }
|
||||
},
|
||||
{
|
||||
title: "充分性要求",
|
||||
hide: true,
|
||||
dataIndex: "adequacy",
|
||||
formType: "textarea",
|
||||
maxLength: 256,
|
||||
commonRules: [{ required: true, message: "充分性描述必填" }],
|
||||
addDefaultValue:
|
||||
"测试用例覆盖XX子项名称1、XX子项名称2、XX子项名称3子项要求的全部内容。\n所有用例执行完毕,对于未执行的用例说明未执行原因。"
|
||||
},
|
||||
{
|
||||
title: "测试子项",
|
||||
hide: true,
|
||||
dataIndex: "testContent",
|
||||
commonRules: [{ required: true, message: "测试方法是必填的" }],
|
||||
formType: "children-form",
|
||||
formList: [
|
||||
{
|
||||
title: "子项名称",
|
||||
dataIndex: "subName",
|
||||
placeholder: "对应测试项描述标题,和测试方法的标题",
|
||||
rules: [{ required: true, message: "测试子项名称必填" }],
|
||||
onChange: (ev) => {
|
||||
// 取出子项的对象数组
|
||||
const subItemFormData = crudRef.value.getFormData().testContent
|
||||
// 取出充分性条件字段字符串
|
||||
const mapRes = subItemFormData.map((subItem) => subItem.subName)
|
||||
crudRef.value.getFormData().adequacy = `测试用例覆盖${mapRes.join(
|
||||
"、"
|
||||
)}子项要求的全部内容。\n所有用例执行完毕,对于未执行的用例说明未执行原因。`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "子项描述",
|
||||
dataIndex: "subDesc",
|
||||
formType: "textarea",
|
||||
placeholder: "对应大纲测试项表格的测试项描述",
|
||||
rules: [{ required: true, message: "测试子项描述必填" }]
|
||||
},
|
||||
{
|
||||
title: "条件",
|
||||
dataIndex: "condition",
|
||||
formType: "textarea",
|
||||
placeholder: "在什么环境和前置条件下"
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
dataIndex: "operation",
|
||||
formType: "textarea",
|
||||
placeholder: "通过xxx操作"
|
||||
},
|
||||
{
|
||||
title: "观察",
|
||||
dataIndex: "observe",
|
||||
formType: "textarea",
|
||||
placeholder: "查看xxx内容"
|
||||
},
|
||||
{
|
||||
title: "期望",
|
||||
dataIndex: "expect",
|
||||
formType: "textarea",
|
||||
placeholder: "xxx结果正确"
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
return {
|
||||
projectId,
|
||||
crudRef,
|
||||
crudOptions,
|
||||
crudColumns,
|
||||
handleBeforeCancel
|
||||
}
|
||||
}
|
||||
@@ -45,11 +45,14 @@
|
||||
import { ref } from "vue"
|
||||
import commonApi from "@/api/common"
|
||||
// hooks
|
||||
import useCrudRef from "./hooks/useCrudRef"
|
||||
import useCrudOpMore from "./hooks/useCrudOpMore"
|
||||
import useColumn from "./hooks/useColumns"
|
||||
import useRalateDemand from "./hooks/useRalateDemand"
|
||||
|
||||
// refs
|
||||
const crudRef = ref(null)
|
||||
// 根据传参获取key,分别为轮次、设计需求的key
|
||||
const { projectId, crudRef, crudOptions, crudColumns, handleBeforeCancel } = useCrudRef()
|
||||
const { projectId, crudOptions, handleBeforeCancel } = useCrudOpMore(crudRef)
|
||||
const crudColumns = useColumn(crudRef)
|
||||
// 关联弹窗、关联的事件处理
|
||||
const { visible, relatedData, options, cascaderLoading, computedRelatedData, handleOpenRelationCSX, handleRelatedOk } =
|
||||
useRalateDemand(projectId)
|
||||
|
||||
69
cdTMP/src/views/project/dut/DesignSubForm/index.tsx
Normal file
69
cdTMP/src/views/project/dut/DesignSubForm/index.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { defineComponent } from "vue"
|
||||
import { TreeNodeData } from "@arco-design/web-vue"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import designDemandAPI from "@/api/project/designDemand"
|
||||
import useOptions from "./useOptions"
|
||||
import subFormHooks from "@/views/project/projPublicHooks/subFormHooks"
|
||||
|
||||
const DesignSubForm = defineComponent({
|
||||
name: "DesignSubForm",
|
||||
setup(_, { expose }) {
|
||||
// hook variable
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const { title, formData, formRef, modalOptions, project_id, visible } = subFormHooks(
|
||||
designDemandAPI.update,
|
||||
treeDataStore.updateDesignDemandTreeData,
|
||||
"80%"
|
||||
)
|
||||
// hooks
|
||||
const { options, columnOptions } = useOptions(formRef) // **option里面变化**
|
||||
// 双击打开回调
|
||||
const open = async (nodeData: TreeNodeData) => {
|
||||
// 请求数据
|
||||
try {
|
||||
const key = nodeData.key as string
|
||||
// 设置表单名称
|
||||
title.value = nodeData.title!
|
||||
const res = await designDemandAPI.getDesignDemandOne({ project_id, key }) // **API变化**
|
||||
// 更新表单
|
||||
formData.value = res.data // **属性变化**
|
||||
formData.value.round = key.split("-")[0]
|
||||
formData.value.dut = key.split("-")[1]
|
||||
visible.value = true
|
||||
} catch (e) {
|
||||
visible.value = false
|
||||
}
|
||||
}
|
||||
// out use
|
||||
expose({ open })
|
||||
|
||||
// Dom
|
||||
return () => (
|
||||
// 注意v-model:visible是不能放在对象解构的
|
||||
<a-modal {...modalOptions} v-model:visible={visible.value}>
|
||||
{{
|
||||
title: () => <span>[设计需求]-{title.value}</span>,
|
||||
default: () => (
|
||||
<ma-form
|
||||
ref={formRef}
|
||||
v-model={formData.value}
|
||||
options={options.value}
|
||||
columns={columnOptions.value}
|
||||
>
|
||||
{{
|
||||
"inputPrepend-ident": () => <span>SJ-XX-</span>
|
||||
}}
|
||||
</ma-form>
|
||||
)
|
||||
}}
|
||||
</a-modal>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default DesignSubForm
|
||||
// 组件类型导出
|
||||
type DesignSubFormOrigin = InstanceType<typeof DesignSubForm>
|
||||
export interface DesignSubFormInstance extends DesignSubFormOrigin {
|
||||
open(nodeData: TreeNodeData): void
|
||||
}
|
||||
16
cdTMP/src/views/project/dut/DesignSubForm/useOptions.ts
Normal file
16
cdTMP/src/views/project/dut/DesignSubForm/useOptions.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { ref, computed } from "vue"
|
||||
import tool from "@/utils/tool"
|
||||
import useColumn from "../hooks/useColumns"
|
||||
|
||||
// 设置不同ma-form选项
|
||||
export default function useOptions(formRef: any) {
|
||||
const options = ref({
|
||||
showButtons: false,
|
||||
labelAlign: "center"
|
||||
})
|
||||
const crudColumns = useColumn(formRef)
|
||||
const columnOptions = computed(() => {
|
||||
return tool.renameKeyInArray(crudColumns.value, "commonRules", "rules")
|
||||
})
|
||||
return { options, columnOptions }
|
||||
}
|
||||
119
cdTMP/src/views/project/dut/hooks/useColumns.ts
Normal file
119
cdTMP/src/views/project/dut/hooks/useColumns.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { ref } from "vue"
|
||||
|
||||
export default function (crudOrFormRef: any) {
|
||||
const crudColumns = ref([
|
||||
{
|
||||
title: "ID",
|
||||
align: "center",
|
||||
width: 50,
|
||||
hide: true,
|
||||
dataIndex: "id",
|
||||
commonRules: [{ required: true, message: "ID必填" }],
|
||||
validateTrigger: "blur",
|
||||
display: false
|
||||
},
|
||||
{
|
||||
title: "设需标识",
|
||||
align: "center",
|
||||
sortable: { sortDirections: ["ascend"] },
|
||||
width: 180,
|
||||
dataIndex: "ident",
|
||||
search: true,
|
||||
validateTrigger: "blur",
|
||||
placeholder: "请输入文档中设计需求的标识",
|
||||
help: '若不知道则填"无"或不填',
|
||||
openPrepend: true
|
||||
},
|
||||
{
|
||||
title: "设需名称",
|
||||
align: "center",
|
||||
width: 200,
|
||||
dataIndex: "name",
|
||||
search: true,
|
||||
commonRules: [{ required: true, message: "设计需求名称是必填" }],
|
||||
validateTrigger: "blur"
|
||||
},
|
||||
{
|
||||
title: "章节号",
|
||||
align: "center",
|
||||
width: 150,
|
||||
dataIndex: "chapter",
|
||||
search: true,
|
||||
help: '若为隐含需求则填"/"'
|
||||
},
|
||||
{
|
||||
title: "需求类型",
|
||||
width: 150,
|
||||
align: "center",
|
||||
dataIndex: "demandType",
|
||||
addDefaultValue: "1",
|
||||
formType: "radio",
|
||||
search: true,
|
||||
dict: { name: "demandType", props: { label: "title", value: "key" }, translation: true },
|
||||
commonRules: [{ required: true, message: "需求类型是必填" }],
|
||||
validateTrigger: "blur",
|
||||
// 主要为了添加“接口”的4个字段
|
||||
onControl: (value) => {
|
||||
if (value === "3") {
|
||||
return {
|
||||
source: { display: true },
|
||||
to: { display: true },
|
||||
type: { display: true },
|
||||
protocal: { display: true }
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
source: { display: false },
|
||||
to: { display: false },
|
||||
type: { display: false },
|
||||
protocal: { display: false }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
formType: "grid-tailwind",
|
||||
customClass: [],
|
||||
colNumber: 2,
|
||||
cols: [
|
||||
{
|
||||
formList: [
|
||||
{
|
||||
title: "接口来源",
|
||||
dataIndex: "source",
|
||||
hide: true
|
||||
},
|
||||
{
|
||||
title: "目的地",
|
||||
dataIndex: "to",
|
||||
hide: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formList: [
|
||||
{
|
||||
title: "接口类型",
|
||||
dataIndex: "type",
|
||||
hide: true
|
||||
},
|
||||
{
|
||||
title: "接口内容",
|
||||
dataIndex: "protocal",
|
||||
hide: true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "需求描述",
|
||||
dataIndex: "description",
|
||||
hide: true,
|
||||
width: 300,
|
||||
formType: "editor",
|
||||
height: 300
|
||||
}
|
||||
])
|
||||
return crudColumns
|
||||
}
|
||||
74
cdTMP/src/views/project/dut/hooks/useCrudOptions.ts
Normal file
74
cdTMP/src/views/project/dut/hooks/useCrudOptions.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import MaCrud from "@/components/ma-crud/index.vue"
|
||||
import { type Ref, ref } from "vue"
|
||||
import designDemandApi from "@/api/project/designDemand"
|
||||
import { useRoute } from "vue-router"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
/**
|
||||
* Dut被测件的crud选项
|
||||
*/
|
||||
export default function (crudRef: Ref<InstanceType<typeof MaCrud>>) {
|
||||
// globals
|
||||
const route = useRoute() as any
|
||||
const projectId = ref(route.query.id)
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const roundNumber = (route.query.key as any).split("-")[0]
|
||||
const dutNumber = (route.query.key as any).split("-")[1]
|
||||
// refs
|
||||
const crudOptions = ref({
|
||||
api: designDemandApi.getDesignDemandList,
|
||||
add: { show: true, api: designDemandApi.save, text: "新增设计需求" },
|
||||
edit: { show: true, api: designDemandApi.editDesignDemand, text: "编辑设计需求" },
|
||||
delete: { show: true, api: designDemandApi.delete },
|
||||
// 处理添加后函数
|
||||
beforeOpenAdd: function () {
|
||||
let key_split = route.query.key.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} > ${(td[round_key] as any).title} > ${(td[round_key] as any).children[dut_key].title} > 设计需求-`
|
||||
return true
|
||||
},
|
||||
beforeOpenEdit: function (record) {
|
||||
let key_split = route.query.key.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let td = treeDataStore.treeData
|
||||
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) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateDesignDemandTreeData(res.data, id)
|
||||
},
|
||||
afterEdit: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateDesignDemandTreeData(res.data, id)
|
||||
},
|
||||
afterDelete: (res, record) => {
|
||||
let id = projectId.value
|
||||
if (!record) {
|
||||
record = { key: route.query.key + "-X" }
|
||||
}
|
||||
treeDataStore.updateDesignDemandTreeData(record, id)
|
||||
// 删除后情况行选择器
|
||||
crudRef.value.tableRef.selectAll(false)
|
||||
},
|
||||
parameters: {
|
||||
projectId: route.query.id,
|
||||
round: roundNumber,
|
||||
dut: dutNumber
|
||||
},
|
||||
showIndex: false,
|
||||
rowSelection: { showCheckedAll: true },
|
||||
searchColNumber: 4,
|
||||
tablePagination: false,
|
||||
operationColumnWidth: 250,
|
||||
operationColumn: true,
|
||||
operationColumnAlign: "center",
|
||||
formOption: {
|
||||
width: 1200
|
||||
},
|
||||
showTools: false
|
||||
})
|
||||
return crudOptions
|
||||
}
|
||||
@@ -25,21 +25,18 @@
|
||||
|
||||
<script setup lang="jsx">
|
||||
import { ref } from "vue"
|
||||
import useCrudOptions from "@/views/project/dut/hooks/useCrudOptions"
|
||||
import useColumns from "./hooks/useColumns"
|
||||
import { useRoute } from "vue-router"
|
||||
import designDemandApi from "@/api/project/designDemand"
|
||||
import dutApi from "@/api/project/dut"
|
||||
import commonApi from "@/api/common"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import FileInputModal from "./components/FileInputModal/index.vue"
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const route = useRoute()
|
||||
const crudRef = ref()
|
||||
const roundNumber = route.query.key.split("-")[0]
|
||||
const dutNumber = route.query.key.split("-")[1]
|
||||
const projectId = ref(route.query.id)
|
||||
// 5月8日修改设计需求标识就按SJ-FT-设计需求标识来
|
||||
const demandTypeDict = ref([])
|
||||
!(function () {
|
||||
;(function () {
|
||||
commonApi.getDict("demandType").then((res) => {
|
||||
demandTypeDict.value = res
|
||||
})
|
||||
@@ -63,175 +60,8 @@ const showType = (record) => {
|
||||
}
|
||||
}
|
||||
// crud组件
|
||||
const crudOptions = ref({
|
||||
api: designDemandApi.getDesignDemandList,
|
||||
add: { show: true, api: designDemandApi.save, text: "新增设计需求" },
|
||||
edit: { show: true, api: designDemandApi.editDesignDemand, text: "编辑设计需求" },
|
||||
delete: { show: true, api: designDemandApi.delete },
|
||||
// 处理添加后函数
|
||||
beforeOpenAdd: function () {
|
||||
let key_split = route.query.key.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} > ${td[round_key].title} > ${td[round_key].children[dut_key].title} > 设计需求-`
|
||||
return true
|
||||
},
|
||||
beforeOpenEdit: function (record) {
|
||||
let key_split = route.query.key.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} > ${td[round_key].title} > ${td[round_key].children[dut_key].title} >设计需求[${record.name}]-`
|
||||
return true
|
||||
},
|
||||
afterAdd: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateDesignDemandTreeData(res.data, id)
|
||||
},
|
||||
afterEdit: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateDesignDemandTreeData(res.data, id)
|
||||
},
|
||||
afterDelete: (res, record) => {
|
||||
let id = projectId.value
|
||||
if (!record) {
|
||||
record = { key: route.query.key + "-X" }
|
||||
}
|
||||
treeDataStore.updateDesignDemandTreeData(record, id)
|
||||
// 删除后情况行选择器
|
||||
crudRef.value.tableRef.selectAll(false)
|
||||
},
|
||||
parameters: {
|
||||
projectId: route.query.id,
|
||||
round: roundNumber,
|
||||
dut: dutNumber
|
||||
},
|
||||
showIndex: false,
|
||||
rowSelection: { showCheckedAll: true },
|
||||
searchColNumber: 4,
|
||||
tablePagination: false,
|
||||
operationColumnWidth: 250,
|
||||
operationColumn: true,
|
||||
operationColumnAlign: "center",
|
||||
formOption: {
|
||||
width: 1200
|
||||
},
|
||||
showTools: false
|
||||
})
|
||||
const crudColumns = ref([
|
||||
{
|
||||
title: "ID",
|
||||
align: "center",
|
||||
width: 50,
|
||||
hide: true,
|
||||
dataIndex: "id",
|
||||
commonRules: [{ required: true, message: "ID必填" }],
|
||||
validateTrigger: "blur"
|
||||
},
|
||||
{
|
||||
title: "设需标识",
|
||||
align: "center",
|
||||
sortable: { sortDirections: ["ascend"] },
|
||||
width: 180,
|
||||
dataIndex: "ident",
|
||||
search: true,
|
||||
validateTrigger: "blur",
|
||||
placeholder: "请输入文档中设计需求的标识",
|
||||
help: '若不知道则填"无"或不填',
|
||||
openPrepend: true
|
||||
},
|
||||
{
|
||||
title: "设需名称",
|
||||
align: "center",
|
||||
width: 200,
|
||||
dataIndex: "name",
|
||||
search: true,
|
||||
commonRules: [{ required: true, message: "设计需求名称是必填" }],
|
||||
validateTrigger: "blur"
|
||||
},
|
||||
{
|
||||
title: "章节号",
|
||||
align: "center",
|
||||
width: 150,
|
||||
dataIndex: "chapter",
|
||||
search: true,
|
||||
help: '若为隐含需求则填"/"'
|
||||
},
|
||||
{
|
||||
title: "需求类型",
|
||||
width: 150,
|
||||
align: "center",
|
||||
dataIndex: "demandType",
|
||||
addDefaultValue: "1",
|
||||
formType: "radio",
|
||||
search: true,
|
||||
dict: { name: "demandType", props: { label: "title", value: "key" }, translation: true },
|
||||
commonRules: [{ required: true, message: "需求类型是必填" }],
|
||||
validateTrigger: "blur",
|
||||
// 主要为了添加“接口”的4个字段
|
||||
onControl: (value) => {
|
||||
if (value === "3") {
|
||||
return {
|
||||
source: { display: true },
|
||||
to: { display: true },
|
||||
type: { display: true },
|
||||
protocal: { display: true }
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
source: { display: false },
|
||||
to: { display: false },
|
||||
type: { display: false },
|
||||
protocal: { display: false }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
formType: "grid-tailwind",
|
||||
customClass: [],
|
||||
colNumber: 2,
|
||||
cols: [
|
||||
{
|
||||
formList: [
|
||||
{
|
||||
title: "接口来源",
|
||||
dataIndex: "source",
|
||||
hide: true
|
||||
},
|
||||
{
|
||||
title: "目的地",
|
||||
dataIndex: "to",
|
||||
hide: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formList: [
|
||||
{
|
||||
title: "接口类型",
|
||||
dataIndex: "type",
|
||||
hide: true
|
||||
},
|
||||
{
|
||||
title: "接口内容",
|
||||
dataIndex: "protocal",
|
||||
hide: true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "需求描述",
|
||||
dataIndex: "description",
|
||||
hide: true,
|
||||
width: 300,
|
||||
formType: "editor",
|
||||
height: 300
|
||||
}
|
||||
])
|
||||
const crudOptions = useCrudOptions(crudRef)
|
||||
const crudColumns = useColumns(crudRef)
|
||||
// ~~~大功能打开ma-form-modal~~~
|
||||
const fileInputRef = ref(null)
|
||||
const handleAddFileInputDemand = () => {
|
||||
|
||||
42
cdTMP/src/views/project/projPublicHooks/subFormHooks.ts
Normal file
42
cdTMP/src/views/project/projPublicHooks/subFormHooks.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 该hook为了各个页面双击弹窗SubForm进行公共代码提取
|
||||
*/
|
||||
import { ref, inject } from "vue"
|
||||
import { useRoute } from "vue-router"
|
||||
import MaForm from "@/components/ma-form/index.vue"
|
||||
import { Message } from "@arco-design/web-vue"
|
||||
|
||||
export default function (updateApiFunc: Function, updateTreeFunc: Function, width = "40%") {
|
||||
const route = useRoute()
|
||||
const project_id = route.query.id // 只能拿ID其他是null
|
||||
const rightViewRef = inject("rightViewRef")
|
||||
// has returns
|
||||
const visible = ref(false)
|
||||
const formRef = ref<InstanceType<typeof MaForm> | null>(null)
|
||||
const formData = ref<any>({})
|
||||
// 标题
|
||||
const title = ref("")
|
||||
// 异步确认按钮点击
|
||||
const handleBeforeOk = async () => {
|
||||
const isValidated = await formRef.value!.validateForm()
|
||||
if (isValidated) {
|
||||
// 失败
|
||||
return false
|
||||
} else {
|
||||
// 成功 **变化**
|
||||
const res = await updateApiFunc(formData.value.id, { project_id, ...formData.value })
|
||||
updateTreeFunc(res.data, project_id) // 刷新树节点信息
|
||||
!(rightViewRef as any).value.refresh()
|
||||
Message.success("修改成功")
|
||||
}
|
||||
}
|
||||
const modalOptions = {
|
||||
width,
|
||||
draggable: true,
|
||||
"unmount-on-close": true,
|
||||
"ok-text": "保存",
|
||||
"cancel-text": "关闭",
|
||||
"on-before-ok": handleBeforeOk
|
||||
}
|
||||
return { title, formData, formRef, modalOptions, project_id, visible }
|
||||
}
|
||||
@@ -1,28 +1,21 @@
|
||||
import { defineComponent, inject, ref } from "vue"
|
||||
import { defineComponent } from "vue"
|
||||
import { TreeNodeData } from "@arco-design/web-vue"
|
||||
import { useRoute } from "vue-router"
|
||||
import { Message } from "@arco-design/web-vue"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import dutAPI from "@/api/project/dut"
|
||||
import useOptions from "./useOptions"
|
||||
import MaForm from "@/components/ma-form/index.vue"
|
||||
import subFormHooks from "../../projPublicHooks/subFormHooks"
|
||||
|
||||
const DutSubForm = defineComponent({
|
||||
name: "DutSubForm",
|
||||
setup(props, { expose }) {
|
||||
// globals
|
||||
const route = useRoute()
|
||||
const project_id = route.query.id
|
||||
setup(_, { expose }) {
|
||||
// hook variable
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const rightViewRef = inject("rightViewRef")
|
||||
// refs
|
||||
const visible = ref(false)
|
||||
const formRef = ref<InstanceType<typeof MaForm> | null>(null)
|
||||
const formData = ref<any>({})
|
||||
const { title, formData, formRef, modalOptions, project_id, visible } = subFormHooks(
|
||||
dutAPI.update,
|
||||
treeDataStore.updateDutTreeData
|
||||
)
|
||||
// hooks
|
||||
const { options, columnOptions } = useOptions(formRef)
|
||||
// 标题
|
||||
const title = ref("被测件详情")
|
||||
const { options, columnOptions } = useOptions(formRef) // **变化**
|
||||
// 双击打开回调
|
||||
const open = async (nodeData: TreeNodeData) => {
|
||||
// 请求数据
|
||||
@@ -30,43 +23,22 @@ const DutSubForm = defineComponent({
|
||||
const key = nodeData.key
|
||||
// 设置表单名称
|
||||
title.value = nodeData.title!
|
||||
const res = await dutAPI.getDutOne({ project_id, key })
|
||||
const res = await dutAPI.getDutOne({ project_id, key }) // **API变化**
|
||||
// 更新表单
|
||||
formData.value = res.data
|
||||
formData.value.round = key
|
||||
formData.value.round = key // **属性变化**
|
||||
visible.value = true
|
||||
} catch (e) {
|
||||
visible.value = false
|
||||
}
|
||||
}
|
||||
// 异步确认按钮点击
|
||||
const handleBeforeOk = async () => {
|
||||
const isValidated = await formRef.value!.validateForm()
|
||||
if (isValidated) {
|
||||
// 失败
|
||||
return false
|
||||
} else {
|
||||
// 成功
|
||||
const res = await dutAPI.update(formData.value.id, { project_id, ...formData.value })
|
||||
treeDataStore.updateDutTreeData(res.data, project_id) // 刷新树节点信息
|
||||
!(rightViewRef as any).value.refresh()
|
||||
Message.success("修改成功")
|
||||
}
|
||||
}
|
||||
// out use
|
||||
expose({ open })
|
||||
|
||||
// Dom
|
||||
return () => (
|
||||
<a-modal
|
||||
v-model:visible={visible.value}
|
||||
width={"40%"}
|
||||
draggable
|
||||
unmount-on-close
|
||||
ok-text="保存"
|
||||
cancel-text="关闭"
|
||||
on-before-ok={handleBeforeOk}
|
||||
>
|
||||
// 注意v-model:visible是不能放在对象解构的
|
||||
<a-modal {...modalOptions} v-model:visible={visible.value}>
|
||||
{{
|
||||
title: () => <span>[被测件]-{title.value}</span>,
|
||||
default: () => (
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { ref, computed } from "vue"
|
||||
import useCrudRef from "@/views/project/round/hooks/useCrudRef"
|
||||
import tool from "@/utils/tool"
|
||||
import useColumn from "../hooks/useColumn"
|
||||
|
||||
export default function useOptions(formRef: any) {
|
||||
const options = ref({
|
||||
showButtons: false,
|
||||
labelAlign: "center"
|
||||
})
|
||||
const { crudColumns } = useCrudRef(undefined, formRef)
|
||||
const crudColumns = useColumn(formRef)
|
||||
const columnOptions = computed(() => {
|
||||
return tool.renameKeyInArray(crudColumns.value, "commonRules", "rules")
|
||||
})
|
||||
|
||||
@@ -1,91 +1,18 @@
|
||||
import { ref } from "vue"
|
||||
import dutApi from "@/api/project/dut"
|
||||
import { useRoute } from "vue-router"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import beiceType from "@/views/project/round/beiceType"
|
||||
/**
|
||||
* 传入组件Ref返回其options和columnOptions
|
||||
* @param crudRef crud组件的Ref,注意不存在传递undefined
|
||||
* @param formRef ma-form组件Ref
|
||||
* @returns
|
||||
*/
|
||||
export default function useCrudRef(crudRef?, formRef?) {
|
||||
// globals
|
||||
|
||||
export default function (crudOrFormRef: any) {
|
||||
// global
|
||||
const route = useRoute()
|
||||
const projectId = ref(route.query.id)
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const roundNumber = (route.query.key as any).split("-")[0]
|
||||
// 计算注释率计算crud/form的数据,判断
|
||||
const calcPercent = () => {
|
||||
if (crudRef) {
|
||||
const formData = crudRef.value.getFormData()
|
||||
const total_line = +formData.black_line + +formData.code_line + +formData.comment_line + +formData.mix_line
|
||||
const comment_total = +formData.comment_line + +formData.mix_line
|
||||
formData.comment_percent = `${(comment_total / total_line).toFixed(2).toString()}%`
|
||||
} else if (formRef) {
|
||||
const formData = formRef.value.getFormData()
|
||||
const { code_line, comment_line, mix_line, black_line } = formData
|
||||
const total_line = +black_line + +code_line + +comment_line + +mix_line
|
||||
const comment_total = +comment_line + +mix_line
|
||||
formData.comment_percent = `${(comment_total / total_line).toFixed(2).toString()}%`
|
||||
}
|
||||
const formData = crudOrFormRef.value.getFormData()
|
||||
const { code_line, comment_line, mix_line, black_line } = formData
|
||||
const total_line = +black_line + +code_line + +comment_line + +mix_line
|
||||
const comment_total = +comment_line + +mix_line
|
||||
formData.comment_percent = `${(comment_total / total_line).toFixed(2).toString()}%`
|
||||
}
|
||||
// refs
|
||||
const crudOptions = ref({
|
||||
api: dutApi.getDutList,
|
||||
add: { show: true, api: dutApi.save, text: "新增被测件" },
|
||||
edit: { show: true, api: dutApi.update, text: "编辑被测件" },
|
||||
delete: { show: true, api: dutApi.delete },
|
||||
// 处理添加后函数
|
||||
beforeOpenAdd: function () {
|
||||
let round_str = parseInt(route.query.key as any) + 1
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident}>第${round_str}轮>被测件-`
|
||||
return true
|
||||
},
|
||||
beforeOpenEdit: function (record) {
|
||||
let round_str = parseInt(route.query.key as any) + 1
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident}>第${round_str}轮>被测件[${record.name}]-`
|
||||
return true
|
||||
},
|
||||
afterAdd: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateDutTreeData(res.data, id)
|
||||
},
|
||||
afterEdit: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateDutTreeData(res.data, id)
|
||||
},
|
||||
afterDelete: (res, record) => {
|
||||
let id = projectId.value
|
||||
if (!record) {
|
||||
record = { key: route.query.key + "-X" }
|
||||
}
|
||||
treeDataStore.updateDutTreeData(record, id)
|
||||
// 清空行选择器
|
||||
crudRef.value.tableRef.selectAll(false)
|
||||
},
|
||||
|
||||
// 新增、编辑、删除均携带下面
|
||||
parameters: {
|
||||
projectId: route.query.id,
|
||||
round: roundNumber
|
||||
},
|
||||
operationWidth: 500,
|
||||
showIndex: false,
|
||||
showTools: false,
|
||||
rowSelection: { showCheckedAll: true },
|
||||
searchColNumber: 3,
|
||||
tablePagination: false,
|
||||
operationColumnWidth: 200, // 操作列宽度
|
||||
operationColumn: true,
|
||||
operationColumnAlign: "center",
|
||||
formOption: {
|
||||
viewType: "drawer",
|
||||
width: 600,
|
||||
mask: false
|
||||
}
|
||||
})
|
||||
|
||||
const crudColumns = ref([
|
||||
{
|
||||
title: "ID",
|
||||
@@ -251,11 +178,9 @@ export default function useCrudRef(crudRef?, formRef?) {
|
||||
placeholder: "计算注释率",
|
||||
hide: true,
|
||||
addDisabled: true,
|
||||
editDisabled: true
|
||||
editDisabled: true,
|
||||
disabled: true
|
||||
}
|
||||
])
|
||||
return {
|
||||
crudOptions,
|
||||
crudColumns
|
||||
}
|
||||
return crudColumns
|
||||
}
|
||||
71
cdTMP/src/views/project/round/hooks/useCrudOptions.ts
Normal file
71
cdTMP/src/views/project/round/hooks/useCrudOptions.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import MaCrud from "@/components/ma-crud/index.vue"
|
||||
import { type Ref, ref } from "vue"
|
||||
import dutApi from "@/api/project/dut"
|
||||
import { useRoute } from "vue-router"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
/**
|
||||
* Dut被测件的crud选项
|
||||
*/
|
||||
export default function (crudRef: Ref<InstanceType<typeof MaCrud>>) {
|
||||
// globals
|
||||
const route = useRoute()
|
||||
const projectId = ref(route.query.id)
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const roundNumber = (route.query.key as any).split("-")[0]
|
||||
// refs
|
||||
const crudOptions = {
|
||||
api: dutApi.getDutList,
|
||||
add: { show: true, api: dutApi.save, text: "新增被测件" },
|
||||
edit: { show: true, api: dutApi.update, text: "编辑被测件" },
|
||||
delete: { show: true, api: dutApi.delete },
|
||||
// 处理添加后函数
|
||||
beforeOpenAdd: function () {
|
||||
let round_str = parseInt(route.query.key as any) + 1
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident}>第${round_str}轮>被测件-`
|
||||
return true
|
||||
},
|
||||
beforeOpenEdit: function (record) {
|
||||
let round_str = parseInt(route.query.key as any) + 1
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident}>第${round_str}轮>被测件[${record.name}]-`
|
||||
return true
|
||||
},
|
||||
afterAdd: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateDutTreeData(res.data, id)
|
||||
},
|
||||
afterEdit: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateDutTreeData(res.data, id)
|
||||
},
|
||||
afterDelete: (res, record) => {
|
||||
let id = projectId.value
|
||||
if (!record) {
|
||||
record = { key: route.query.key + "-X" }
|
||||
}
|
||||
treeDataStore.updateDutTreeData(record, id)
|
||||
// 清空行选择器
|
||||
crudRef.value.tableRef.selectAll(false)
|
||||
},
|
||||
|
||||
// 新增、编辑、删除均携带下面
|
||||
parameters: {
|
||||
projectId: route.query.id,
|
||||
round: roundNumber
|
||||
},
|
||||
operationWidth: 500,
|
||||
showIndex: false,
|
||||
showTools: false,
|
||||
rowSelection: { showCheckedAll: true },
|
||||
searchColNumber: 3,
|
||||
tablePagination: false,
|
||||
operationColumnWidth: 200, // 操作列宽度
|
||||
operationColumn: true,
|
||||
operationColumnAlign: "center",
|
||||
formOption: {
|
||||
viewType: "drawer",
|
||||
width: 600,
|
||||
mask: false
|
||||
}
|
||||
}
|
||||
return crudOptions
|
||||
}
|
||||
@@ -12,10 +12,12 @@
|
||||
|
||||
<script setup lang="jsx">
|
||||
import { ref } from "vue"
|
||||
import useCrudRef from "@/views/project/round/hooks/useCrudRef"
|
||||
import useCrudOptions from "@/views/project/round/hooks/useCrudOptions"
|
||||
import useColumn from "@/views/project/round/hooks/useColumn"
|
||||
const crudRef = ref()
|
||||
// crud组件
|
||||
const { crudOptions, crudColumns } = useCrudRef(crudRef)
|
||||
const crudOptions = useCrudOptions(crudRef)
|
||||
const crudColumns = useColumn(crudRef)
|
||||
|
||||
const refreshCrudTable = () => {
|
||||
crudRef.value.refresh()
|
||||
|
||||
69
cdTMP/src/views/project/testDemand/CaseSubForm/index.tsx
Normal file
69
cdTMP/src/views/project/testDemand/CaseSubForm/index.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { defineComponent } from "vue"
|
||||
import { Message, TreeNodeData } from "@arco-design/web-vue"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import caseApi from "@/api/project/case"
|
||||
import useOptions from "./useOptions"
|
||||
import subFormHooks from "@/views/project/projPublicHooks/subFormHooks"
|
||||
|
||||
const CaseSubForm = defineComponent({
|
||||
name: "DemandSubFormForm",
|
||||
setup(_, { expose }) {
|
||||
// hook variable
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const { title, formData, formRef, modalOptions, project_id, visible } = subFormHooks(
|
||||
caseApi.update,
|
||||
treeDataStore.updateCaseTreeData,
|
||||
"80%"
|
||||
)
|
||||
// hooks
|
||||
const { options, columnOptions } = useOptions(formRef) // **option里面变化**
|
||||
// 双击打开回调
|
||||
const open = async (nodeData: TreeNodeData) => {
|
||||
// 请求数据
|
||||
try {
|
||||
const key = nodeData.key as string
|
||||
// 设置表单名称
|
||||
title.value = nodeData.title!
|
||||
// 注意这里因为case接口原因,这里需要projectId!!!!!!!!!!!!!!!
|
||||
const res = await caseApi.getCaseOne({ projectId: project_id, key }) // **API变化**
|
||||
// 更新表单
|
||||
formData.value = res.data // **属性变化**
|
||||
formData.value.round = key.split("-")[0]
|
||||
formData.value.dut = key.split("-")[1]
|
||||
formData.value.designDemand = key.split("-")[2]
|
||||
formData.value.testDemand = key.split("-")[3]
|
||||
visible.value = true
|
||||
} catch (e) {
|
||||
Message.error("数据未获取到,请联系开发者")
|
||||
visible.value = false
|
||||
}
|
||||
}
|
||||
// out use
|
||||
expose({ open })
|
||||
|
||||
// Dom
|
||||
return () => (
|
||||
// 注意v-model:visible是不能放在对象解构的
|
||||
<a-modal {...modalOptions} v-model:visible={visible.value}>
|
||||
{{
|
||||
title: () => <span>[设计需求]-{title.value}</span>,
|
||||
default: () => (
|
||||
<ma-form
|
||||
ref={formRef}
|
||||
v-model={formData.value}
|
||||
options={options.value}
|
||||
columns={columnOptions.value}
|
||||
></ma-form>
|
||||
)
|
||||
}}
|
||||
</a-modal>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default CaseSubForm
|
||||
// 组件类型导出
|
||||
type CaseSubFormOrigin = InstanceType<typeof CaseSubForm>
|
||||
export interface CaseSubFormInstance extends CaseSubFormOrigin {
|
||||
open(nodeData: TreeNodeData): void
|
||||
}
|
||||
16
cdTMP/src/views/project/testDemand/CaseSubForm/useOptions.ts
Normal file
16
cdTMP/src/views/project/testDemand/CaseSubForm/useOptions.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { ref, computed } from "vue"
|
||||
import tool from "@/utils/tool"
|
||||
import useColumn from "../hooks/useColumn"
|
||||
|
||||
// Case用例在这里设置不同ma-form选项
|
||||
export default function useOptions(formRef: any) {
|
||||
const options = ref({
|
||||
showButtons: false,
|
||||
labelAlign: "center"
|
||||
})
|
||||
const crudColumns = useColumn(formRef)
|
||||
const columnOptions = computed(() => {
|
||||
return tool.renameKeyInArray(crudColumns.value, "commonRules", "rules")
|
||||
})
|
||||
return { options, columnOptions }
|
||||
}
|
||||
213
cdTMP/src/views/project/testDemand/hooks/useColumn.tsx
Normal file
213
cdTMP/src/views/project/testDemand/hooks/useColumn.tsx
Normal file
@@ -0,0 +1,213 @@
|
||||
import { ref } from "vue"
|
||||
import { useRoute } from "vue-router"
|
||||
|
||||
export default function (crudOrFormRef: any, problemFormRef?: any) {
|
||||
const title = ref("问题单表单")
|
||||
const route = useRoute()
|
||||
const crudColumns = ref([
|
||||
{
|
||||
title: "ID",
|
||||
width: 60,
|
||||
align: "center",
|
||||
hide: true,
|
||||
dataIndex: "id",
|
||||
fixed: "left",
|
||||
display: false
|
||||
},
|
||||
{
|
||||
title: "用例标识",
|
||||
dataIndex: "ident",
|
||||
sortable: { sortDirections: ["ascend"] },
|
||||
width: 180,
|
||||
align: "center",
|
||||
addDisabled: true,
|
||||
addDefaultValue: "用例标识自动生成,结构为YL_IO_XXXX_001",
|
||||
editDefaultValue: "用例标识自动生成,结构为YL_IO_XXXX_001",
|
||||
editDisabled: true,
|
||||
search: true,
|
||||
validateTrigger: "blur"
|
||||
},
|
||||
{
|
||||
title: "名称",
|
||||
dataIndex: "name",
|
||||
align: "center",
|
||||
search: true,
|
||||
commonRules: [{ required: true, message: "名称是必填" }],
|
||||
validateTrigger: "blur"
|
||||
},
|
||||
{
|
||||
title: "是否通过",
|
||||
align: "center",
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
customRender: ({ record }) => {
|
||||
let passCount = 0
|
||||
let failCount = 0
|
||||
let stepCount = record.testStep.length
|
||||
record.testStep.forEach((item) => {
|
||||
if (item.passed === "1") {
|
||||
passCount++
|
||||
} else if (item.passed === "2") {
|
||||
failCount++
|
||||
}
|
||||
})
|
||||
if (failCount > 0) {
|
||||
return (
|
||||
<a-tag bordered color="red">
|
||||
未通过
|
||||
</a-tag>
|
||||
)
|
||||
} else {
|
||||
if (passCount === stepCount) {
|
||||
return (
|
||||
<a-tag bordered color="green">
|
||||
已通过
|
||||
</a-tag>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<a-tag bordered color="orange">
|
||||
包含未执行
|
||||
</a-tag>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "设计人员",
|
||||
width: 80,
|
||||
dataIndex: "designPerson",
|
||||
align: "center",
|
||||
hide: true,
|
||||
search: true,
|
||||
formType: "select",
|
||||
dict: {
|
||||
url: "system/user/list",
|
||||
params: { project_id: route.query.id },
|
||||
translation: true,
|
||||
props: { label: "name", value: "name" }
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "执行人员",
|
||||
dataIndex: "testPerson",
|
||||
width: 120,
|
||||
align: "center",
|
||||
search: true,
|
||||
formType: "select",
|
||||
dict: {
|
||||
url: "system/user/list",
|
||||
params: { project_id: route.query.id },
|
||||
translation: true,
|
||||
props: { label: "name", value: "name" }
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "审核人员",
|
||||
dataIndex: "monitorPerson",
|
||||
width: 80,
|
||||
align: "center",
|
||||
hide: true,
|
||||
formType: "select",
|
||||
dict: {
|
||||
url: "system/user/list",
|
||||
params: { project_id: route.query.id },
|
||||
translation: true,
|
||||
props: { label: "name", value: "name" }
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "用例综述",
|
||||
align: "center",
|
||||
dataIndex: "summarize",
|
||||
hide: true,
|
||||
search: true,
|
||||
addDefaultValue: ""
|
||||
},
|
||||
{
|
||||
title: "用例初始化",
|
||||
dataIndex: "initialization",
|
||||
hide: true,
|
||||
addDefaultValue: "软件正常启动,正常登录进软件"
|
||||
},
|
||||
{
|
||||
title: "前提和约束",
|
||||
dataIndex: "premise",
|
||||
hide: true,
|
||||
addDefaultValue: "软件正常启动,各界面显示工作正常"
|
||||
},
|
||||
{
|
||||
title: "执行时间",
|
||||
dataIndex: "exe_time",
|
||||
hide: true,
|
||||
formType: "date"
|
||||
},
|
||||
{
|
||||
title: "测试步骤",
|
||||
dataIndex: "testStep",
|
||||
hide: true,
|
||||
addDefaultValue: [
|
||||
{
|
||||
operation: "",
|
||||
expect: "",
|
||||
result: "",
|
||||
passed: "3"
|
||||
}
|
||||
],
|
||||
formType: "children-form",
|
||||
type: "group",
|
||||
formList: [
|
||||
{
|
||||
title: "操作",
|
||||
dataIndex: "operation",
|
||||
formType: "editor",
|
||||
height: 180
|
||||
},
|
||||
{
|
||||
title: "预期",
|
||||
placeholder: "请输入预期结果",
|
||||
dataIndex: "expect"
|
||||
},
|
||||
{
|
||||
title: "结果",
|
||||
dataIndex: "result",
|
||||
formType: "editor",
|
||||
height: 180
|
||||
},
|
||||
{
|
||||
title: "是否通过",
|
||||
dataIndex: "passed",
|
||||
formType: "radio",
|
||||
dict: { name: "passType", props: { label: "title", value: "key" } },
|
||||
commonRules: [{ required: true, message: "是否通过必填" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "关联问题",
|
||||
dataIndex: "problem",
|
||||
width: 150,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
align: "center",
|
||||
display: false,
|
||||
customRender: ({ record }) => {
|
||||
if (record.problem) {
|
||||
return (
|
||||
<a-link
|
||||
onClick={() => {
|
||||
title.value = `PT_${route.query.ident}_${record.problem.ident.padStart(3, 0)}`
|
||||
problemFormRef.value.open(record.problem)
|
||||
}}
|
||||
>{`PT_${route.query.ident}_${record.problem.ident.padStart(3, 0)}`}</a-link>
|
||||
)
|
||||
} else {
|
||||
return "无问题单"
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
return crudColumns
|
||||
}
|
||||
159
cdTMP/src/views/project/testDemand/hooks/useCrudOpMore.ts
Normal file
159
cdTMP/src/views/project/testDemand/hooks/useCrudOpMore.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
import { ref, getCurrentInstance, type Ref } from "vue"
|
||||
import MaCrud from "@/components/ma-crud/index.vue"
|
||||
import { useRoute } from "vue-router"
|
||||
import caseApi from "@/api/project/case"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import { isEqual, cloneDeep } from "lodash-es"
|
||||
/**
|
||||
* Dut被测件的crud选项
|
||||
*/
|
||||
export default function (crudRef: Ref<InstanceType<typeof MaCrud>>) {
|
||||
// globals
|
||||
const route = useRoute() as any
|
||||
const projectId = ref(route.query.id)
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const roundNumber = route.query.key.split("-")[0]
|
||||
const dutNumber = route.query.key.split("-")[1]
|
||||
const designDemandNumber = route.query.key.split("-")[2]
|
||||
const testDemandNumber = route.query.key.split("-")[3]
|
||||
// 辅助
|
||||
const app = getCurrentInstance()!.appContext.config.globalProperties
|
||||
let beforeFormStep = undefined
|
||||
// 注意只保留测试步骤!!!
|
||||
const handleBeforeCancel = () => {
|
||||
if (!beforeFormStep) {
|
||||
return
|
||||
}
|
||||
crudRef.value.getFormData().testStep
|
||||
const iuEqualValue = isEqual(crudRef.value.getFormData().testStep, beforeFormStep)
|
||||
!iuEqualValue &&
|
||||
app.$modal.confirm({
|
||||
title: "测试项步骤内容你已改动,是否保留您编写的测试项/测试用例步骤数据?",
|
||||
content: "",
|
||||
okText: "保留",
|
||||
cancelText: "恢复原数据",
|
||||
simple: true,
|
||||
onOk: () => null,
|
||||
onCancel: () => {
|
||||
crudRef.value.refresh()
|
||||
}
|
||||
})
|
||||
}
|
||||
// refs
|
||||
const crudOptions = ref({
|
||||
api: caseApi.getCaseList,
|
||||
add: { show: true, api: caseApi.save, text: "新增用例" },
|
||||
edit: { show: true, api: caseApi.update, text: "修改用例" },
|
||||
delete: { show: true, api: caseApi.delete },
|
||||
operationColumnAlign: "center",
|
||||
isDbClickEdit: true, // 关闭双击编辑
|
||||
// 处理新增删除后树状图显示
|
||||
beforeOpenAdd: function () {
|
||||
// 1.新增则将form的content数据变为undifined以便判断
|
||||
beforeFormStep = undefined
|
||||
// 2.标识处理
|
||||
let key_split = route.query.key.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let design_key = key_split[2]
|
||||
let test_key = key_split[3]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} >
|
||||
${(td[round_key] as any).title} > ${(td[round_key] as any).children[dut_key].title} >
|
||||
${(td[round_key] as any).children[dut_key].children[design_key].title} >
|
||||
${(td[round_key] as any).children[dut_key].children[design_key].children[test_key].title} > 用例-`
|
||||
return true
|
||||
},
|
||||
beforeOpenEdit: function (record) {
|
||||
// 1.储存打开前form的content数据到ref中,以便后续比较
|
||||
beforeFormStep = cloneDeep(record.testStep)
|
||||
// 2.标识处理
|
||||
let key_split = route.query.key.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let design_key = key_split[2]
|
||||
let test_key = key_split[3]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} >
|
||||
${(td[round_key] as any).title} > ${(td[round_key] as any).children[dut_key].title} >
|
||||
${(td[round_key] as any).children[dut_key].children[design_key].title} >
|
||||
${(td[round_key] as any).children[dut_key].children[design_key].children[test_key].title}
|
||||
>用例[${record.name}]-`
|
||||
return true
|
||||
},
|
||||
afterAdd: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateCaseTreeData(res.data, id)
|
||||
},
|
||||
afterEdit: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateCaseTreeData(res.data, id)
|
||||
},
|
||||
afterDelete: (res, record) => {
|
||||
let id = projectId.value
|
||||
if (!record) {
|
||||
record = { key: route.query.key + "-X" }
|
||||
}
|
||||
treeDataStore.updateCaseTreeData(record, id)
|
||||
// 被删除还是在选择里面
|
||||
crudRef.value.tableRef.selectAll(false)
|
||||
},
|
||||
parameters: {
|
||||
projectId: route.query.id,
|
||||
round: roundNumber,
|
||||
dut: dutNumber,
|
||||
designDemand: designDemandNumber,
|
||||
testDemand: testDemandNumber
|
||||
},
|
||||
showIndex: false,
|
||||
showTools: false,
|
||||
rowSelection: { showCheckedAll: true },
|
||||
searchColNumber: 3,
|
||||
tablePagination: false,
|
||||
operationColumnWidth: 180,
|
||||
operationColumn: true,
|
||||
formOption: {
|
||||
width: 1200,
|
||||
layout: [
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{ span: 12, formList: [{ dataIndex: "ident" }] },
|
||||
{ span: 12, formList: [{ dataIndex: "name" }] }
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "card",
|
||||
customClass: ["ml-10", "mb-3", "py-0", "px-0"],
|
||||
title: "人员信息",
|
||||
formList: [
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{ span: 8, formList: [{ dataIndex: "designPerson" }] },
|
||||
{ span: 8, formList: [{ dataIndex: "testPerson" }] },
|
||||
{ span: 8, formList: [{ dataIndex: "monitorPerson" }] }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [{ span: 24, formList: [{ dataIndex: "summarize" }] }]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [{ span: 24, formList: [{ dataIndex: "initialization" }] }]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{ span: 12, formList: [{ dataIndex: "premise" }] },
|
||||
{ span: 12, formList: [{ dataIndex: "exe_time" }] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
return { handleBeforeCancel, crudOptions }
|
||||
}
|
||||
@@ -13,369 +13,22 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import { ref, getCurrentInstance } from "vue"
|
||||
import { useRoute } from "vue-router"
|
||||
import caseApi from "@/api/project/case"
|
||||
import { useTreeDataStore } from "@/store"
|
||||
import { ref } from "vue"
|
||||
import ProblemForm from "@/views/project/case/components/ProblemForm.vue"
|
||||
import { isEqual, cloneDeep } from "lodash-es"
|
||||
import useCrudOpMore from "./hooks/useCrudOpMore"
|
||||
import useColumn from "./hooks/useColumn"
|
||||
const problemFormRef = ref(null)
|
||||
const title = ref("问题单表单")
|
||||
const treeDataStore = useTreeDataStore()
|
||||
const route = useRoute()
|
||||
const roundNumber = route.query.key.split("-")[0]
|
||||
const dutNumber = route.query.key.split("-")[1]
|
||||
const designDemandNumber = route.query.key.split("-")[2]
|
||||
const testDemandNumber = route.query.key.split("-")[3]
|
||||
const crudRef = ref()
|
||||
const projectId = ref(route.query.id)
|
||||
// 标识显示字段-用例比较特殊让后端返回了“FT”字样,因为FT是在测试项里面标识的
|
||||
// 标识重新定义
|
||||
const showType = (record) => {
|
||||
let key_string = parseInt(record.key.substring(record.key.lastIndexOf("-") + 1)) + 1
|
||||
return "YL-" + record.testType + "-" + record.ident + "-" + key_string.toString().padStart(3, "0")
|
||||
}
|
||||
|
||||
// crud设置以及是否保留step数据事件函数
|
||||
const app = getCurrentInstance().appContext.config.globalProperties
|
||||
let beforeFormStep = undefined
|
||||
// 注意只保留测试步骤!!!
|
||||
const handleBeforeCancel = () => {
|
||||
if (!beforeFormStep) {
|
||||
return
|
||||
}
|
||||
crudRef.value.getFormData().testStep
|
||||
const iuEqualValue = isEqual(crudRef.value.getFormData().testStep, beforeFormStep)
|
||||
!iuEqualValue &&
|
||||
app.$modal.confirm({
|
||||
title: "测试项步骤内容你已改动,是否保留您编写的测试项/测试用例步骤数据?",
|
||||
content: "",
|
||||
okText: "保留",
|
||||
cancelText: "恢复原数据",
|
||||
simple: true,
|
||||
onOk: () => null,
|
||||
onCancel: () => {
|
||||
crudRef.value.refresh()
|
||||
}
|
||||
})
|
||||
}
|
||||
const crudOptions = ref({
|
||||
api: caseApi.getCaseList,
|
||||
add: { show: true, api: caseApi.save, text: "新增用例" },
|
||||
edit: { show: true, api: caseApi.update, text: "修改用例" },
|
||||
delete: { show: true, api: caseApi.delete },
|
||||
operationColumnAlign: "center",
|
||||
isDbClickEdit: true, // 关闭双击编辑
|
||||
// 处理新增删除后树状图显示
|
||||
beforeOpenAdd: function () {
|
||||
// 1.新增则将form的content数据变为undifined以便判断
|
||||
beforeFormStep = undefined
|
||||
// 2.标识处理
|
||||
let key_split = route.query.key.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let design_key = key_split[2]
|
||||
let test_key = key_split[3]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} >
|
||||
${td[round_key].title} > ${td[round_key].children[dut_key].title} >
|
||||
${td[round_key].children[dut_key].children[design_key].title} >
|
||||
${td[round_key].children[dut_key].children[design_key].children[test_key].title} > 用例-`
|
||||
return true
|
||||
},
|
||||
beforeOpenEdit: function (record) {
|
||||
// 1.储存打开前form的content数据到ref中,以便后续比较
|
||||
beforeFormStep = cloneDeep(record.testStep)
|
||||
// 2.标识处理
|
||||
let key_split = route.query.key.split("-")
|
||||
let round_key = key_split[0]
|
||||
let dut_key = key_split[1]
|
||||
let design_key = key_split[2]
|
||||
let test_key = key_split[3]
|
||||
let td = treeDataStore.treeData
|
||||
crudRef.value.crudFormRef.actionTitle = `${route.query.ident} >
|
||||
${td[round_key].title} > ${td[round_key].children[dut_key].title} >
|
||||
${td[round_key].children[dut_key].children[design_key].title} >
|
||||
${td[round_key].children[dut_key].children[design_key].children[test_key].title}
|
||||
>用例[${record.name}]-`
|
||||
return true
|
||||
},
|
||||
afterAdd: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateCaseTreeData(res.data, id)
|
||||
},
|
||||
afterEdit: (res) => {
|
||||
let id = projectId.value
|
||||
treeDataStore.updateCaseTreeData(res.data, id)
|
||||
},
|
||||
afterDelete: (res, record) => {
|
||||
let id = projectId.value
|
||||
if (!record) {
|
||||
record = { key: route.query.key + "-X" }
|
||||
}
|
||||
treeDataStore.updateCaseTreeData(record, id)
|
||||
// 被删除还是在选择里面
|
||||
crudRef.value.tableRef.selectAll(false)
|
||||
},
|
||||
parameters: {
|
||||
projectId: route.query.id,
|
||||
round: roundNumber,
|
||||
dut: dutNumber,
|
||||
designDemand: designDemandNumber,
|
||||
testDemand: testDemandNumber
|
||||
},
|
||||
showIndex: false,
|
||||
showTools: false,
|
||||
rowSelection: { showCheckedAll: true },
|
||||
searchColNumber: 3,
|
||||
tablePagination: false,
|
||||
operationColumnWidth: 180,
|
||||
operationColumn: true,
|
||||
formOption: {
|
||||
width: 1200,
|
||||
layout: [
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{ span: 12, formList: [{ dataIndex: "ident" }] },
|
||||
{ span: 12, formList: [{ dataIndex: "name" }] }
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "card",
|
||||
customClass: ["ml-10", "mb-3", "py-0", "px-0"],
|
||||
title: "人员信息",
|
||||
formList: [
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{ span: 8, formList: [{ dataIndex: "designPerson" }] },
|
||||
{ span: 8, formList: [{ dataIndex: "testPerson" }] },
|
||||
{ span: 8, formList: [{ dataIndex: "monitorPerson" }] }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [{ span: 24, formList: [{ dataIndex: "summarize" }] }]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [{ span: 24, formList: [{ dataIndex: "initialization" }] }]
|
||||
},
|
||||
{
|
||||
formType: "grid",
|
||||
cols: [
|
||||
{ span: 12, formList: [{ dataIndex: "premise" }] },
|
||||
{ span: 12, formList: [{ dataIndex: "exe_time" }] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
const crudColumns = ref([
|
||||
{
|
||||
title: "ID",
|
||||
width: 60,
|
||||
align: "center",
|
||||
hide: true,
|
||||
dataIndex: "id",
|
||||
fixed: "left"
|
||||
},
|
||||
{
|
||||
title: "用例标识",
|
||||
dataIndex: "ident",
|
||||
sortable: { sortDirections: ["ascend"] },
|
||||
width: 180,
|
||||
align: "center",
|
||||
addDisabled: true,
|
||||
addDefaultValue: "用例标识自动生成,结构为YL_IO_XXXX_001",
|
||||
editDefaultValue: "用例标识自动生成,结构为YL_IO_XXXX_001",
|
||||
editDisabled: true,
|
||||
search: true,
|
||||
validateTrigger: "blur"
|
||||
},
|
||||
{
|
||||
title: "名称",
|
||||
dataIndex: "name",
|
||||
align: "center",
|
||||
search: true,
|
||||
commonRules: [{ required: true, message: "名称是必填" }],
|
||||
validateTrigger: "blur"
|
||||
},
|
||||
{
|
||||
title: "是否通过",
|
||||
align: "center",
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
customRender: ({ record }) => {
|
||||
let passCount = 0
|
||||
let failCount = 0
|
||||
let stepCount = record.testStep.length
|
||||
record.testStep.forEach((item) => {
|
||||
if (item.passed === "1") {
|
||||
passCount++
|
||||
} else if (item.passed === "2") {
|
||||
failCount++
|
||||
}
|
||||
})
|
||||
if (failCount > 0) {
|
||||
return (
|
||||
<a-tag bordered color="red">
|
||||
未通过
|
||||
</a-tag>
|
||||
)
|
||||
} else {
|
||||
if (passCount === stepCount) {
|
||||
return (
|
||||
<a-tag bordered color="green">
|
||||
已通过
|
||||
</a-tag>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<a-tag bordered color="orange">
|
||||
包含未执行
|
||||
</a-tag>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "设计人员",
|
||||
width: 80,
|
||||
dataIndex: "designPerson",
|
||||
align: "center",
|
||||
hide: true,
|
||||
search: true,
|
||||
formType: "select",
|
||||
dict: {
|
||||
url: "system/user/list",
|
||||
params: { project_id: route.query.id },
|
||||
translation: true,
|
||||
props: { label: "name", value: "name" }
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "执行人员",
|
||||
dataIndex: "testPerson",
|
||||
width: 120,
|
||||
align: "center",
|
||||
search: true,
|
||||
formType: "select",
|
||||
dict: {
|
||||
url: "system/user/list",
|
||||
params: { project_id: route.query.id },
|
||||
translation: true,
|
||||
props: { label: "name", value: "name" }
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "审核人员",
|
||||
dataIndex: "monitorPerson",
|
||||
width: 80,
|
||||
align: "center",
|
||||
hide: true,
|
||||
formType: "select",
|
||||
dict: {
|
||||
url: "system/user/list",
|
||||
params: { project_id: route.query.id },
|
||||
translation: true,
|
||||
props: { label: "name", value: "name" }
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "用例综述",
|
||||
align: "center",
|
||||
dataIndex: "summarize",
|
||||
hide: true,
|
||||
search: true,
|
||||
addDefaultValue: ""
|
||||
},
|
||||
{
|
||||
title: "用例初始化",
|
||||
dataIndex: "initialization",
|
||||
hide: true,
|
||||
addDefaultValue: "软件正常启动,正常登录进软件"
|
||||
},
|
||||
{
|
||||
title: "前提和约束",
|
||||
dataIndex: "premise",
|
||||
hide: true,
|
||||
addDefaultValue: "软件正常启动,各界面显示工作正常"
|
||||
},
|
||||
{
|
||||
title: "执行时间",
|
||||
dataIndex: "exe_time",
|
||||
hide: true,
|
||||
formType: "date"
|
||||
},
|
||||
{
|
||||
title: "测试步骤",
|
||||
dataIndex: "testStep",
|
||||
hide: true,
|
||||
addDefaultValue: [
|
||||
{
|
||||
operation: "",
|
||||
expect: "",
|
||||
result: "",
|
||||
passed: "3"
|
||||
}
|
||||
],
|
||||
formType: "children-form",
|
||||
type: "group",
|
||||
formList: [
|
||||
{
|
||||
title: "操作",
|
||||
dataIndex: "operation",
|
||||
formType: "editor",
|
||||
height: 180
|
||||
},
|
||||
{
|
||||
title: "预期",
|
||||
placeholder: "请输入预期结果",
|
||||
dataIndex: "expect"
|
||||
},
|
||||
{
|
||||
title: "结果",
|
||||
dataIndex: "result",
|
||||
formType: "editor",
|
||||
height: 180
|
||||
},
|
||||
{
|
||||
title: "是否通过",
|
||||
dataIndex: "passed",
|
||||
formType: "radio",
|
||||
dict: { name: "passType", props: { label: "title", value: "key" } },
|
||||
commonRules: [{ required: true, message: "是否通过必填" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "关联问题",
|
||||
dataIndex: "problem",
|
||||
width: 150,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
align: "center",
|
||||
customRender: ({ record }) => {
|
||||
if (record.problem) {
|
||||
return (
|
||||
<a-link
|
||||
onClick={() => {
|
||||
title.value = `PT_${route.query.ident}_${record.problem.ident.padStart(3, 0)}`
|
||||
problemFormRef.value.open(record.problem)
|
||||
}}
|
||||
>{`PT_${route.query.ident}_${record.problem.ident.padStart(3, 0)}`}</a-link>
|
||||
)
|
||||
} else {
|
||||
return "无问题单"
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
const { handleBeforeCancel, crudOptions } = useCrudOpMore(crudRef)
|
||||
const crudColumns = useColumn(crudRef, problemFormRef)
|
||||
|
||||
// 暴露刷新表格方法给外部
|
||||
const refreshCrudTable = () => {
|
||||
crudRef.value.refresh()
|
||||
|
||||
Reference in New Issue
Block a user