diff --git a/src/pages/Outline/components/AddModal.tsx b/src/pages/Outline/components/AddModal.tsx index 6b4464da4dbc23726ce4ff2d40e5836b5ac202a1..40e251e8ebc45333d27566deb38711bc887d60da 100644 --- a/src/pages/Outline/components/AddModal.tsx +++ b/src/pages/Outline/components/AddModal.tsx @@ -94,8 +94,6 @@ const AddOutlineModal: React.ForwardRefRenderFunction = (props, r valuePropName="fileList" name="outline" getValueFromEvent={normFile} - - // extra="" > void; - onCancel?: () => void; + onOk: () => void; + onCancel?: () => void; } type IRefs = { - [k: string]: any + [k: string]: any } const ReactComponent: React.ForwardRefRenderFunction = (props, ref) => { - const { onOk } = props + const {onOk} = props - const [visible, setVisible] = React.useState(false) - const [loading, setLoading] = React.useState(false) - const [source, setSource] = React.useState(undefined) + const [visible, setVisible] = React.useState(false) + const [loading, setLoading] = React.useState(false) + const [source, setSource] = React.useState(undefined) - React.useImperativeHandle(ref, () => ({ - show(_: any) { - setSource(_) - setVisible(true) - form.setFieldsValue(_) - } - })) + const uploadProps = { + action: "", + method: 'post', + accept: '.xls,.xlsx', + }; - const [form] = Form.useForm() - - const handleCancel = () => { - setVisible(false) - setLoading(false) - setSource(undefined) + React.useImperativeHandle(ref, () => ({ + show(_: any) { + setSource(_) + setVisible(true) + form.setFieldsValue(_) } + })) - const handleOk = async () => { - if (loading) return - setLoading(true) - onOk() - handleCancel() - } + const [form] = Form.useForm() + + const handleCancel = () => { + setVisible(false) + setLoading(false) + setSource(undefined) + } + + const handleOk = async () => { + if (loading) return + setLoading(true) + onOk() + handleCancel() + } - const uploadProps = { - name: 'file', - action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76', - headers: { - authorization: 'authorization-text', - }, - onChange(info: any) { - if (info.file.status !== 'uploading') { - console.log(info.file, info.fileList); - } - if (info.file.status === 'done') { - message.success(`${info.file.name} file uploaded successfully`); - } else if (info.file.status === 'error') { - message.error(`${info.file.name} file upload failed.`); - } - }, - }; + const downloadTemplate = async () => { + const data = await downloadCaseTempFile() + const fileAppType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + const blob = new Blob([data], { + type: fileAppType, + }); + const objectURL = URL.createObjectURL(blob); + const btn = document.createElement('a'); + btn.download = '模板文件.xlsx'; + btn.href = objectURL; + btn.click(); + URL.revokeObjectURL(objectURL); + message.success('下载成功'); + } - return ( - - - - - } - onCancel={handleCancel} - onOk={handleOk} - > - - 1. - - 下载表格模板 - 下载表格后,将用例内容按照格式填入表格中 - - - - - 2. - - 选择用例文件 - 系统会按照第一个工作表里的格式读取数据,请保证整个文件格式正确 - - - - - 支持扩展名:.xlsx - - - - - ) + return ( + + + + + } + onCancel={handleCancel} + onOk={handleOk} + > + + 1. + + 下载表格模板 + 下载表格后,将用例内容按照格式填入表格中 + + + + + 2. + + 选择用例文件 + 系统会按照第一个工作表里的格式读取数据,请保证整个文件格式正确 + + + + + 支持扩展名:.xlsx + + + + + ) } -export default React.forwardRef(ReactComponent) \ No newline at end of file +export default React.forwardRef(ReactComponent) diff --git a/src/pages/Suite/components/RightContent/index.tsx b/src/pages/Suite/components/RightContent/index.tsx index a578636a0fe6a0f2e242b20456816d01fa70527e..16a9c4f50a992f500b355a5937a0474d683b76a6 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 { Space, Row, Typography, Button, Card, Input, Divider, Spin, Empty } from "antd" -import { DownOutlined, UpOutlined } from "@ant-design/icons" +import {Button, Divider, Empty, Input, Row, Space, Spin, Typography} from "antd" +import {DownOutlined, UpOutlined} from "@ant-design/icons" import SuiteList from "./SuiteList" @@ -10,220 +10,230 @@ import FilterForm from "./FilterForm" import AddModal from "../AddModal" import ExportCase from "./ExportCase" -import { createCases, queryCases, queryModalCases } from "../../services" -import { useParams } from "umi" +import {exportCases, queryCases, queryModalCases} from "../../services" +import {useParams} from "umi" import CaseChild from "@/pages/Suite/components/Case" -import { useCaseProvider } from "../../provider" +import {useCaseProvider} from "../../provider" +import {message} from "_antd@4.19.5@antd"; type IProps = { - [k: string]: any + [k: string]: any } const RightContent: React.FC = (props) => { - const { mod_id } = useParams() as any - const defaultParams = { mod_id } + const {mod_id} = useParams() as any + const defaultParams = {mod_id} - const { refreshModules, state } = useCaseProvider() + const {refreshModules, state} = useCaseProvider() - const { modules, caseCount } = state + const {modules, caseCount} = state - const [loading, setLoading] = React.useState(true) - const [cases, setCases] = React.useState([]) - const [selectCases, setSelectCases] = React.useState([]) - const [activeCase, setActiveCase] = React.useState(null) + const [loading, setLoading] = React.useState(true) + const [cases, setCases] = React.useState([]) + const [selectCases, setSelectCases] = React.useState([]) + const [activeCase, setActiveCase] = React.useState(null) - const [filter, setFilter] = React.useState(false) - const [inp, setInp] = React.useState("") + const [filter, setFilter] = React.useState(false) + const [inp, setInp] = React.useState("") - const batchMoveRef = React.useRef(null) as any - const batchDeleteRef = React.useRef(null) as any - const createCaseRef = React.useRef(null) as any - const exportCaseRef = React.useRef(null) as any + const batchMoveRef = React.useRef(null) as any + const batchDeleteRef = React.useRef(null) as any + const createCaseRef = React.useRef(null) as any + const exportCaseRef = React.useRef(null) as any - const [pageParams, setPageParams] = React.useState(defaultParams) + const [pageParams, setPageParams] = React.useState(defaultParams) - const handleExportOk = () => { - refreshModules() - } + const handleExportOk = () => { + refreshModules() + } - const getModalCase = async (params: any) => { - setLoading(true) - const { code, msg, data } = await queryModalCases(params) - if (code !== 200) { - setLoading(false) - return setCases([]) - } - setCases(data) - if (data.length > 0) { - if (activeCase && activeCase.id) { - const idx = data.findIndex((i: any) => i.id === activeCase.id) - if (!idx) - setActiveCase(data[idx]) - } - else - setActiveCase(data[0]) - } - setLoading(false) + const getModalCase = async (params: any) => { + setLoading(true) + const {code, msg, data} = await queryModalCases(params) + if (code !== 200) { + setLoading(false) + return setCases([]) } - - console.log(activeCase) - - React.useEffect(() => { - getModalCase({ mod_id }) - - return () => { - setCases([]) - setLoading(true) - setSelectCases([]) - setPageParams(defaultParams) - setFilter(false) - } - }, [mod_id]) - - const handleMoveOk = () => { - getModalCase(defaultParams) - setSelectCases([]) + setCases(data) + if (data.length > 0) { + if (activeCase && activeCase.id) { + const idx = data.findIndex((i: any) => i.id === activeCase.id) + if (!idx) + setActiveCase(data[idx]) + } else + setActiveCase(data[0]) } + setLoading(false) + } - const handleDeleteOk = () => { - getModalCase(defaultParams) - setSelectCases([]) - } - - const handleCreateOk = () => { - getModalCase(defaultParams) - refreshModules() - } + console.log(activeCase) - const getFilterCase = async (params: any) => { - const { code, msg, data } = await queryCases(params) - if (code !== 200) { - return - } + React.useEffect(() => { + getModalCase({mod_id}) - setCases(data) + return () => { + setCases([]) + setLoading(true) + setSelectCases([]) + setPageParams(defaultParams) + setFilter(false) } - - const handleOkFilter = (vals: any) => { - console.log(vals) - getFilterCase({ ...vals, key: inp }) - // getModalCase(vals) + }, [mod_id]) + + const handleMoveOk = () => { + getModalCase(defaultParams) + setSelectCases([]) + } + + const handleDeleteOk = () => { + getModalCase(defaultParams) + setSelectCases([]) + } + + const handleCreateOk = () => { + getModalCase(defaultParams) + refreshModules() + } + + const getFilterCase = async (params: any) => { + const {code, msg, data} = await queryCases(params) + if (code !== 200) { + return } - const exportExcel = () => { - const api = `/api/case/export/` - window.open(api) + setCases(data) + } + + const handleOkFilter = (vals: any) => { + console.log(vals) + getFilterCase({...vals, key: inp}) + // getModalCase(vals) + } + + const exportExcel = async () => { + const data = await exportCases(selectCases) + const fileAppType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + const blob = new Blob([data], { + type: fileAppType, + }); + const objectURL = URL.createObjectURL(blob); + const btn = document.createElement('a'); + btn.download = `${Date.parse(new Date().toString())}.xlsx`; + btn.href = objectURL; + btn.click(); + URL.revokeObjectURL(objectURL); + message.success('下载成功'); + } + + const currnetModule = React.useMemo(() => { + if (mod_id) { + const idx = modules.findIndex((i: any) => i.id === +mod_id) + return modules[idx] } - - 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]) - - return ( -
-
- - - - {currnetModule ? `${currnetModule.name}` : `所有用例`} - - ({currnetModule ? currnetModule.count : cases.length}) - - - - - - - - - - - - - - - - - setInp(target.value)} - onSearch={() => handleOkFilter({ key: inp })} - /> - setFilter(!filter)}> + return null + }, [mod_id, modules]) + + return ( +
+
+ + + + {currnetModule ? `${currnetModule.name}` : `所有用例`} + + ({currnetModule ? currnetModule.count : cases.length}) + + + + + + + + + + + + + + + + + setInp(target.value)} + onSearch={() => handleOkFilter({key: inp})} + /> + setFilter(!filter)}> 筛选 - { - filter ? - : - - } + { + filter ? + : + + } - - - - { - filter && - - } - - - - { - cases.length === 0 ? - : - - - getModalCase(defaultParams)} - /> - - } -
- - { - loading && -
- -
- } - - - - - - + + + + { + filter && + + } + + + + { + cases.length === 0 ? + : + + + getModalCase(defaultParams)} + /> + + } +
+ + { + loading && +
+
- ) + } + + + + + + +
+ ) } -export default RightContent \ No newline at end of file +export default RightContent diff --git a/src/pages/Suite/services.ts b/src/pages/Suite/services.ts index 5227b9a9f287411bfaa001795e66318ad160133c..c8f6066bb0d8aa04acb38b61c1aafa95be209b7c 100644 --- a/src/pages/Suite/services.ts +++ b/src/pages/Suite/services.ts @@ -1,119 +1,122 @@ -import { request } from "umi" +import {request} from "umi" export type ICase = { - name: string; - run_method: "manual" | "auto"; - run_model: "single" | "cluster"; - is_available: boolean; - base_fields: any; - tone_case?: any; - custom_field?: any; - parent?: any + name: string; + run_method: "manual" | "auto"; + run_model: "single" | "cluster"; + is_available: boolean; + base_fields: any; + tone_case?: any; + custom_field?: any; + parent?: any } //新增测试用例 export const createCases = async (data: ICase) => { - return request(`/api/case/create/`, { method: "post", data }) + return request(`/api/case/create/`, {method: "post", data}) } export type IModal = { - mod_id: any; - page_num?: any; - page_size?: any; + mod_id: any; + page_num?: any; + page_size?: any; } //查个每个模块下的测试用例 export const queryModalCases = async (params: IModal) => { - return request(`/api/case/`, { method: "get", params }) + return request(`/api/case/`, {method: "get", params}) } //重命名测试用例 export const renameCase = async (case_id: any, data: { name: string }) => { - return request(`/api/case/rename/${case_id}`, { method: "post", data }) + return request(`/api/case/rename/${case_id}`, {method: "post", data}) } //批量删除测试用例 export const deleteCases = async (params: { id: any }) => { - return request(`/api/case/`, { method: "delete", params }) + return request(`/api/case/`, {method: "delete", params}) } //移动测试用例 export const moveCase = async (data: { parent: any, cases: any[] }) => { - return request(`/api/case/move`, { method: "post", data }) + return request(`/api/case/move`, {method: "post", data}) } //更新测试用例 export const updateCase = async (case_id: string, data: ICase) => { - return request(`/api/case/edit/${case_id}`, { method: "post", data }) + return request(`/api/case/edit/${case_id}`, {method: "post", data}) } export type IModule = { - name: string; - level?: any; - parent?: any; + name: string; + level?: any; + parent?: any; } //创建分类模块 export const createModule = async (data: IModule) => { - return request(`/api/case/module/create`, { method: "post", data }) + return request(`/api/case/module/create`, {method: "post", data}) } //获得某一模块写的所有子模块 export const queryModuleCase = async (node_id: any) => { - return request(`/api/case/module/${node_id}`) + return request(`/api/case/module/${node_id}`) } //根据前缀获得相同前缀的所有模块名称 export const queryModuleName = async (params: { start?: string }) => { - return request(`/api/case/modules`, { params }) + return request(`/api/case/modules`, {params}) } //重命名模块名称 export const renameModule = async (mod_id: any, data: { name: string }) => { - return request(`/api/case/module/rename/${mod_id}`, { method: "post", data }) + return request(`/api/case/module/rename/${mod_id}`, {method: "post", data}) } //移动模块路径 export const moveMudal = async (mod_id: any, data: { level: any, parent: any }) => { - return request(`/api/case/module/move/${mod_id}`, { method: "post", data }) + return request(`/api/case/module/move/${mod_id}`, {method: "post", data}) } //删除模块(只删除模块,模块用例移动到删除模块的父模块下) export const deleteModule = async (mod_id: string) => { - return request(`/api/case/module/${mod_id}`, { method: "delete" }) -} - -//导出测试用例为excel(.xlsx)类型 -export const exportExcelCase = async (data: { cases: any }) => { - return request(`/api/case/export/`, { method: "post", data }) + return request(`/api/case/module/${mod_id}`, {method: "delete"}) } //从excel导入测试用例(只支持.xls,.xlsx) export const importExcelCase = async (data: { excel: any }) => { - return request(`/api/case/import/`, { method: "post", data }) + return request(`/api/case/import/`, {method: "post", data}) } type CaseSearchQuery = { - key: string; //查找的关键词 - page_size?: number;//页面大小,默认1 - page_num?: number;// 分页页数,默认50 - type?: string;//测试用例类型,功能测试,性能测试,默认全部 - run_method?: string;// 用例执行方式,默认全选 - run_model?: string;// 用例运行模式,默认全选 - is_available?: boolean;// 用例是否可用,默认全选 - device_type?: string;// 用例执行机器类型,默认全选 - creator?: string;// 创建人,默认不区分 - start_time?: string;// 开始时间 - end_time?: string;// 结束时间 + key: string; //查找的关键词 + page_size?: number;//页面大小,默认1 + page_num?: number;// 分页页数,默认50 + type?: string;//测试用例类型,功能测试,性能测试,默认全部 + run_method?: string;// 用例执行方式,默认全选 + run_model?: string;// 用例运行模式,默认全选 + is_available?: boolean;// 用例是否可用,默认全选 + device_type?: string;// 用例执行机器类型,默认全选 + creator?: string;// 创建人,默认不区分 + start_time?: string;// 开始时间 + end_time?: string;// 结束时间 } //查找用例 export const queryCases = async (params: CaseSearchQuery) => { - return request(`/api/case/search/`, { params }) + return request(`/api/case/search/`, {params}) } export const querySuiteCase = async (params: any) => { - return request(`/tone/api/case/workspace/case/`, { params: { ...params, ws_id: "s63u44w7" } }) + return request(`/tone/api/case/workspace/case/`, {params: {...params, ws_id: "s63u44w7"}}) } export const queryDomainList = async (params: any) => { - return request(`/tone/api/case/test_domain/?test_type=domainconf`) -} \ No newline at end of file + return request(`/tone/api/case/test_domain/?test_type=domainconf`) +} + +export const downloadCaseTempFile = async () => { + return request(`/api/case/export`, {method: 'get', responseType: 'blob'}) +} + +export const exportCases = async (cases: any) => { + return request(`/api/case/export`, {method: 'get', params: {case: cases}, responseType: 'blob'}) +}