@@ -107,6 +109,8 @@ import verifyCode from "@cps/ma-verifyCode/index.vue"
import { useUserStore } from "@/store"
import { useRouter, useRoute } from "vue-router"
import userApi from "@/api/system/user"
+// 导入背景ui组件
+import ParticlesBg from "@/components/ui/particles-bg/ParticlesBg.vue"
const router = useRouter()
const userStore = useUserStore()
// 绑定登录form的数据
@@ -157,7 +161,6 @@ const handleSubmit = async ({ values, errors }) => {
width: 100%;
height: 100%;
background-size: cover;
- background-image: url("@/assets/BingWallpaper.jpg");
}
.bg-backdrop-layout {
top: 0;
@@ -176,13 +179,14 @@ const handleSubmit = async ({ values, errors }) => {
z-index: 3;
.login-width {
max-width: 950px;
- background: #fff;
padding: 10px;
height: 500px;
position: relative;
top: 50%;
margin-top: -255px;
border-radius: var(--border-radius-small);
+ box-shadow: rgba(0, 0, 0, 0.25) 0px 14px 28px, rgba(0, 0, 0, 0.22) 0px 10px 10px;
+ backdrop-filter: blur(3px);
}
.left-panel {
diff --git a/cdTMP/src/views/project/design-demand/DemandSubForm/useOptions.ts b/cdTMP/src/views/project/design-demand/DemandSubForm/useOptions.ts
index c899cac..63efa4b 100644
--- a/cdTMP/src/views/project/design-demand/DemandSubForm/useOptions.ts
+++ b/cdTMP/src/views/project/design-demand/DemandSubForm/useOptions.ts
@@ -10,7 +10,44 @@ export default function useOptions(formRef: any) {
})
const crudColumns = useColumn(formRef)
const columnOptions = computed(() => {
- return tool.renameKeyInArray(crudColumns.value, "commonRules", "rules")
+ const transformColumns = tool.renameKeyInArray(crudColumns.value, "commonRules", "rules")
+ // 针对测试项的布局优化
+ // 取出所有字段
+ const identColumn = transformColumns.find((item: any) => item.dataIndex === "ident")
+ const nameColumn = transformColumns.find((item: any) => item.dataIndex === "name")
+ const priorityColumn = transformColumns.find((item: any) => item.dataIndex === "priority")
+ const testTypeColumn = transformColumns.find((item: any) => item.dataIndex === "testType")
+ const testMethodColumn = transformColumns.find((item: any) => item.dataIndex === "testMethod")
+ // 组装表单布局
+ const identAndNameColumn = {
+ formType: "grid",
+ cols: [
+ { span: 12, formList: [identColumn] },
+ { span: 12, formList: [nameColumn] }
+ ]
+ }
+ const priorityColumnNew = {
+ formType: "grid",
+ cols: [{ span: 24, formList: [priorityColumn] }]
+ }
+ const testTypeAndMethodColumn = {
+ formType: "grid",
+ cols: [
+ { span: 12, formList: [testTypeColumn] },
+ { span: 12, formList: [testMethodColumn] }
+ ]
+ }
+ // 取除原数组里面的内容
+ const newColumnsArray = transformColumns.filter(
+ (it: any) =>
+ it.dataIndex !== "ident" &&
+ it.dataIndex !== "name" &&
+ it.dataIndex !== "priority" &&
+ it.dataIndex !== "testType" &&
+ it.dataIndex !== "testMethod"
+ )
+ newColumnsArray.unshift(identAndNameColumn, priorityColumnNew, testTypeAndMethodColumn)
+ return newColumnsArray
})
return { options, columnOptions }
}
diff --git a/cdTMP/src/views/project/design-demand/hooks/useColumns.ts b/cdTMP/src/views/project/design-demand/hooks/useColumns.ts
index ba89dfa..202ba28 100644
--- a/cdTMP/src/views/project/design-demand/hooks/useColumns.ts
+++ b/cdTMP/src/views/project/design-demand/hooks/useColumns.ts
@@ -25,7 +25,7 @@ export default function (crudOrFormRef: any) {
{
title: "名称",
dataIndex: "name",
- width: 120,
+ width: 150,
align: "center",
search: true,
commonRules: [{ required: true, message: "名称是必填" }],
diff --git a/cdTMP/src/views/project/dut/components/FileInputModal/index.vue b/cdTMP/src/views/project/dut/components/FileInputModal/index.vue
index 11927e3..47b4b68 100644
--- a/cdTMP/src/views/project/dut/components/FileInputModal/index.vue
+++ b/cdTMP/src/views/project/dut/components/FileInputModal/index.vue
@@ -3,7 +3,7 @@
-
上传设计需求.docx:
+
上传需求.docx:
+
+
要解析的章节名称:
+
+
选择需求录入类型:
+
+ {{ item.title }}
+
+
- 请去除需求规格说明文件中不必要的部分再来此处解析,注意:本系统不支持word中emf格式图片,如果使用了visio等图片请在word变为普通图片上传
+ 只能上传.docx,如果有visio图请替换为普通图片上传,请在需求规格说明文档中操作 ->
+ 引用 -> 目录 -> 自定义目录 -> 显示级别改为6以上保存后上传
操作按钮:
@@ -109,104 +119,39 @@
diff --git a/cdTMP/src/views/project/dut/components/FileInputModal/useListOperation.ts b/cdTMP/src/views/project/dut/components/FileInputModal/useListOperation.ts
new file mode 100644
index 0000000..7bae3f4
--- /dev/null
+++ b/cdTMP/src/views/project/dut/components/FileInputModal/useListOperation.ts
@@ -0,0 +1,39 @@
+import { ref } from "vue"
+
+const templateDemandObj = {
+ chapter: "",
+ title: "",
+ ident: "",
+ demandType: "",
+ content: ""
+}
+
+export default function useListOperaton(htmlData: any) {
+ // 数据变化spin显示
+ const loading = ref(false)
+ // 上方按钮:直接在最下新增一条
+ const handleCreateAtLatest = () => {
+ const newDemand = JSON.parse(JSON.stringify(templateDemandObj))
+ htmlData.value.push(newDemand)
+ }
+ // 上方按钮:重置数据,点击页面不卡段
+ const handleResetData = () => {
+ htmlData.value = []
+ }
+ // 点击单条右侧按钮:下方新增 - 深拷贝,并插入到下方
+ const handledownCreate = (index: number) => {
+ const newDemand = JSON.parse(JSON.stringify(templateDemandObj))
+ htmlData.value.splice(index + 1, 0, newDemand)
+ }
+ // 因为a-list限制必须知道当前页码和页容量
+ const currentPage = ref(1)
+ const handlePageChange = (page) => {
+ currentPage.value = page
+ }
+ // 点击单条右侧按钮:删除 - 需要根据currentPage动态觉得因为a-list每页都是这样计算的
+ const handleDelete = (index: number) => {
+ const currentIndex = index + (currentPage.value - 1) * 15
+ htmlData.value.splice(currentIndex, 1)
+ }
+ return { loading, handleCreateAtLatest, handleResetData, handledownCreate, handlePageChange, handleDelete }
+}
diff --git a/cdTMP/src/views/project/dut/components/FileInputModal/useUpload.ts b/cdTMP/src/views/project/dut/components/FileInputModal/useUpload.ts
new file mode 100644
index 0000000..9116172
--- /dev/null
+++ b/cdTMP/src/views/project/dut/components/FileInputModal/useUpload.ts
@@ -0,0 +1,130 @@
+import { ref } from "vue"
+import { Message, Notification } from "@arco-design/web-vue"
+
+const templateDemandObj = {
+ chapter: "",
+ title: "",
+ ident: "",
+ demandType: "",
+ content: ""
+}
+// 判断是否为{"__type__": "image","format": "base64","data": "base64数据"}
+function isImageObject(obj: any) {
+ return (
+ obj !== null &&
+ typeof obj === "object" &&
+ !Array.isArray(obj) &&
+ Object.hasOwn(obj, "__type__") &&
+ Object.hasOwn(obj, "format") &&
+ Object.hasOwn(obj, "data")
+ )
+}
+
+export default function useUpload(htmlData: any) {
+ const parseChapter = ref("") // 定义用户想解析的章节名称
+ const selectValue = ref("1") // 定义选择框
+ const handleUploadSuccess = (fileItem: any) => {
+ const data = fileItem.response.data
+ if (!data.children) {
+ Notification.error({
+ content: "解析失败:请确认上传文件目录级别包含6以上;章节名称正确",
+ duration: 3000,
+ closable: true
+ })
+ parseChapter.value = ""
+ return
+ }
+ // 这里就是解析出东西了
+ const parsedData = getObjFromChapter(data)
+ if (parsedData) {
+ enterDemand(parsedData)
+ }
+ // 上传成功后清空解析章节名称
+ parseChapter.value = ""
+ }
+ const handleUploadError = (fileItem: any) => {
+ console.log(fileItem.response)
+ }
+ const getObjFromChapter = (parseObj: any) => {
+ if (parseObj.title === parseChapter.value) return parseObj
+ if (Array.isArray(parseObj.children) && parseObj.children.length > 0) {
+ for (const child of parseObj.children) {
+ const found = getObjFromChapter(child)
+ if (found) return found // 递归返回obj或null
+ }
+ }
+ return null // 如果都没找到返回null
+ }
+ // 辅助函数:(递归)将parseObj转为templateDemandObj录入,递归录入
+ const enterDemand = (parseObj: any) => {
+ // 下面是录入
+ const demandObj = JSON.parse(JSON.stringify(templateDemandObj))
+ demandObj.chapter = parseObj.number
+ demandObj.title = parseObj.title
+ demandObj.ident = parseObj.ordinal ? parseObj.ordinal : "" // 设计需求标识如果没有则为空
+ demandObj.demandType = selectValue.value
+ // 解析数组,然后添加到内容中
+ const content = formatContentForTinyMCE(JSON.parse(parseObj.content))
+ demandObj.content = content
+ htmlData.value.push(demandObj)
+ // 如果有子对象,则再运行一次即可
+ if (Array.isArray(parseObj.children) && parseObj.children.length > 0) {
+ for (const childObj of parseObj.children) {
+ enterDemand(childObj)
+ }
+ }
+ }
+ // 上面函数的辅助函数:将数组变为HTML给tinymce使用
+ function formatContentForTinyMCE(data: any) {
+ let htmlContent = ""
+ // 处理普通文本行
+ for (const item of data) {
+ // 如果是普通文本
+ if (typeof item === "string") {
+ // 处理表头标记
+ if (item.includes("见表") || item.includes("如表") || item.includes("如下表")) {
+ htmlContent += `
${item.replace(/见表\d+/, "见下表").replace(/见图\d+/, "见下图")}
`
+ } else if (item.includes("见图") || item.includes("如图") || item.includes("如下图")) {
+ htmlContent += `
${item.replace(/见图\d+/, "见下图").replace(/见表\d+/, "见下表")}
`
+ } else if (/表\d+/.test(item)) {
+ htmlContent += ``
+ } else if (/图\d+/.test(item)) {
+ htmlContent += `${item.replace(/图\d+/, "下图")}`
+ } else {
+ htmlContent += `
${item}
`
+ }
+ }
+ // 如果是对象(根据后端逻辑是图片)
+ else if (isImageObject(item)) {
+ // item现在是对象,其data是base64字符串
+ htmlContent += `

`
+ }
+ // 处理表格数据
+ else if (Array.isArray(item)) {
+ htmlContent += '
'
+ // 处理表头
+ const headers = item[0].split("\t")
+ htmlContent += ""
+ for (const header of headers) {
+ htmlContent += `| ${header} | `
+ }
+ htmlContent += "
"
+ // 处理表格内容
+ htmlContent += ""
+ for (let i = 1; i < item.length; i++) {
+ const cells = item[i].split("\t")
+ htmlContent += ""
+ for (const cell of cells) {
+ // 处理单元格内的换行符
+ const formattedCell = cell.replace(/\n/g, "
")
+ htmlContent += `${formattedCell} | `
+ }
+ htmlContent += "
"
+ }
+ htmlContent += "
"
+ }
+ }
+ return htmlContent
+ }
+ return { handleUploadSuccess, handleUploadError, parseChapter, selectValue }
+}
diff --git a/cdTMP/src/views/project/dut/index.vue b/cdTMP/src/views/project/dut/index.vue
index 93cb19e..e4e3735 100644
--- a/cdTMP/src/views/project/dut/index.vue
+++ b/cdTMP/src/views/project/dut/index.vue
@@ -19,7 +19,7 @@
SJ-XX-
-
+
diff --git a/cdTMP/src/views/project/dut/tools/parseHtmlString.js b/cdTMP/src/views/project/dut/tools/parseHtmlString.js
deleted file mode 100644
index 7ad7e11..0000000
--- a/cdTMP/src/views/project/dut/tools/parseHtmlString.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/**
- * 辅助函数,给每个h2增加个自定义属性,用来储存章节号,返回功能/接口h2节点对象【非DOM,有dom属性表示DOM】
- */
-function getNeedH2NodeList(h1h2Node) {
- const h2ObjList = []
- // 首先将h1和h2节点都组成一个数组
- let h1Index = 0,
- h2Index = 0
- h1h2Node.forEach((hDom) => {
- if (hDom.tagName === "H1") {
- // 找到h1,那么其index+1
- h1Index += 1
- h2Index = 0
- } else if (hDom.tagName === "H2") {
- // 按顺序找到h2了,
- h2Index += 1
- let h2Obj = {
- chapter: h1Index + "." + h2Index,
- dom: hDom,
- text: hDom.innerText
- }
- h2ObjList.push(h2Obj)
- }
- })
- // 1.~~~~TODO:可以从这里修改识别范围~~~~
- return h2ObjList.filter(
- (item) =>
- item.text.includes("CSCI功能需求") ||
- item.text.includes("CSCI外部接口需求") ||
- item.text.includes("CSCI能力需求")
- )
-}
-
-/**
- * 思路:因为mammoth解析后变为html字符串,使用new DOMParser()转换为DOM进行解析
- * 作用:创建DOMParser()对象,然后解析需求规格说明的html字符串,目前仅支持功能和接口需求
- * 返回:Array[Object[String,String]]
- */
-export function parseHtmlStringByDemandDut(htmlString) {
- const parser = new DOMParser()
- const doc = parser.parseFromString(htmlString, "text/html")
- const h1h2NodeList = doc.querySelectorAll("h1,h2")
- // 这一步得到功能需求、接口需求的h2对象,里面有dom、text、chapter
- const h2ObjArray = getNeedH2NodeList(h1h2NodeList)
- // 这里开始就要获取全部有用信息:
- // 2.遍历全部DOM
- const allArray = Array.from(doc.body.children)
- const demandArray = []
- let h2Index = 0
- let locker = false
- // 3.将H3和H4的索引增加
- let currentH3ele = {
- initChapter: "",
- index: 0,
- title: "",
- ident: "",
- isIn: false
- }
- let currentH4ele = {
- initChapter: "",
- index: 0,
- title: "",
- ident: ""
- }
- let adpterIndex = 0
-
- allArray.forEach((element) => {
- // 2.1.找到h2ObjArray的位置
- if (h2ObjArray[h2Index] && element === h2ObjArray[h2Index].dom) {
- h2Index += 1
- currentH3ele.index = 0
- locker = true
- } else if (element.tagName === "H1" || element.tagName === "H2") {
- locker = false
- } else if (locker && element.tagName !== "H2") {
- // 就是从H3开始需求的
- if (element.tagName === "H3") {
- // 按顺序解析到H3
- currentH3ele.index += 1
- currentH4ele.index = 0
- const splitString = element.innerText.split(/[(())]/)
- currentH3ele.title = splitString[0]
- currentH3ele.ident = splitString[1] ? splitString[1] : ""
- currentH3ele.initChapter = h2ObjArray[h2Index - 1].chapter + "." + currentH3ele.index
- // 将isIn变为true,说明当前解析在这里面
- currentH3ele.isIn = true
- // 段落索引设置0
- adpterIndex = 0
- } else if (element.tagName === "H4") {
- // 按顺序解析到H4
- currentH4ele.index += 1
- const splitString = element.innerText.split(/[(())]/)
- currentH4ele.title = splitString[0]
- currentH4ele.ident = splitString[1] ? splitString[1] : ""
- // 将H3的isIn变为false,说明在H4里面不在H3了
- currentH3ele.isIn = false
- // chapter
- currentH4ele.initChapter = currentH3ele.initChapter + "." + currentH4ele.index
- // 段落索引
- adpterIndex = 0
- } else {
- // 当currentH3ele的title有值的时候开始解析
- if (currentH3ele.title) {
- const demandObj = {
- chapter: "",
- title: "",
- ident: "",
- demandType: "",
- content: ""
- }
- if (currentH3ele.isIn) {
- demandObj.chapter = currentH3ele.initChapter
- demandObj.title = currentH3ele.title
- demandObj.ident = currentH3ele.ident
- demandObj.demandType = demandObj.title.includes("接口") ? "3" : "1"
- } else {
- demandObj.chapter = currentH4ele.initChapter
- demandObj.title = currentH4ele.title
- demandObj.ident = currentH4ele.ident
- demandObj.demandType = demandObj.title.includes("接口") ? "3" : "1"
- }
- // 1.解析table元素
- if (element.tagName === "TABLE") {
- demandObj.content = element.outerHTML
- adpterIndex += 1
- demandObj.ident = demandObj.ident + `-t${adpterIndex}`
- demandArray.push(demandObj)
- }
- // 2.解析p元素-注意排除图片元素
- if (element.tagName === "P" && !element.querySelector("img")) {
- demandObj.content = element.innerText
- adpterIndex += 1
- demandObj.ident = demandObj.ident + `-p${adpterIndex}`
- demandArray.push(demandObj)
- }
- // 3.解析ol和ul元素
- if (element.tagName === "OL" || element.tagName === "UL") {
- demandObj.content = element.innerHTML
- adpterIndex += 1
- demandObj.ident = demandObj.ident + `-u${adpterIndex}`
- demandArray.push(demandObj)
- }
- }
- }
- }
- })
- return demandArray
-}
diff --git a/cdTMP/src/views/project/dut/tools/parser.ts b/cdTMP/src/views/project/dut/tools/parser.ts
deleted file mode 100644
index eb893b3..0000000
--- a/cdTMP/src/views/project/dut/tools/parser.ts
+++ /dev/null
@@ -1,174 +0,0 @@
-// 根据后端定义,不能更改的枚举
-enum DemandType {
- gn = "1",
- xn = "2",
- jk = "3",
- kkx = "4",
- aqx = "5",
- other = "6"
-}
-
-// 数据每一项的结构
-interface DemandObj {
- chapter: string
- title: string
- ident?: string // 如果其标题有()则放入
- demandType: DemandType
- content: string
-}
-
-// 定义h元素对象接口
-interface IHobj {
- level: number // h1 -> 1
- title: string // 标题文字
- ident?: string // 如果有()则放入
- index: number // 该标题的索引,先map的时候不设置后续再排列
- demandType: DemandType
-}
-
-// h元素对象带计算出的章节号的对象
-interface IHobjWithChapter extends IHobj {
- chapter: string
-}
-
-export class HtmlParser {
- domArray: Element[] // 初始化得到一个元素的集合
- hWithChapter: IHobjWithChapter[]
- constructor(htmlText: string) {
- const parser = new DOMParser()
- const doc = parser.parseFromString(htmlText, "text/html")
- this.domArray = Array.from(doc.body.children)
- // 解析domArray将h元素加入
- const HDomArray = this.domArray.filter((domItem) => domItem.tagName.startsWith("H"))
- const storeArray: IHobj[] = []
- HDomArray.forEach((it, i) => {
- !it.textContent && (it.textContent = "")
- // 这里判断是什么类型的设计需求 -> 后续可以添加
- let type: DemandType = DemandType.gn
- if (it.textContent.includes("接口")) {
- type = DemandType.jk
- } else if (it.textContent.includes("性能")) {
- type = DemandType.xn
- } else if (it.textContent.includes("可靠")) {
- type = DemandType.kkx
- } else if (it.textContent.includes("安全")) {
- type = DemandType.aqx
- }
- // 获取章节号
- const level = +it.tagName.slice(1)
- // 1.判断当前的章节级别的前一个级别的level是否一样/小于/大于
- let index = 0
- if (i > 0) {
- // 找上一个标题对象的level
- if (level === storeArray[i - 1].level) {
- index = storeArray[i - 1].index + 1
- } else if (level < storeArray[i - 1].level) {
- // 如果等级小于上一个标题对象,找storeArray里面level一样的长度
- for (let j = storeArray.length - 1; j >= 0; j--) {
- if (storeArray[j].level === level) {
- index = storeArray[j].index + 1
- break
- }
- }
- }
- }
- storeArray.push({
- level: level,
- title: it.textContent,
- ident: it.textContent.match(/[\((](.*?)[\))]/)?.[1],
- index: index,
- demandType: type
- })
- })
- // 直接将storeArray计算出章节号
- const chapterArray: any[] = storeArray.map((it, indx) => {
- let str = it.index + 1 + ""
- for (let i = it.level - 1; i > 0; i--) {
- for (let j = indx - 1; j >= 0; j--) {
- if (storeArray[j].level === i) {
- str = storeArray[j].index + 1 + "." + str
- break
- }
- }
- }
- return {
- ...it,
- chapter: str
- }
- })
- this.hWithChapter = chapterArray
- }
- /**
- * 将所有Element元素遍历,输出列表格式
- */
- parseToArray(): DemandObj[] {
- const resArr: DemandObj[] = []
- let index = 0
- let currentHElement: IHobjWithChapter = this.hWithChapter[index]
- let adapterIndex: number = 1
- this.domArray.forEach((item) => {
- // 1.如果循环到H元素,将其存入
- if (item.tagName.startsWith("H")) {
- const text = item.textContent
- if (text !== currentHElement.title) {
- currentHElement = this.hWithChapter[index + 1]
- index++
- adapterIndex = 1
- }
- } else {
- // 2.构造每一项放入 - chapter和content计算
- let content = ""
- let ident = currentHElement.ident
- if (!ident) {
- ident = ""
- }
- // 这里对图片进行处理
- if (item.querySelector("img")) {
- const img = item.querySelector("img")
- if (img) {
- const strblob = img.src + ""
- const blob = strblob.split(",")[1]
- content = `

`
- }
- ident += `-g${adapterIndex}`
- adapterIndex++
- resArr.push({
- chapter: currentHElement.chapter,
- title: currentHElement.title,
- ident: ident,
- demandType: currentHElement.demandType,
- content
- })
- } else {
- // 如果不是图片进行判断
- if (item.textContent) {
- if (item.tagName === "TABLE") {
- content = item.outerHTML
- ident += `-t${adapterIndex}`
- adapterIndex++
- }
- if (item.tagName === "P" && !item.querySelector("img")) {
- content = item.innerHTML.trim()
- ident += `-p${adapterIndex}`
- adapterIndex++
- }
- if (item.tagName === "OL" || item.tagName === "UL") {
- content = item.innerHTML.trim()
- ident += `-u${adapterIndex}`
- adapterIndex++
- }
- // title要将括号去除
- resArr.push({
- chapter: currentHElement.chapter,
- title: currentHElement.title,
- ident: ident,
- demandType: currentHElement.demandType,
- content
- })
- }
- }
- }
- })
- return resArr
- }
-}
diff --git a/cdTMP/src/views/project/round/beiceType.ts b/cdTMP/src/views/project/round/beiceType.ts
index 287df86..b5b84a0 100644
--- a/cdTMP/src/views/project/round/beiceType.ts
+++ b/cdTMP/src/views/project/round/beiceType.ts
@@ -9,7 +9,7 @@ const beiceType: BeiceTypeT[] = [
{ label: "设计说明", value: "SJ" },
{ label: "需求文档", value: "XQ" },
{ label: "通信协议", value: "XY" },
- { label: "研制总要求", value: "YZ" }
+ { label: "研制总要求/技术协议等", value: "YZ" }
]
export default beiceType
diff --git a/cdTMP/src/views/project/round/hooks/useColumn.ts b/cdTMP/src/views/project/round/hooks/useColumn.ts
index 8070015..6b76894 100644
--- a/cdTMP/src/views/project/round/hooks/useColumn.ts
+++ b/cdTMP/src/views/project/round/hooks/useColumn.ts
@@ -1,6 +1,8 @@
-import { ref } from "vue"
+import { ref, shallowRef } from "vue"
import { useRoute } from "vue-router"
import beiceType from "@/views/project/round/beiceType"
+// 导入自定义组件
+import UploadInput from "@/components/UploadInput/index.vue"
export default function (crudOrFormRef: any) {
// global
@@ -8,10 +10,8 @@ export default function (crudOrFormRef: any) {
// 计算注释率计算crud/form的数据,判断
const calcPercent = () => {
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()}%`
+ const { total_lines, comment_lines } = formData
+ formData.comment_percent = `${(comment_lines / total_lines).toFixed(2).toString()}%`
}
const crudColumns = ref([
{
@@ -51,28 +51,24 @@ export default function (crudOrFormRef: any) {
translation: true,
tagColors: { XQ: "blue", SO: "green", SJ: "orangered", XY: "pinkpurple", YZ: "red" }
},
- onControl: (value) => {
+ onControl: (value: string) => {
if (value === "SO") {
return {
- black_line: { display: true },
- code_line: { display: true },
- mix_line: { display: true },
- comment_line: { display: true },
- total_code_line: { display: true },
- total_line: { display: true },
+ total_lines: { display: true },
+ effective_lines: { display: true },
+ comment_lines: { display: true },
comment_percent: { display: true },
+ upload: { display: true },
release_date: { display: false }
}
} else {
// 其他数据清除
return {
- black_line: { display: false },
- code_line: { display: false },
- mix_line: { display: false },
- comment_line: { display: false },
- total_code_line: { display: false },
- total_line: { display: false },
+ total_lines: { display: false },
+ effective_lines: { display: false },
+ comment_lines: { display: false },
comment_percent: { display: false },
+ upload: { display: false },
release_date: { display: true }
}
}
@@ -123,49 +119,36 @@ export default function (crudOrFormRef: any) {
formType: "date"
},
{
- title: "空行",
+ title: "总行数",
hide: true,
align: "center",
- dataIndex: "black_line",
+ dataIndex: "total_lines",
formType: "input-number",
- commonRules: [{ required: true, message: "空行数必填" }],
+ commonRules: [{ required: true, message: "总行数必填" }],
min: 0,
onControl: () => {
calcPercent()
}
},
{
- title: "纯代码行",
+ title: "有效行数",
hide: true,
align: "center",
- dataIndex: "code_line",
+ dataIndex: "effective_lines",
formType: "input-number",
- commonRules: [{ required: true, message: "纯代码行数必填" }],
+ commonRules: [{ required: true, message: "有效行数必填" }],
min: 0,
onControl: () => {
calcPercent()
}
},
{
- title: "纯注释行",
+ title: "注释行数",
hide: true,
align: "center",
- dataIndex: "comment_line",
+ dataIndex: "comment_lines",
formType: "input-number",
- commonRules: [{ required: true, message: "纯注释行数必填" }],
- min: 0,
- onControl: () => {
- calcPercent()
- }
- },
- {
- title: "混合行",
- hide: true,
- align: "center",
- dataIndex: "mix_line",
- formType: "input-number",
- help: "混合行是指:代码中一行即包含代码也包含注释",
- commonRules: [{ required: true, message: "混合行数必填" }],
+ commonRules: [{ required: true, message: "注释行数必填" }],
min: 0,
onControl: () => {
calcPercent()
@@ -180,6 +163,15 @@ export default function (crudOrFormRef: any) {
addDisabled: true,
editDisabled: true,
disabled: true
+ },
+ {
+ title: "上传源代码",
+ align: "center",
+ dataIndex: "upload",
+ placeholder: "上传源代码",
+ hide: true,
+ formType: "component",
+ component: shallowRef(UploadInput)
}
])
return crudColumns
diff --git a/cdTMP/src/views/project/testDemand/CaseSubForm/useOptions.ts b/cdTMP/src/views/project/testDemand/CaseSubForm/useOptions.ts
index 638064e..9765f15 100644
--- a/cdTMP/src/views/project/testDemand/CaseSubForm/useOptions.ts
+++ b/cdTMP/src/views/project/testDemand/CaseSubForm/useOptions.ts
@@ -10,7 +10,78 @@ export default function useOptions(formRef: any) {
})
const crudColumns = useColumn(formRef)
const columnOptions = computed(() => {
- return tool.renameKeyInArray(crudColumns.value, "commonRules", "rules")
+ // 处理表单布局
+ const transformColumns = tool.renameKeyInArray(crudColumns.value, "commonRules", "rules")
+ // 取出字段column对象
+ const identColumn = transformColumns.find((item: any) => item.dataIndex === "ident")
+ const nameColumn = transformColumns.find((item: any) => item.dataIndex === "name")
+ const designPersonColumn = transformColumns.find((item: any) => item.dataIndex === "designPerson")
+ const testPersonColumn = transformColumns.find((item: any) => item.dataIndex === "testPerson")
+ const monitorPersonColumn = transformColumns.find((item: any) => item.dataIndex === "monitorPerson")
+ const summarizeColumn = transformColumns.find((item: any) => item.dataIndex === "summarize")
+ const initializationColumn = transformColumns.find((item: any) => item.dataIndex === "initialization")
+ const premiseColumn = transformColumns.find((item: any) => item.dataIndex === "premise")
+ const exe_timeColumn = transformColumns.find((item: any) => item.dataIndex === "exe_time")
+ // 组装表单布局
+ const identAndNameColumn = {
+ formType: "grid",
+ cols: [
+ { span: 12, formList: [identColumn] },
+ { span: 12, formList: [nameColumn] }
+ ]
+ }
+ const cardColumn = {
+ formType: "card",
+ customClass: ["ml-5", "mb-3", "py-0", "px-0"],
+ title: "人员信息",
+ formList: [
+ {
+ formType: "grid",
+ cols: [
+ { span: 8, formList: [designPersonColumn] },
+ { span: 8, formList: [testPersonColumn] },
+ { span: 8, formList: [monitorPersonColumn] }
+ ]
+ }
+ ]
+ }
+ const summarizeColumnNew = {
+ formType: "grid",
+ cols: [{ span: 24, formList: [summarizeColumn] }]
+ }
+ const initializationColumnNew = {
+ formType: "grid",
+ cols: [{ span: 24, formList: [initializationColumn] }]
+ }
+ const premiseAndExeColumn = {
+ formType: "grid",
+ cols: [
+ { span: 12, formList: [premiseColumn] },
+ { span: 12, formList: [exe_timeColumn] }
+ ]
+ }
+ // 取除原数组里面的内容
+ const newColumnsArray = transformColumns.filter(
+ (it: any) =>
+ it.dataIndex !== "ident" &&
+ it.dataIndex !== "name" &&
+ it.dataIndex !== "designPerson" &&
+ it.dataIndex !== "testPerson" &&
+ it.dataIndex !== "monitorPerson" &&
+ it.dataIndex !== "summarize" &&
+ it.dataIndex !== "initialization" &&
+ it.dataIndex !== "premise" &&
+ it.dataIndex !== "exe_time"
+ )
+ newColumnsArray.unshift(
+ identAndNameColumn,
+ cardColumn,
+ summarizeColumnNew,
+ initializationColumnNew,
+ premiseAndExeColumn
+ )
+ return newColumnsArray
})
+
return { options, columnOptions }
}
diff --git a/cdTMP/src/views/project/testDemand/hooks/useColumn.tsx b/cdTMP/src/views/project/testDemand/hooks/useColumn.tsx
index de6cd07..ee90c10 100644
--- a/cdTMP/src/views/project/testDemand/hooks/useColumn.tsx
+++ b/cdTMP/src/views/project/testDemand/hooks/useColumn.tsx
@@ -140,9 +140,20 @@ export default function (crudOrFormRef: any, problemFormRef?: any) {
},
{
title: "执行时间",
+ align: "center",
dataIndex: "exe_time",
+ formType: "date",
+ customRender: ({ record }) => {
+ // 如果不存在exe_time则显示为“没有设置”
+ return record.exe_time ? record.exe_time :
未填写
+ }
+ },
+ {
+ title: "时序图(cpu不填写此字段)",
hide: true,
- formType: "date"
+ dataIndex: "timing_diagram",
+ addDefaultValue: "",
+ formType: "editor"
},
{
title: "测试步骤",
diff --git a/cdTMP/src/views/project/testDemand/hooks/useCrudOpMore.ts b/cdTMP/src/views/project/testDemand/hooks/useCrudOpMore.ts
index f64196d..421f97e 100644
--- a/cdTMP/src/views/project/testDemand/hooks/useCrudOpMore.ts
+++ b/cdTMP/src/views/project/testDemand/hooks/useCrudOpMore.ts
@@ -123,7 +123,7 @@ export default function (crudRef: Ref
>) {
},
{
formType: "card",
- customClass: ["ml-10", "mb-3", "py-0", "px-0"],
+ customClass: ["ml-5", "mb-3", "py-0", "px-0"],
title: "人员信息",
formList: [
{
diff --git a/cdTMP/src/views/testmanage/projmanage/hooks/useGenerateSecond.ts b/cdTMP/src/views/testmanage/projmanage/hooks/useGenerateSecond.ts
index b96d175..0bdea1c 100644
--- a/cdTMP/src/views/testmanage/projmanage/hooks/useGenerateSecond.ts
+++ b/cdTMP/src/views/testmanage/projmanage/hooks/useGenerateSecond.ts
@@ -32,14 +32,12 @@ const useGenerateSecond = function () {
dgGenerateApi.createTechYiju({ id }), // 技术依据文件
dgGenerateApi.createContact({ id }), // 生成联系人和方式
dgGenerateApi.createTimeaddress({ id }), // 生成测评时间和地点
- dgGenerateApi.createFuncList({ id }), // 生成被测软件功能列表
dgGenerateApi.createSoftComposition({ id }), // 生成测评对象-软件组成
dgGenerateApi.createAdequacyEffectiveness({ id }), // 生成测试充分性(adequancy)和有效性(effectiveness)说明
dgGenerateApi.createGroup({ id }), // 生成测评组织及分工
dgGenerateApi.createGuarantee({ id }), // 生成测评保障
dgGenerateApi.createAbbreviation({ id }), // 生成缩略语
dgGenerateApi.createInterface({ id }), // 生成-被测软件接口
- dgGenerateApi.createPerformance({ id }), // 生成-被测软件性能
dgGenerateApi.createBaseInformation({ id }), // 生成-被测软件基本信息
dgGenerateApi.createLevelAndType({ id }), // 生成-测试级别和测试类型 -【修改】
dgGenerateApi.createStrategy({ id }), // 生成-测试策略 -【新增】
@@ -47,6 +45,8 @@ const useGenerateSecond = function () {
dgGenerateApi.createXqComparison({ id }), // 生成-需求规格说明-测试项对照表
dgGenerateApi.createFanXqComparison({ id }), // 生成-反向测试项-需求规格说明对照表
dgGenerateApi.createCodeQuality({ id }), // 生成-代码质量度量分析表
+ // 2025年4月29日新增 - 顶层技术文件
+ dgGenerateApi.createTopFile({ id }), // 生成顶层技术文件
// 新增拆分接口
dgGenerateApi.createStaticEnvironment({ id }), // 生成-静态测试环境说明
dgGenerateApi.createStaticSoft({ id }), // 生成-静态软件项
@@ -69,9 +69,7 @@ const useGenerateSecond = function () {
isSmLoading.value = true
await Promise.all([
dgGenerateApi.createSoftComposition({ id }), // 生成测评对象 - 和大纲一样
- dgGenerateApi.createFuncList({ id }), // 生成被测软件功能 - 和大纲重复
dgGenerateApi.createInterface({ id }), // 生成被测软件接口 - 和大纲重复 - 可能会删除
- dgGenerateApi.createPerformance({ id }), // 生成被测软件性能 - 和大纲重复 - 可能会删除
dgGenerateApi.createBaseInformation({ id }), // 生成被测软件基本信息 - 和大纲重复 - 可能会删除
dgGenerateApi.createYiju({ id }), // 生成标准类引用文档 - 和大纲重复 - 可能会删除
smGenerateApi.createSMTechyiju({ id }), // 生成技术类引用文档列表 -> 在大纲基础上添加《测评大纲》
@@ -97,7 +95,12 @@ const useGenerateSecond = function () {
const createJLItem = async (id: number) => {
isGenerating.value = true
isJlloading.value = true
- await jlGenerateApi.createJLcaserecord({ id }).finally(() => {
+ await Promise.all([
+ // 生成-被测软件基本信息 - 和大纲一样
+ dgGenerateApi.createBaseInformation({ id }),
+ // 记录相关片段
+ jlGenerateApi.createJLcaserecord({ id })
+ ]).finally(() => {
isGenerating.value = false
isJlloading.value = false
})
@@ -116,7 +119,10 @@ const useGenerateSecond = function () {
hsmGenerateApi.createCaseListDesc({ id }),
hsmGenerateApi.createCaseList({ id }),
hsmGenerateApi.createTrack({ id }),
- // 拆分大纲软硬件环境
+ // 拆分大纲软硬件环境-大纲内容
+ dgGenerateApi.createSoftComposition({ id }), // 生成测评对象-软件组成
+ dgGenerateApi.createYiju({ id }), // 生成依据文件
+ dgGenerateApi.createInterface({ id }), // 生成-被测软件接口 - 和大纲一样
dgGenerateApi.createStaticEnvironment({ id }), // 生成-静态测试环境说明
dgGenerateApi.createStaticSoft({ id }), // 生成-静态软件项
dgGenerateApi.createStaticHard({ id }), // 生成-静态硬件和固件项
@@ -171,7 +177,15 @@ const useGenerateSecond = function () {
bgGenerateApi.createBgEntire({ id }),
bgGenerateApi.createBgYzxqTrack({ id }),
bgGenerateApi.createBgProblemsSummary({ id }),
- // 拆分软硬件环境
+ // 2025年4月27日新增:软件问题统计
+ bgGenerateApi.createProblemStatistics({ id }), // 生成软件问题统计
+ // 2025年4月28日新增:摸底清单
+ bgGenerateApi.createBgModiList({ id }), // 生成摸底清单
+ // 拆分软硬件环境-大纲内容
+ dgGenerateApi.createSoftComposition({ id }), // 生成测评对象 - 大纲内容
+ dgGenerateApi.createYiju({ id }), // 生成依据文件
+ dgGenerateApi.createInterface({ id }), // 生成-被测软件接口 - 大纲内容
+ dgGenerateApi.createAbbreviation({ id }), // 生成缩略语 - 大纲内容
dgGenerateApi.createStaticEnvironment({ id }), // 生成-静态测试环境说明
dgGenerateApi.createStaticSoft({ id }), // 生成-静态软件项
dgGenerateApi.createStaticHard({ id }), // 生成-静态硬件和固件项
@@ -179,7 +193,9 @@ const useGenerateSecond = function () {
dgGenerateApi.createDynamicSoft({ id }), // 生成-动态软件项
dgGenerateApi.createDynamicHard({ id }), // 生成-动态硬件和固件项
dgGenerateApi.createTestData({ id }), // 生成-测评数据
- dgGenerateApi.createEnvDiff({ id }) // 生成-环境差异性分析
+ dgGenerateApi.createEnvDiff({ id }), // 生成-环境差异性分析
+ // 2025年4月29日新增 - 顶层技术文件
+ dgGenerateApi.createTopFile({ id }) // 生成顶层技术文件
]).finally(() => {
isGenerating.value = false
isBgLoading.value = false
diff --git a/cdTMP/visualizer.html b/cdTMP/visualizer.html
index 6fef6a5..e05f30e 100644
--- a/cdTMP/visualizer.html
+++ b/cdTMP/visualizer.html
@@ -4929,7 +4929,7 @@ var drawChart = (function (exports) {