index.jsx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. import React, { useEffect, useRef, useState } from 'react';
  2. import { Form, Row, Col, Card, Modal, Input, Select, Upload, Button, message } from 'antd';
  3. import { connect } from 'umi';
  4. import styles from './index.less';
  5. import {
  6. ForkOutlined,
  7. PlusOutlined,
  8. ExclamationCircleFilled,
  9. UploadOutlined,
  10. EditOutlined,
  11. EyeOutlined,
  12. } from '@ant-design/icons';
  13. import { recurrent, severity, bug_categories } from './const';
  14. const formItemLayout = {
  15. labelCol: {
  16. span: 5,
  17. },
  18. wrapperCol: {
  19. span: 19,
  20. },
  21. };
  22. const Step2 = (props) => {
  23. const [form] = Form.useForm();
  24. const [addCaseForm] = Form.useForm();
  25. const [addBugForm] = Form.useForm();
  26. const { data, dispatch, reportCommonInfo, testCaseList, caseBugList,categories } = props;
  27. const [showTaskRecommendModal, setTaskRecommendModal] = useState(false);
  28. const [showAddTestCaseModal, setAddTestCaseModal] = useState(false);
  29. const [showAddBugModal, setAddTestBugModal] = useState(false);
  30. const currentTestCaseRef = useRef({});
  31. const [isAddCaseStatus, setIsAddCaseStatus] = useState(true);
  32. const [currActiveTestCase, setCurrActiveTestCase] = useState({});
  33. if (!data) {
  34. return null;
  35. }
  36. const handleAddOrEditTestCase = () => {
  37. addCaseForm.validateFields().then((res) => {
  38. let formData = new FormData();
  39. // formData.append("id", values.reportName);
  40. formData.append('report_id', reportCommonInfo.id);
  41. formData.append('name', res.name);
  42. formData.append('front', res.front);
  43. formData.append('behind', res.behind);
  44. formData.append('description', res.description);
  45. if (!isAddCaseStatus) {
  46. //处理编辑用例
  47. formData.append('id', currentTestCaseRef.current.id);
  48. dispatch({
  49. type: 'editReport/updateTestCase',
  50. payload: {
  51. formData,
  52. report_id: reportCommonInfo.id,
  53. },
  54. }).then((res) => {
  55. if (res && res.status === 200) {
  56. message.success('修改成功!');
  57. }
  58. });
  59. } else {
  60. //处理添加用例
  61. dispatch({
  62. type: 'editReport/createTestCase',
  63. payload: {
  64. formData,
  65. report_id: reportCommonInfo.id,
  66. },
  67. }).then((res) => {
  68. if (res && res.id) {
  69. message.success('添加成功!');
  70. }
  71. });
  72. }
  73. setAddTestCaseModal(false);
  74. });
  75. };
  76. const handleAddBug = () => {
  77. addBugForm.validateFields().then((res) => {
  78. console.log(res);
  79. let formData = new FormData();
  80. formData.append('report_id', reportCommonInfo.id);
  81. formData.append('name', res.name);
  82. formData.append('front', res.front);
  83. formData.append('behind', res.behind);
  84. formData.append('description', res.description);
  85. });
  86. // if (true) {
  87. // //新建bug的逻辑
  88. // setAddTestBugModal(true);
  89. // dispatch({
  90. // type: 'editReport/createTestCase',
  91. // payload: {
  92. // report_id:reportCommonInfo.id
  93. // },
  94. // }).then((res)=>{
  95. // if(res&&res.id){
  96. // message.success('添加成功!');
  97. // }
  98. // });
  99. // } else {
  100. // //编辑bug的逻辑
  101. // }
  102. };
  103. const handleClickTestCase = (caseItem) => {
  104. setCurrActiveTestCase(caseItem);
  105. dispatch({
  106. type: 'editReport/getCaseBugList',
  107. payload: caseItem.id,
  108. });
  109. };
  110. const handleEditTestCase = (item) => {
  111. setIsAddCaseStatus(false);
  112. currentTestCaseRef.current = item;
  113. addCaseForm.setFieldsValue(currentTestCaseRef.current);
  114. setAddTestCaseModal(true);
  115. };
  116. const handleClickAddCase = () => {
  117. currentTestCaseRef.current = {};
  118. addCaseForm.resetFields();
  119. setAddTestCaseModal(true);
  120. };
  121. // const handleEditBug = (item) => {
  122. // setIsAddCaseStatus(false);
  123. // currentTestCaseRef.current = item;
  124. // addBugForm.setFieldsValue(currentTestCaseRef.current)
  125. // setAddTestCaseModal(true);
  126. // };
  127. const handleClickAddBug = () => {
  128. addBugForm.resetFields();
  129. setAddTestBugModal(true);
  130. };
  131. useEffect(() => {
  132. //判断是否已经有报告
  133. dispatch({
  134. type: 'editReport/getReportInfo',
  135. payload: {
  136. case_take_id: '1718-1718',
  137. worker_id: 1,
  138. },
  139. }).then(() => {
  140. //有报告,获取对应信息。没有就直接转去了第一步
  141. dispatch({
  142. type: 'editReport/getTestCaseList',
  143. payload: { report_id: reportCommonInfo.id },
  144. });
  145. dispatch({
  146. type: 'editReport/getCategories',
  147. payload: { examId: 1945 },
  148. });
  149. });
  150. }, [dispatch]);
  151. return (
  152. <div>
  153. <Form
  154. {...formItemLayout}
  155. form={form}
  156. layout="horizontal"
  157. className={styles.stepForm}
  158. hideRequiredMark
  159. initialValues={data}
  160. >
  161. <Row gutter={10}>
  162. <Col span={5}>
  163. <Form.Item label="创建日期" rules={[{ required: true, message: '请输入报告名称' }]}>
  164. {'2021.4.12'}
  165. </Form.Item>
  166. </Col>
  167. <Col span={5}>
  168. <Form.Item label="报告名称" rules={[{ required: true, message: '请输入报告名称' }]}>
  169. {reportCommonInfo.name}
  170. </Form.Item>
  171. </Col>
  172. <Col span={5}>
  173. <Form.Item label="设备名称" required>
  174. {reportCommonInfo.device_brand}
  175. </Form.Item>
  176. </Col>
  177. <Col span={5}>
  178. <Form.Item label="设备品牌" required>
  179. {reportCommonInfo.device_model}
  180. </Form.Item>
  181. </Col>
  182. <Col span={4}>
  183. <Form.Item label="操作系统" required>
  184. {reportCommonInfo.device_os}
  185. </Form.Item>
  186. </Col>
  187. </Row>
  188. </Form>
  189. <Card>
  190. <div className={styles.reportContainer}>
  191. <Row gutter={10}>
  192. <Col span={8}>
  193. <div>
  194. <Row gutter={10} style={{ marginBottom: 10 }}>
  195. <Col span={20}><h3>测试用例列表</h3></Col>
  196. <Col span={4}>
  197. <Button size="small" onClick={() => {
  198. handleClickAddCase();
  199. }}>
  200. <PlusOutlined className={styles.addIcon} />
  201. 用例
  202. </Button>
  203. </Col>
  204. </Row>
  205. </div>
  206. <div className={styles.testCaseList}>
  207. {testCaseList && testCaseList.map((item) => {
  208. return (
  209. <div
  210. className={`${styles.testCaseItem} ${currActiveTestCase.id === item.id ? styles.activeCase : ''}`}
  211. key={item.id}
  212. onClick={() => {
  213. handleClickTestCase(item);
  214. }}>
  215. <Row gutter={10}>
  216. <Col span={21}><p>{item.name}</p></Col>
  217. <Col span={3}>
  218. <EditOutlined className={styles.editTestBug}
  219. onClick={() => handleEditTestCase(item)} />
  220. </Col>
  221. </Row>
  222. </div>);
  223. })}
  224. </div>
  225. </Col>
  226. <Col span={16} style={{ paddingLeft: 20 }}>
  227. <Row gutter={10} style={{ marginBottom: 10 }}>
  228. <Col span={20}><h3>缺陷列表</h3></Col>
  229. <Col span={2}>
  230. <Button size="small" onClick={() => handleClickAddBug()}>
  231. <PlusOutlined className={styles.addIcon} />
  232. 缺陷
  233. </Button>
  234. </Col>
  235. <Col span={2}>
  236. <Button size="small" onClick={() => setTaskRecommendModal(true)}>
  237. <ForkOutlined className={styles.addIcon} />
  238. 推荐
  239. </Button>
  240. </Col>
  241. </Row>
  242. <div className={styles.testBugList}>
  243. {caseBugList.map((item) => {
  244. return (
  245. <div className={styles.testBugItem} key={item.detail.id}>
  246. <Row gutter={10}>
  247. <Col span={20}>
  248. <div><span className={styles.bugItemTitle}>Bug标题:</span>{item.detail.title}</div>
  249. <div><span className={styles.bugItemTitle}>复现程度:</span>{recurrent.get(item.detail.recurrent)}</div>
  250. <div><span className={styles.bugItemTitle}>严重程度:</span>{item.detail.severity}</div>
  251. <div><span className={styles.bugItemTitle}>缺陷分类:</span>{severity.get(item.detail.bug_category)}
  252. </div>
  253. </Col>
  254. <Col span={4}>
  255. <Button size='small' style={{ marginTop: 10 }}>
  256. <EyeOutlined />详情</Button>
  257. </Col>
  258. </Row>
  259. </div>
  260. );
  261. })}
  262. </div>
  263. </Col>
  264. </Row>
  265. </div>
  266. </Card>
  267. <Modal title={isAddCaseStatus ? '添加测试用例' : '编辑测试用例'} width={720}
  268. visible={showAddTestCaseModal}
  269. forceRender={true}
  270. className="addModal"
  271. footer={[
  272. <Button key='submit' type="primary" htmlType="submit" onClick={handleAddOrEditTestCase}>确定</Button>,
  273. <Button key='cancel' htmlType="button" style={{ marginLeft: '10px' }}
  274. onClick={() => {
  275. setAddTestCaseModal(false);
  276. }}>取消</Button>]}
  277. onCancel={() => {
  278. setAddTestCaseModal(false);
  279. }}
  280. >
  281. <ExclamationCircleFilled className={styles.addModalInfo} />为了评分准确,请勿提交重复测试用例
  282. <Form
  283. {...formItemLayout}
  284. form={addCaseForm}
  285. layout="horizontal"
  286. className={styles.stepForm}
  287. >
  288. <Form.Item
  289. label="用例名称"
  290. name="name"
  291. rules={[
  292. {
  293. required: true,
  294. message: '请输入用例名称!',
  295. },
  296. ]}
  297. >
  298. <Input />
  299. </Form.Item>
  300. <Form.Item
  301. label="前置条件"
  302. name="front"
  303. rules={[
  304. {
  305. required: true,
  306. message: '请输入前置条件!',
  307. },
  308. ]}
  309. >
  310. <Input.TextArea autoSize={{ minRows: 3, maxRows: 999 }} />
  311. </Form.Item>
  312. <Form.Item
  313. label="测试步骤"
  314. name="behind"
  315. rules={[
  316. {
  317. required: true,
  318. message: '请输入测试步骤!',
  319. },
  320. ]}
  321. >
  322. <Input.TextArea autoSize={{ minRows: 3, maxRows: 999 }} />
  323. </Form.Item>
  324. <Form.Item
  325. label="预期结果"
  326. name="description"
  327. rules={[
  328. {
  329. required: true,
  330. message: '请输入预期结果!',
  331. },
  332. ]}
  333. >
  334. <Input.TextArea autoSize={{ minRows: 3, maxRows: 999 }} />
  335. </Form.Item>
  336. </Form>
  337. </Modal>
  338. <Modal title="添加用例缺陷" visible={showAddBugModal} width={720}
  339. footer={[
  340. <Button key='submit' type="primary" htmlType="submit" onClick={handleClickAddBug}>确定</Button>,
  341. <Button key='cancel' htmlType="button" style={{ marginLeft: '10px' }}
  342. onClick={() => { handleAddBug();}}>取消</Button>]}
  343. onCancel={() => {
  344. setAddTestBugModal(false);
  345. }}
  346. >
  347. <ExclamationCircleFilled className={styles.addModalInfo} />为了评分准确,请勿提交重复Bug
  348. <Form
  349. labelCol={{ span: 4 }}
  350. form={addBugForm}
  351. {...formItemLayout}
  352. layout="horizontal"
  353. className={styles.stepForm}
  354. >
  355. <Form.Item
  356. label="测试题目"
  357. name="testName"
  358. rules={[
  359. {
  360. required: true,
  361. message: '请输入测试题目!',
  362. },
  363. ]}
  364. >
  365. <Input />
  366. </Form.Item>
  367. <Form.Item
  368. label="前置条件"
  369. name="precondition"
  370. rules={[
  371. {
  372. required: true,
  373. message: '请输入前置条件!',
  374. },
  375. ]}
  376. >
  377. <Input.TextArea autoSize />
  378. </Form.Item>
  379. <Form.Item
  380. label="三级页面"
  381. name="pages"
  382. rules={[
  383. {
  384. required: true,
  385. message: '请确保输入了三级页面',
  386. },
  387. ]}
  388. >
  389. <Row gutter={5}>
  390. <Col span={8}>
  391. <Select>
  392. {categories.map((item)=>{
  393. return <Select.Option value="demo" key={item.item}>{item.item}</Select.Option>
  394. })}
  395. </Select>
  396. </Col>
  397. <Col span={8}>
  398. <Select>
  399. <Select.Option value="demo">Demo2</Select.Option>
  400. </Select>
  401. </Col>
  402. <Col span={8}>
  403. <Select>
  404. <Select.Option value="demo">Demo3</Select.Option>
  405. </Select>
  406. </Col>
  407. </Row>
  408. </Form.Item>
  409. <Form.Item
  410. label="漏洞分类"
  411. name="bugType"
  412. rules={[
  413. {
  414. required: true,
  415. message: '请输入漏洞分类!',
  416. },
  417. ]}
  418. >
  419. <Select>
  420. <Select.Option value="demo">Demo</Select.Option>
  421. </Select>
  422. </Form.Item>
  423. <Form.Item
  424. label="严重等级"
  425. name="service"
  426. rules={[
  427. {
  428. required: true,
  429. message: '请输入严重等级!',
  430. },
  431. ]}
  432. >
  433. <Select>
  434. <Select.Option value="demo">Demo</Select.Option>
  435. </Select>
  436. </Form.Item>
  437. <Form.Item
  438. label="复现程度"
  439. name="recurrent"
  440. rules={[
  441. {
  442. required: true,
  443. message: '请输入测试题目!',
  444. },
  445. ]}
  446. >
  447. <Select>
  448. <Select.Option value="demo">Demo</Select.Option>
  449. </Select>
  450. </Form.Item>
  451. {/*<Form.Item*/}
  452. {/* label="上传截图"*/}
  453. {/* name="testName"*/}
  454. {/*>*/}
  455. {/* <Upload*/}
  456. {/* action="https://www.mocky.io/v2/5cc8019d300000980a055e76"*/}
  457. {/* listType="picture"*/}
  458. {/* >*/}
  459. {/* <Button icon={<UploadOutlined />}>Upload</Button>*/}
  460. {/* </Upload>*/}
  461. {/*</Form.Item>*/}
  462. </Form>
  463. </Modal>
  464. <Modal title="任务推荐" visible={showTaskRecommendModal} onOk={() => setTaskRecommendModal(false)}
  465. onCancel={() => setTaskRecommendModal(false)} className="addModal">
  466. <div>
  467. <div id="forceChart"></div>
  468. </div>
  469. </Modal>
  470. </div>
  471. );
  472. };
  473. export default connect(({ editReport, loading }) => ({
  474. submitting: loading.effects['editReport/submitStepForm'],
  475. data: editReport.step,
  476. reportCommonInfo: editReport.reportCommonInfo,
  477. testCaseList: editReport.testCaseList,
  478. caseBugList: editReport.caseBugList,
  479. categories:editReport.categories
  480. }))(Step2);