diff --git a/package.json b/package.json index 49a9e6f6652d0573c876515592a3f921f254944e..b0310a9c620202dff91757528e4f21d4b7d25507 100644 --- a/package.json +++ b/package.json @@ -1,134 +1,137 @@ { - "name": "test-lib-front", - "version": "1.0.0", - "private": true, - "description": "An out-of-box UI solution for enterprise applications", - "scripts": { - "analyze": "cross-env ANALYZE=1 umi build", - "build": "umi build", - "deploy": "npm run build && npm run gh-pages", - "dev": "npm run start:dev", - "gh-pages": "gh-pages -d dist", - "i18n-remove": "pro i18n-remove --locale=zh-CN --write", - "postinstall": "umi g tmp", - "lint": "umi g tmp && npm run lint:js && npm run lint:style && npm run lint:prettier && npm run tsc", - "lint-staged": "lint-staged", - "lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ", - "lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src && npm run lint:style", - "lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src", - "lint:prettier": "prettier -c --write \"src/**/*\" --end-of-line auto", - "lint:style": "stylelint --fix \"src/**/*.less\" --syntax less", - "openapi": "umi openapi", - "precommit": "lint-staged", - "prettier": "prettier -c --write \"src/**/*\"", - "start": "cross-env UMI_ENV=dev umi dev", - "start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev umi dev", - "start:no-mock": "cross-env MOCK=none UMI_ENV=dev umi dev", - "start:no-ui": "cross-env UMI_UI=none UMI_ENV=dev umi dev", - "start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev umi dev", - "start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev umi dev", - "pretest": "node ./tests/beforeTest", - "test": "umi test", - "test:all": "node ./tests/run-tests.js", - "test:component": "umi test ./src/components", - "serve": "umi-serve", - "tsc": "tsc --noEmit" - }, - "lint-staged": { - "**/*.less": "stylelint --syntax less", - "**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js", - "**/*.{js,jsx,tsx,ts,less,md,json}": [ - "prettier --write" - ] - }, - "browserslist": [ - "> 1%", - "last 2 versions", - "not ie <= 10" - ], - "dependencies": { - "@ant-design/charts": "^0.9.4", - "@ant-design/icons": "^4.7.0", - "@ant-design/pro-descriptions": "^1.6.8", - "@ant-design/pro-form": "^1.18.3", - "@ant-design/pro-layout": "^6.15.3", - "@ant-design/pro-table": "^2.30.8", - "@antv/data-set": "^0.11.0", - "@antv/l7": "^2.3.7", - "@antv/l7-maps": "^2.3.7", - "@antv/l7-react": "^2.1.9", - "@types/react-color": "^3.0.6", - "@types/react-custom-scrollbars": "^4.0.10", - "@types/reactcss": "^1.2.6", - "@types/styled-components": "^5.1.24", - "@umijs/route-utils": "^1.0.36", - "@wangeditor/editor": "^5.0.1", - "@wangeditor/plugin-md": "^1.0.0", - "ahooks": "^3.1.13", - "antd": "^4.19.3", - "bizcharts": "^3.5.3-beta.0", - "bizcharts-plugin-slider": "^2.1.1-beta.1", - "classnames": "^2.2.6", - "clipboard": "^2.0.11", - "gg-editor": "^2.0.2", - "lodash": "^4.17.11", - "lodash-decorators": "^6.0.0", - "moment": "^2.25.3", - "numeral": "^2.0.6", - "nzh": "^1.0.3", - "omit.js": "^2.0.2", - "react": "^17.0.0", - "react-color": "^2.19.3", - "react-custom-scrollbars": "^4.2.1", - "react-dev-inspector": "^1.1.1", - "react-dom": "^17.0.0", - "react-fittext": "^1.0.0", - "react-helmet-async": "^1.0.4", - "react-router": "^4.3.1", - "react-split-pane": "^0.1.92", - "reactcss": "^1.2.3", - "styled-components": "^5.3.5", - "umi": "^3.5.0", - "umi-serve": "^1.9.10" - }, - "devDependencies": { - "@ant-design/pro-cli": "^2.0.2", - "@types/express": "^4.17.0", - "@types/history": "^4.7.2", - "@types/jest": "^26.0.0", - "@types/lodash": "^4.14.144", - "@types/react": "^17.0.0", - "@types/react-dom": "^17.0.0", - "@types/react-helmet": "^6.1.0", - "@umijs/fabric": "^2.6.2", - "@umijs/openapi": "^1.1.14", - "@umijs/plugin-blocks": "^2.0.5", - "@umijs/plugin-esbuild": "^1.0.1", - "@umijs/plugin-openapi": "^1.2.0", - "@umijs/preset-ant-design-pro": "^1.2.0", - "@umijs/preset-dumi": "^1.1.7", - "@umijs/preset-react": "^1.8.17", - "@umijs/yorkie": "^2.0.3", - "carlo": "^0.9.46", - "cross-env": "^7.0.0", - "cross-port-killer": "^1.1.1", - "detect-installer": "^1.0.1", - "enzyme": "^3.11.0", - "eslint": "^7.1.0", - "express": "^4.17.1", - "gh-pages": "^3.0.0", - "jsdom-global": "^3.0.2", - "lint-staged": "^10.0.0", - "mockjs": "^1.0.1-beta3", - "prettier": "^2.3.2", - "puppeteer-core": "^8.0.0", - "stylelint": "^13.0.0", - "typescript": "^4.2.2" - }, - "engines": { - "node": ">=10.0.0" - }, - "gitHooks": { - "commit-msg": "fabric verify-commit" - } + "name": "test-lib-front", + "version": "1.0.0", + "private": true, + "description": "An out-of-box UI solution for enterprise applications", + "scripts": { + "analyze": "cross-env ANALYZE=1 umi build", + "build": "umi build", + "deploy": "npm run build && npm run gh-pages", + "dev": "npm run start:dev", + "gh-pages": "gh-pages -d dist", + "i18n-remove": "pro i18n-remove --locale=zh-CN --write", + "postinstall": "umi g tmp", + "lint": "umi g tmp && npm run lint:js && npm run lint:style && npm run lint:prettier && npm run tsc", + "lint-staged": "lint-staged", + "lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ", + "lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src && npm run lint:style", + "lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src", + "lint:prettier": "prettier -c --write \"src/**/*\" --end-of-line auto", + "lint:style": "stylelint --fix \"src/**/*.less\" --syntax less", + "openapi": "umi openapi", + "precommit": "lint-staged", + "prettier": "prettier -c --write \"src/**/*\"", + "start": "cross-env UMI_ENV=dev umi dev", + "start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev umi dev", + "start:no-mock": "cross-env MOCK=none UMI_ENV=dev umi dev", + "start:no-ui": "cross-env UMI_UI=none UMI_ENV=dev umi dev", + "start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev umi dev", + "start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev umi dev", + "pretest": "node ./tests/beforeTest", + "test": "umi test", + "test:all": "node ./tests/run-tests.js", + "test:component": "umi test ./src/components", + "serve": "umi-serve", + "tsc": "tsc --noEmit" + }, + "lint-staged": { + "**/*.less": "stylelint --syntax less", + "**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js", + "**/*.{js,jsx,tsx,ts,less,md,json}": [ + "prettier --write" + ] + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 10" + ], + "dependencies": { + "@ant-design/charts": "^0.9.4", + "@ant-design/icons": "^4.7.0", + "@ant-design/pro-descriptions": "^1.6.8", + "@ant-design/pro-form": "^1.18.3", + "@ant-design/pro-layout": "^6.15.3", + "@ant-design/pro-table": "^2.30.8", + "@antv/data-set": "^0.11.0", + "@antv/l7": "^2.3.7", + "@antv/l7-maps": "^2.3.7", + "@antv/l7-react": "^2.1.9", + "@types/react-color": "^3.0.6", + "@types/react-custom-scrollbars": "^4.0.10", + "@types/reactcss": "^1.2.6", + "@types/styled-components": "^5.1.24", + "@umijs/route-utils": "^1.0.36", + "@wangeditor/editor": "^5.0.1", + "@wangeditor/plugin-md": "^1.0.0", + "ahooks": "^3.1.13", + "antd": "^4.19.3", + "bizcharts": "^3.5.3-beta.0", + "bizcharts-plugin-slider": "^2.1.1-beta.1", + "classnames": "^2.2.6", + "clipboard": "^2.0.11", + "gg-editor": "^2.0.2", + "immutability-helper": "^3.1.1", + "lodash": "^4.17.11", + "lodash-decorators": "^6.0.0", + "moment": "^2.25.3", + "numeral": "^2.0.6", + "nzh": "^1.0.3", + "omit.js": "^2.0.2", + "react": "^17.0.0", + "react-color": "^2.19.3", + "react-custom-scrollbars": "^4.2.1", + "react-dev-inspector": "^1.1.1", + "react-dnd": "^14.0.4", + "react-dnd-html5-backend": "^14.0.2", + "react-dom": "^17.0.0", + "react-fittext": "^1.0.0", + "react-helmet-async": "^1.0.4", + "react-router": "^4.3.1", + "react-split-pane": "^0.1.92", + "reactcss": "^1.2.3", + "styled-components": "^5.3.5", + "umi": "^3.5.23", + "umi-serve": "^1.9.10" + }, + "devDependencies": { + "@ant-design/pro-cli": "^2.0.2", + "@types/express": "^4.17.0", + "@types/history": "^4.7.2", + "@types/jest": "^26.0.0", + "@types/lodash": "^4.14.144", + "@types/react": "^17.0.0", + "@types/react-dom": "^17.0.0", + "@types/react-helmet": "^6.1.0", + "@umijs/fabric": "^2.6.2", + "@umijs/openapi": "^1.1.14", + "@umijs/plugin-blocks": "^2.0.5", + "@umijs/plugin-esbuild": "^1.0.1", + "@umijs/plugin-openapi": "^1.2.0", + "@umijs/preset-ant-design-pro": "^1.2.0", + "@umijs/preset-dumi": "^1.1.7", + "@umijs/preset-react": "^1.8.17", + "@umijs/yorkie": "^2.0.3", + "carlo": "^0.9.46", + "cross-env": "^7.0.0", + "cross-port-killer": "^1.1.1", + "detect-installer": "^1.0.1", + "enzyme": "^3.11.0", + "eslint": "^7.1.0", + "express": "^4.17.1", + "gh-pages": "^3.0.0", + "jsdom-global": "^3.0.2", + "lint-staged": "^10.0.0", + "mockjs": "^1.0.1-beta3", + "prettier": "^2.3.2", + "puppeteer-core": "^8.0.0", + "stylelint": "^13.0.0", + "typescript": "^4.2.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "gitHooks": { + "commit-msg": "fabric verify-commit" + } } diff --git a/src/pages/Suite/components/AddModal.tsx b/src/pages/Suite/components/AddModal.tsx index 12a0b60d24b50c314e10fe2be1e11e205b185e7d..3a5c6eb979cc796887b7a1341f38ff9777af5f7a 100644 --- a/src/pages/Suite/components/AddModal.tsx +++ b/src/pages/Suite/components/AddModal.tsx @@ -1,11 +1,11 @@ import React from "react" -import { Modal, Space, Typography, Button, Form, Input, Select, Radio, Switch, Divider, message, Row } from "antd" -import RichTextEditor from "@/components/RichTextEditor" +import { Modal, Space, Typography, Button, Form, Input, Select, Radio, Switch, Col, Divider, message, Row } from "antd" import { deviceArchOptions, deviceTypeOptions, priorityListOptions, runMethodOptions, runModelOptions, testTypeOptions } from "../utils"; import { createCases } from "../services"; import { ToneCaseItem } from "@/pages/Suite/components/ToneCase" import { CustomForm } from "@/components/CustomStyled"; -import { ModuleSelect, PrioritySelect } from "@/pages/Suite/components/FormItems" +import { TagSelect, TestSuiteSelect, ModuleClassSelect, PrioritySelect, OperatStepsTables } from "@/pages/Suite/components/FormItems" +import { useParams } from "umi" type IProps = { onOk: () => void; @@ -16,43 +16,22 @@ type IRefs = { [k: string]: any } -const RICH_EDITER_DEFAULT_TEXT = [ - { - type: "paragrapha", children: [{ text: "工具:", bold: true }] - }, - { - type: "paragrapha", children: [{ text: "", }] - }, - { - type: "paragrapha", children: [{ text: "版本:", bold: true }] - }, - { - type: "paragrapha", children: [{ text: "", }] - }, - { - type: "paragrapha", children: [{ text: "步骤:", bold: true }] - }, - { - type: "paragrapha", children: [{ text: "", }] - }, - { - type: "paragrapha", children: [{ text: "用例说明:", bold: true }] - }, -] - const ReactComponent: React.ForwardRefRenderFunction = (props, ref) => { const { onOk } = props + const { mod_id } = useParams() as any + const [visible, setVisible] = React.useState(false) const [loading, setLoading] = React.useState(false) const [source, setSource] = React.useState(undefined) const [runMethod, setRunMethod] = React.useState("auto") + const [steps, setSteps] = React.useState([]) React.useImperativeHandle(ref, () => ({ show(_: any) { setSource(_) setVisible(true) - form.setFieldsValue(_) + form.setFieldsValue({ ..._, parent: mod_id ? + mod_id : undefined }) } })) @@ -75,27 +54,27 @@ const ReactComponent: React.ForwardRefRenderFunction = (props, re const handleOk = async () => { if (loading) return - setLoading(true) form.validateFields() .then(async (values: any) => { - const vm = richEditerRef.current - values.custom_fields = vm.getText() !== "" ? vm.children : null - + console.log(values) + const { device_arch } = values if (runMethod !== "manual") { if (!isCheckedCase) { - setLoading(false) message.error("请选择T-One用例!") return } values.tone_case = isCheckedCase.tone_case_id values.base_fields = isCheckedCase } + setLoading(true) const { msg, code } = await createCases({ ...values, + device_arch: device_arch.toString(), + steps }) + setLoading(false) if (code !== 200) { - setLoading(false) message.error(msg) return } @@ -104,7 +83,7 @@ const ReactComponent: React.ForwardRefRenderFunction = (props, re onOk() message.success("添加成功") }).catch(err => { - setLoading(false) + console.log(err) }) } @@ -114,12 +93,6 @@ const ReactComponent: React.ForwardRefRenderFunction = (props, re setIsCheckedCase(conf) } - const richEditerRef = React.useRef(null) as any - - const handleChange = (vm: any) => { - richEditerRef.current = vm - } - return ( = (props, re > - - - - - {/* 模块分类 */} - - - - - - - - - - setRunMethod(target.value)} /> - - - { - runMethod === "manual" ? - - - - - - - */} + + + + + + + + + + + + + {/* 功能模块 */} + + + + + + + + + + + + + + + + + + + + setRunMethod(target.value)} /> + + { + runMethod === "manual" ? + + + + + + + + + + + - - 用例说明 -
- -
-
) } -export default React.forwardRef(ReactComponent) \ No newline at end of file +export default React.forwardRef(ReactComponent) + + +const RICH_EDITER_DEFAULT_TEXT = [ + { + type: "paragrapha", children: [{ text: "工具:", bold: true }] + }, + { + type: "paragrapha", children: [{ text: "", }] + }, + { + type: "paragrapha", children: [{ text: "版本:", bold: true }] + }, + { + type: "paragrapha", children: [{ text: "", }] + }, + { + type: "paragrapha", children: [{ text: "步骤:", bold: true }] + }, + { + type: "paragrapha", children: [{ text: "", }] + }, + { + type: "paragrapha", children: [{ text: "用例说明:", bold: true }] + }, +] + + +{/* +用例说明 +
+ +
+
*/} \ No newline at end of file diff --git a/src/pages/Suite/components/Case/Base.tsx b/src/pages/Suite/components/Case/Base.tsx index 2808c227065fa8cc00585b7df592d9258d08333a..2e8e71ccac23efcb4e17c43f4fc9bd746fa238cf 100644 --- a/src/pages/Suite/components/Case/Base.tsx +++ b/src/pages/Suite/components/Case/Base.tsx @@ -1,8 +1,8 @@ import React from "react" -import { Divider, Typography, Form } from "antd" +import { Divider, Typography, Form, Tag } from "antd" import styled from "styled-components" import { testTypeMap, runMethodMap, isAvailableMap, deviceTypeMap, deviceArchMap, runModelMap } from "@/pages/Suite/utils" -import EchoRichText from "@/components/RichTextEditor/EchoRichText" +import { TableCls } from "@/pages/Plan/components/ContentTable/styled" type IProps = { [k: string]: any @@ -23,6 +23,10 @@ const BaseChild: React.FC = (props) => { const { currentCase } = props const [form] = Form.useForm() + if (!currentCase) return <> + const { labels, steps } = currentCase + let labelArr: any[] = labels.split(",") + return ( = (props) => { 基础信息 + + + {currentCase?.suite_name || "-"} + + {runMethodMap.get(currentCase?.run_method) || "-"} @@ -49,6 +58,10 @@ const BaseChild: React.FC = (props) => { {isAvailableMap.get(currentCase?.is_available) || "-"} + + {labelArr.length > 0 ? labelArr?.map((i: string) => {i}) : "-"} + + { currentCase?.run_method === "auto" && @@ -65,9 +78,14 @@ const BaseChild: React.FC = (props) => { 测试环境 + + {deviceArchMap.get(currentCase?.device_arch) || "-"} + + {deviceTypeMap.get(currentCase?.device_type) || "-"} + {testTypeMap.get(currentCase?.type) || "-"} @@ -75,34 +93,43 @@ const BaseChild: React.FC = (props) => { - 测试步骤 + 前置条件 - {/* - {"-"} - */} - - {deviceArchMap.get(currentCase?.device_arch) || "-"} - - {/* - {"-"} - */} +
- 运行步骤 - - {/* - {currentCase?.base_fields?.tools || "-"} + 操作步骤 - - {currentCase?.base_fields?.version || "-"} - */} - - ) diff --git a/src/pages/Suite/components/Case/Edit.tsx b/src/pages/Suite/components/Case/Edit.tsx index 5313cbd2cef7c24c7a80a25c1f803dae41400eaf..ab3ed55fbb34327a13a10c7df09d3522d51db83f 100644 --- a/src/pages/Suite/components/Case/Edit.tsx +++ b/src/pages/Suite/components/Case/Edit.tsx @@ -2,9 +2,8 @@ import React from "react" import { Divider, Typography, Input, Switch, Form, Select, Radio } from "antd" import styled from "styled-components" import { deviceArchOptions, deviceTypeOptions, runMethodOptions, runModelOptions, testTypeOptions } from "../../utils" -import RichTextEditor from "@/components/RichTextEditor" import { ToneCaseItem } from "@/pages/Suite/components/ToneCase" -import { PrioritySelect } from "@/pages/Suite/components/FormItems" +import { OperatStepsTables, TestSuiteSelect, TagSelect } from "@/pages/Suite/components/FormItems" type IProps = { [k: string]: any @@ -25,6 +24,7 @@ const EditChild: React.ForwardRefRenderFunction<{}, IProps> = (props, ref) => { const [checkCase, setCheckCase] = React.useState(null) const [runMethod, setRunMethod] = React.useState(null) + const [steps, setSteps] = React.useState([]) React.useImperativeHandle(ref, () => { return { @@ -60,6 +60,7 @@ const EditChild: React.ForwardRefRenderFunction<{}, IProps> = (props, ref) => { return { ...values, ...params, + steps } }, } @@ -67,8 +68,9 @@ const EditChild: React.ForwardRefRenderFunction<{}, IProps> = (props, ref) => { React.useEffect(() => { if (currentCase && JSON.stringify(currentCase) !== "{}") { - const { base_fields, tone_case, run_method } = currentCase - form.setFieldsValue({ ...currentCase, ...base_fields }) + const { base_fields, tone_case, run_method, labels } = currentCase + + form.setFieldsValue({ ...currentCase, ...base_fields, labels: labels.split(",") }) if (base_fields && JSON.stringify(base_fields) !== "{}") setCheckCase({ ...base_fields, id: tone_case }) setRunMethod(run_method) @@ -80,10 +82,6 @@ const EditChild: React.ForwardRefRenderFunction<{}, IProps> = (props, ref) => { } }, [currentCase]) - const richEditerChange = (editor: any) => { - vm.current = editor - } - return ( = (props, ref) => { 基础信息 + + = (props, ref) => { + + @@ -141,29 +143,24 @@ const EditChild: React.ForwardRefRenderFunction<{}, IProps> = (props, ref) => { 测试步骤 - {/* - - */} - - + - */} - - 运行步骤 + 操作步骤 - + + + + + + + -
- -
) } diff --git a/src/pages/Suite/components/Case/index.tsx b/src/pages/Suite/components/Case/index.tsx index 9e9a29e79def2f7c344e62bc50590eac714b5b7d..26f5612efc0c5672067f998df382cad1657f3706 100644 --- a/src/pages/Suite/components/Case/index.tsx +++ b/src/pages/Suite/components/Case/index.tsx @@ -15,10 +15,10 @@ type IProps = { } const priorityText = new Map([ - [0, "不可缺少"], + [0, "系统不可缺少"], [1, "重要而不必需"], - [2, "偏一点功能"], - [3, "可靠性等功能"] + [2, "相对非核心功能"], + [3, "系统可靠性等功能"] ]) const Case: React.FC = (props) => { @@ -151,6 +151,10 @@ const Case: React.FC = (props) => { } + + 描述:{currentCase?.desc} + + ({ + id: i, + step: "", + result: "" +}))) + +const type = 'DraggableBodyRow'; + +const DraggableBodyRow = ({ index, moveRow, className, style, ...restProps }: any) => { + const ref = React.useRef(null) as any; + + const [{ isOver, dropClassName }, drop] = useDrop({ + accept: type, + collect: monitor => { + const { index: dragIndex }: any = monitor.getItem() || {}; + if (dragIndex === index) { + return {}; + } + return { + isOver: monitor.isOver(), + dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward', + }; + }, + drop: (item: any) => { + moveRow(item.index, index); + }, + }); + const [, drag] = useDrag({ + type, + item: { index }, + collect: monitor => ({ + isDragging: monitor.isDragging(), + }), + }); + drop(drag(ref)); + + return ( + + ); +}; + +type StepTableProps = { + dataSource: any[]; + onChange: (arr: any) => void +} + +export const OperatStepsTables: React.FC = ({ dataSource, onChange }) => { + const [source, setSource] = React.useState(dataSource && dataSource.length !== 0 ? dataSource : OPERAT_STEP_TABLE_SOURCE) + + const handleFieldChange = (index: any, field: string, value: string) => { + setSource( + source.reduce((pre, cur, idx) => { + if (index === idx) + return pre.concat({ ...cur, [field]: value }) + return pre.concat(cur) + }, []) + ) + } + + React.useEffect(() => { + onChange(source) + }, [source]) + + const columns: TableColumnProps[] = [{ + title: '', + width: 16, + className: 'dragIconWrapper', + render: (_: any, row: any) => ( + + + + ) + }, { + title: "编号", + render(_, row, index) { + return {index + 1} + } + }, { + dataIndex: "step", + title: "步骤描述", + render(_, row, index) { + return ( + handleFieldChange(index, "step", target.value)} + /> + ) + } + }, { + dataIndex: "result", + title: "预期结果", + render(_, row, index) { + return ( + handleFieldChange(index, "result", target.value)} + /> + ) + } + }, { + title: "操作", + render(_, row, idx) { + return remove(idx)}>删除 + } + }] + + const remove = (index: number) => { + setSource(source.filter((i, idx) => idx !== index)) + } + + const add = () => { + const data = source.concat({ desc: "", result: "" }) + setSource(data) + } + + const components = { + body: { + row: DraggableBodyRow, + }, + }; + + const moveRow = React.useCallback( + (dragIndex, hoverIndex) => { + const dragRow = source[dragIndex]; + setSource( + source.reduce((pre, cur, index) => { + if (index === hoverIndex) + return pre.concat(cur, dragRow) + if (index === dragIndex) + return pre + return pre.concat(cur) + }, []) + ); + }, + [source], + ); + + return ( + + + ({ + index, + moveRow, + }) as any} + /> + + + + ) +} export const PrioritySelect: React.FC = () => ( @@ -20,6 +204,181 @@ export const PrioritySelect: React.FC = () => ( ) +const getPaths = (list: any[]) => list.reduce((pre: any[], cur: any): any[] => { + if (cur.children) + return pre.concat(getPaths(cur.children)) + return pre.concat({ label: cur.path, value: cur.id }) +}, []) + +const flatten = (obj: any) => { + console.log(obj) + if (obj && obj.children) + return getPaths(obj.children) + return [] +} + +export const ModuleClassSelect: React.FC = () => { + const { data } = useRequest(() => request(`/api/case/module/tree/0`)) + const paths = flatten(data) + + return ( + + setInp(target.value)} + style={{ width: "70%", marginRight: 12 }} + /> +
+ +
+
+ +
+ + ) + + return ( + <> + + setEditing(true)} + > + + + + {title} + + + ) +} + +export const TagSelect: React.FC = (props) => { + const [pendding, setPendding] = React.useState(false) + + const { data, refresh } = useRequest(() => request(`/api/case/labels/`), { initialData: [] }) + const { run } = useRequest( + (name: string) => request(`/api/case/label/`, { method: "post", data: { name } }), + { manual: true, formatResult(res) { return res } } + ) + + const onOk = async (inp: string, callback: () => void) => { + if (!inp) return + if (pendding) return + setPendding(true) + const res = await run(inp) + const { code, msg } = res + setPendding(false) + if (code !== 200) { + message.error(msg) + return + } + refresh() + callback() + } + + return ( + + ({ ...i, value: i.name, label: i.name })) + } + dropdownRender={ + menu => ( + <> + {menu} + + + ) + } + /> + + ) +} + export const ModuleSelect: React.FC = () => { const { state: { modules }, refreshModules } = useCaseProvider() @@ -98,4 +457,28 @@ export const ModuleSelect: React.FC = () => {
) +} + +const CaseTagStyled = styled.span` + height: 16px; + width: 31px; + border: 1px solid #0085FF; + border-radius: 2px; + margin-right: 2px; + span { + font-size: 10px; + color: #0085FF; + transform: scale(.8); + display: inline-block; + } +` + +export const CaseTag: React.FC = ({ children }) => { + return ( + + + {children} + + + ) } \ No newline at end of file diff --git a/src/pages/Suite/components/LeftList/index.tsx b/src/pages/Suite/components/LeftList/index.tsx index e392b8624d98d4221c766bc458e6eb99c48c417d..4a808f016ea28f9320e309cfb5fd13853bf6fe16 100644 --- a/src/pages/Suite/components/LeftList/index.tsx +++ b/src/pages/Suite/components/LeftList/index.tsx @@ -127,7 +127,7 @@ const LeftList: React.FC = (props) => { const addChildrenItem = (list: any, id: number, level: number, data: any) => { return list.reduce((p: any, c: any) => { if (level === c.level && id === c.id) - return p.concat({ ...c, children_nums: c.children_nums + 1, children: c.children ? c.children.concat(data) : [data] }) + return p.concat({ ...c, children_nums: c.children_nums + 1, children: c.children ? c.children.concat(data) : [].concat(data) }) if (c.children) return p.concat({ ...c, children: addChildrenItem(c.children, id, level, data) }) return p.concat(c) @@ -136,19 +136,22 @@ const LeftList: React.FC = (props) => { const createChildModule = async (row: any) => { if (rename) return + const { id, level } = row const $key = `${id}-${level}` - if (!treeExpanedKeys.includes($key)) { - setTreeExpandedKeys(k => k.concat($key)) - } const $id = `${id}-${level + 1}-新分类` - const newData = addChildrenItem(modules, id, level, { id: $id, name: "新分类", parent: id, level: level + 1, children_nums: 0 }) + const $new = { id: $id, name: "新分类", parent: id, level: level + 1, children_nums: 0 } + setRename(`${$id}-${level + 1}`) + + if (!treeExpanedKeys.includes($key)) + setTreeExpandedKeys(k => k.concat($key)) + + const newData = addChildrenItem(modules, id, level, $new) + dispath({ type: "update", - payload: { - modules: newData - } + payload: { modules: newData } }) } @@ -222,7 +225,6 @@ const LeftList: React.FC = (props) => { justify="space-between" align="middle" active={+mod_id === c.id ? 1 : 0} - > { $key !== rename ? @@ -363,8 +365,11 @@ const LeftList: React.FC = (props) => { if (code !== 200) { return message.error(msg) } - dispath({ type: "update", payload: { modules: data } }) - setTreeExpandedKeys([]) + dispath({ + type: "update", payload: { + modules: modules.concat(data) + } + }) setEdit(false) } diff --git a/src/pages/Suite/components/RightContent/SelectSuiteModal.tsx b/src/pages/Suite/components/RightContent/SelectSuiteModal.tsx index 3e47226548c571ae754cdc5469ba88560c0b911a..904ec7ca44226beba410c39a37da708999d9fb60 100644 --- a/src/pages/Suite/components/RightContent/SelectSuiteModal.tsx +++ b/src/pages/Suite/components/RightContent/SelectSuiteModal.tsx @@ -46,16 +46,7 @@ const SelectSuiteModal: React.ForwardRefRenderFunction = (props, React.useImperativeHandle(ref, () => ({ show(_: any) { - // console.log(_) setIsCheckedCaseKey(_) - // for (let x = 0; x < suiteCases.length; x++) { - // const { test_case_list, id } = suiteCases[x] - // const idx = test_case_list.findIndex((i: any) => i.id === _) - // if (~idx) { - // setTreeExpandedKeys([`${id}-${x}`]) - // break; - // } - // } setVisible(true) } })) @@ -99,15 +90,15 @@ const SelectSuiteModal: React.ForwardRefRenderFunction = (props, children: data.map((item: any) => ({ key: item.tone_case_id, title: () => { - const { suite_id, suite_name, test_type, tone_case_id, tone_name } = item + const { suite_id, suite_name, test_type, tone_case_id, tone_case_name } = item return ( onCheck({ - suite_id, suite_name, test_type, tone_case_id, tone_name + suite_id, suite_name, test_type, tone_case_id, tone_case_name })} > - {item.tone_name} + {tone_case_name} ) }, diff --git a/src/pages/Suite/components/RightContent/SuiteTable.tsx b/src/pages/Suite/components/RightContent/SuiteTable.tsx index 84373c7847c2e083c9bc6c8314a4a37c4d451805..62351cbfc4cf638e6899895f65a45213b845fbbe 100644 --- a/src/pages/Suite/components/RightContent/SuiteTable.tsx +++ b/src/pages/Suite/components/RightContent/SuiteTable.tsx @@ -5,6 +5,7 @@ import { TableColumnProps, Typography } from "antd" import React from "react" import styled from "styled-components" import { priorityColorMap } from "@/pages/Suite/utils" +import { CaseTag } from "@/pages/Suite/components/FormItems" type PriorityLevelColorProps = { color: string; @@ -54,7 +55,11 @@ const SuiteTable: React.FC = (props) => { title: "标签", width: 150, render(row) { - return + if (row.labels !== "") { + const list = row.labels.split(",").map((i: any) => {i}) + return + } + return "-" } }, { title: "优先级", diff --git a/src/pages/Suite/components/RightContent/index.tsx b/src/pages/Suite/components/RightContent/index.tsx index bbb369e30261f91bb6a4ab504950702281523482..3d0f232f0721efd27af71178362399d3640d6ef1 100644 --- a/src/pages/Suite/components/RightContent/index.tsx +++ b/src/pages/Suite/components/RightContent/index.tsx @@ -1,6 +1,6 @@ import React from "react" import { Button, Divider, Empty, Input, Row, Space, Typography, message } from "antd" -import { DownOutlined, UpOutlined } from "@ant-design/icons" +import { DownOutlined, UpOutlined, RightOutlined } from "@ant-design/icons" // import SuiteList from "./SuiteList" @@ -16,7 +16,7 @@ import { useParams } from "umi" import CaseChild from "@/pages/Suite/components/Case" import { useCaseProvider } from "../../provider" import Loading from "@/components/Loading" -import SplitPane, { Pane } from "react-split-pane" +import SplitPane from "react-split-pane" import styled from "styled-components" import { useSize } from "ahooks" import SuiteTable from "./SuiteTable" @@ -91,13 +91,14 @@ const RightContent: React.FC = (props) => { const defaultParams = { mod_id } const { refreshModules, state } = useCaseProvider() - const { modules } = state const [loading, setLoading] = React.useState(true) const [cases, setCases] = React.useState([]) const [selectCases, setSelectCases] = React.useState([]) const [activeCase, setActiveCase] = React.useState(null) + const [source, setSource] = React.useState(undefined) + const [filter, setFilter] = React.useState(false) const [inp, setInp] = React.useState("") @@ -111,12 +112,14 @@ const RightContent: React.FC = (props) => { const getModalCase = async (params: any = pageParams) => { setLoading(true) - const { code, data } = await queryModalCases(params) + const response = await queryModalCases(params) + const { code, data } = response if (code !== 200) { setLoading(false) - return setCases([]) + return } setCases(data) + setSource(response) setLoading(false) } @@ -172,26 +175,35 @@ const RightContent: React.FC = (props) => { message.success('下载成功'); } - const currnetModule = React.useMemo(() => { - if (mod_id) { - const idx = modules.findIndex((i: any) => i.id === +mod_id) - return modules[idx] - } - return null - }, [mod_id, modules]) - const contentRef = React.useRef(null) as any const contentSize = useSize(contentRef) + const currentPath = React.useMemo(() => { + if (!source) return [] + const { path } = source + const list = (path as any).split("/").filter(Boolean) + return list + }, [source]) + return (
+ {currentPath.map((i: string, idx: any) => ( + + + {i} + + { + currentPath.length - 1 > idx && + + } + + ))} - {currnetModule ? `${currnetModule.name}` : `所有用例`} + ({cases.length}) - ({currnetModule ? currnetModule.count : cases.length}) diff --git a/src/pages/Suite/components/ToneCase.tsx b/src/pages/Suite/components/ToneCase.tsx index d2cce59e9cbd5c7fe371ecfddef06986752af195..303901d0c316205c492d0cbfc036368f90185596 100644 --- a/src/pages/Suite/components/ToneCase.tsx +++ b/src/pages/Suite/components/ToneCase.tsx @@ -53,8 +53,8 @@ export const ToneCaseItem: React.FC = (props) => { style={{ maxWidth: size?.width ? size.width - 30 : "unset", marginRight: 4 }} > - {isChecked?.suite_name}: - {isChecked?.tone_name} + {isChecked?.suite_name}: + {isChecked?.tone_case_name} onOk(undefined)} /> diff --git a/src/pages/Suite/utils.ts b/src/pages/Suite/utils.ts index 06729e1eb2c14281b7810d2b8c6def6f2cf5b5e6..451a99c8f9936994050e91fd4b70531961e22e63 100644 --- a/src/pages/Suite/utils.ts +++ b/src/pages/Suite/utils.ts @@ -57,7 +57,10 @@ export const deviceTypeMap = arrayToMap(deviceTypeOptions) export const deviceArchOptions = [ { label: "x86", value: "x86" }, { label: "arch64", value: "arch64" }, - { label: "其他", value: "others" }, + { label: "riscv", value: "risc-v" }, + { label: "loongarch", value: "loongarch" }, + { label: "noarch", value: "noarch" }, + // { label: "其他", value: "others" }, ] export const deviceArchMap = arrayToMap(deviceArchOptions)