Example.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. <template>
  2. <div class="table-container">
  3. <!-- 用例模块 -->
  4. <div class="deviceExamples">
  5. <!-- 用例 -->
  6. <div class="title-container">
  7. <div class="title-main">用例</div>
  8. <div class="title-right">
  9. <div class="check-resaults">
  10. 总数:
  11. <span class="total">
  12. {{ unitsData.total }}
  13. </span>
  14. </div>
  15. <div class="check-resaults">
  16. 成功数:
  17. <span class="success">
  18. {{ unitsData.successful }}
  19. </span>
  20. </div>
  21. <div class="check-resaults">
  22. 失败数:
  23. <span class="faild">
  24. {{ unitsData.failed }}
  25. </span>
  26. </div>
  27. <div class="check-resaults">
  28. <el-button
  29. icon="el-icon-refresh"
  30. class="light-button"
  31. size="mini"
  32. @click="refreshManual(true)"
  33. >刷新</el-button>
  34. </div>
  35. <div class="check-resaults">
  36. <el-button class="light-button" icon="el-icon-file" size="mini" @click="openFileTransfer()">文件传输</el-button>
  37. </div>
  38. <div class="check-resaults">
  39. <el-button
  40. icon="el-icon-document"
  41. class="light-button"
  42. size="mini"
  43. @click="checkReport()"
  44. >查看报文</el-button>
  45. </div>
  46. <div class="check-resaults">
  47. <el-button
  48. type="primary"
  49. icon="el-icon-plus"
  50. size="mini"
  51. :disabled="componentParames.isDisable"
  52. @click="editRow()"
  53. >添加</el-button>
  54. </div>
  55. </div>
  56. </div>
  57. <!-- 用例表格 -->
  58. <div class="table-data">
  59. <!-- {
  60. "id": "2300000037",
  61. "name": null,
  62. "suiteId": null,
  63. "planId": "3200000028",
  64. "ruleId": 102,
  65. "ruleName": "读开关量",
  66. "not": null,
  67. "value": null,
  68. "error": null,
  69. "params": {}
  70. } -->
  71. <el-table :key="tableIsUpdate" v-loading="vloading" :data="tableData" stripe>
  72. <el-table-column prop="id" label="序号" width="100px" />
  73. <el-table-column prop="name" label="用例名称" width="150px" />
  74. <el-table-column prop="state" label="测试状态" width="120px">
  75. <template slot-scope="scope">
  76. <span :style="{'color':scope.row.stateStyle}">{{ scope.row.state }}</span>
  77. </template>
  78. </el-table-column>
  79. <el-table-column v-if="false" prop="ruleName" label="测试规则" width="135px" />
  80. <el-table-column prop="occur" label="执行时间" width="160px" />
  81. <el-table-column prop="duration" label="持续时间(ms)" width="135px" />
  82. <!-- 鲜总说不要了 06.测试/20230704/设备检测用例相关改动.png
  83. <el-table-column prop="not" label="规则取反" width="75px" :formatter="formatBool" />
  84. <el-table-column prop="value" label="期望值" width="75px" />
  85. <el-table-column prop="error" label="误差范围" width="75px" /> -->
  86. <el-table-column prop="unit" label="循环次数" width="150px">
  87. <template slot-scope="scope">
  88. <!-- 总数/成功数/失败数 -->
  89. <ul v-if="scope.row.unit" class="unit">
  90. <li>
  91. <div class="unit-title">总数:</div>
  92. <div class="unit-value total">{{ scope.row.unit.total }}</div>
  93. </li>
  94. <li>
  95. <div class="unit-title">成功数:</div>
  96. <div class="unit-value successful">{{ scope.row.unit.successful }}</div>
  97. </li>
  98. <li>
  99. <div class="unit-title">失败数:</div>
  100. <div class="unit-value failed">{{ scope.row.unit.failed }}</div>
  101. </li>
  102. </ul>
  103. </template>
  104. </el-table-column>
  105. <el-table-column prop="params" label="参数设置">
  106. <template slot-scope="scope">
  107. <ul class="setting-json">
  108. <li
  109. v-for="(settingItem) in scope.row.params"
  110. :key="settingItem.id "
  111. >
  112. <div>{{ settingItem.id }}({{ settingItem.name }}):{{ settingItem.value || 0 }}</div>
  113. <!-- <span v-if="index < scope.row.params.length - 1">,</span> -->
  114. </li>
  115. </ul>
  116. </template>
  117. </el-table-column>
  118. <el-table-column fixed="right" label="操作" width="120px">
  119. <template slot-scope="scope">
  120. <el-button
  121. class="table-act"
  122. type="text"
  123. icon="el-icon-edit"
  124. size="small"
  125. @click="editRow(scope.$index)"
  126. >编辑</el-button>
  127. <el-button
  128. class="table-act"
  129. type="text"
  130. icon="el-icon-delete"
  131. size="small"
  132. @click="delRow(scope.$index)"
  133. >删除</el-button>
  134. </template>
  135. </el-table-column>
  136. <!-- 隐藏 列 这里不用显示,但是在编辑的时候需要获取此数据 -->
  137. <el-table-column
  138. v-if="false"
  139. prop="deviceCheckId"
  140. label="序号"
  141. />
  142. <!-- 隐藏 列 -->
  143. </el-table>
  144. </div>
  145. <!-- 用例分页 -->
  146. <div class="page-bar">
  147. <pagination
  148. background
  149. layout="pager"
  150. :limit="deviceExamples.pageLimit"
  151. :total="deviceExamples.paginationTotalElements"
  152. :current-page.sync="deviceExamples.paginationNumber"
  153. :page="deviceExamples.paginationNumber"
  154. :auto-scroll="false"
  155. @pagination="getDeviceExamples"
  156. />
  157. </div>
  158. </div>
  159. <!-- 查看报文 model -->
  160. <ModelReport
  161. v-if="showModelReport"
  162. :report-parames="{
  163. 'deviceName':componentParames.deviceName,
  164. 'curPlanId':componentParames.curPlanId
  165. }"
  166. @toggleModel="closeModel"
  167. />
  168. <!-- 添加/编辑用例 model -->
  169. <ModelFormExample
  170. v-if="showModelForm"
  171. :model-parames="{
  172. 'curPlanId':componentParames.curPlanId,
  173. 'deviceName':componentParames.deviceName,
  174. 'curSuiteId':componentParames.curSuiteId,
  175. 'modelFormData':modelFormData
  176. }"
  177. @toggleModel="closeModel"
  178. />
  179. <ModelFormFileTransferOpt104
  180. v-if="showFileTransferOpt104ModelForm"
  181. :model-parames="{
  182. 'curPlanId':componentParames.curPlanId,
  183. 'productId':componentParames.productId,
  184. 'deviceName':componentParames.deviceName,
  185. 'curSuiteId':componentParames.curSuiteId
  186. }"
  187. @toggleModel="closeModel"
  188. />
  189. </div>
  190. </template>
  191. <script>
  192. import {
  193. httpGet,
  194. delRecord,
  195. json2ArrayContext
  196. } from '@/api/common-action'
  197. // 分页
  198. import Pagination from '@/components/Pagination'
  199. // 查看报文
  200. import ModelReport from '../components/ModelReport'
  201. // 添加用例
  202. import ModelFormExample from '../components/ModelFormExample'
  203. import ModelFormFileTransferOpt104 from '../components/ModelFormFileTransferOpt104'
  204. // 导入总线
  205. import { EventBus } from '@/main.js'
  206. export default {
  207. name: 'Example',
  208. components: {
  209. Pagination,
  210. ModelReport,
  211. ModelFormExample,
  212. ModelFormFileTransferOpt104
  213. },
  214. props: {
  215. componentParames: {
  216. type: Object,
  217. default: function() {
  218. return {}
  219. }
  220. }
  221. },
  222. data() {
  223. return {
  224. showFileTransferOpt104ModelForm: false,
  225. vloading: true,
  226. tableData: [],
  227. tableIsUpdate: 0,
  228. unitsData: {},
  229. // 用例
  230. deviceExamples: {
  231. pageLimit: 5,
  232. paginationNumber: 1,
  233. paginationTotalElements: 1
  234. },
  235. // 是否显示 查看报文
  236. showModelReport: false,
  237. // 编辑用例数据
  238. modelFormData: {},
  239. // 是否显示 添加/编辑用例
  240. showModelForm: false
  241. }
  242. },
  243. // watch: {
  244. // componentParames: {
  245. // handler() {
  246. // // 监听传入的值 是否有变化 ,如有 刷新表格数据
  247. // // console.log('刷新表格数据 componentParames', this.componentParames)
  248. // // // 获取用例列表数据 ,不传分页信息,即采集默认分页获取第一页数据
  249. // // this.getDeviceExamples()
  250. // // // 刷新一次用例状态
  251. // this.refreshManual()
  252. // }
  253. // }
  254. // },
  255. created() {
  256. },
  257. mounted() {
  258. EventBus.$off('refreshManualFn')
  259. EventBus.$on('refreshManualFn', this.refreshManual)
  260. this.$nextTick(() => {
  261. // 网页加载完成后执行
  262. this.initFunctions()
  263. })
  264. },
  265. methods: {
  266. // 初始化
  267. async initFunctions() {
  268. // 所有需要加载时初始化的函数都放这里
  269. // console.log('Example initFunctions componentParames=', this.componentParames)
  270. // 获取用例列表数据 ,不传分页信息,即采集默认分页获取第一页数据
  271. this.getDeviceExamples()
  272. },
  273. // 文件传输
  274. openFileTransfer() {
  275. this.showFileTransferOpt104ModelForm = true
  276. },
  277. // 手动刷新状态 manual
  278. refreshManual(isHand) {
  279. // 接口 用例状态(高频刷新) /test/execute/:runner/results
  280. const getUrl = `/test/execute/${this.componentParames.curPlanId}/results`
  281. // const getUrl = `/test/execute/${this.componentParames.curPlanId}/models`
  282. // console.log('手动刷新 getUrl=', getUrl)
  283. httpGet(getUrl).then(res => {
  284. this.unitsData = res
  285. if (this.tableData.length > 0) {
  286. // this.tableData.filter(item)
  287. this.tableData.forEach(item => {
  288. res.units.forEach(uitem => {
  289. // console.log('item.id=', item.id)
  290. // console.log('uitem.id=', uitem.id)
  291. if (item.id === uitem.id) {
  292. // console.log('uitem.stateName=', uitem.stateName)
  293. item.state = uitem.stateName
  294. item.stateStyle = uitem.stateStyle
  295. item.occur = uitem.occur || '-'
  296. item.duration = uitem.duration || '-'
  297. item.unit = uitem
  298. }
  299. })
  300. })
  301. // 解决tableData无法刷新的问题
  302. this.tableIsUpdate = 'example' + new Date().getTime()
  303. }
  304. // console.log('this.tableData', this.tableData)
  305. if (isHand) {
  306. this.$message({
  307. message: '用例刷新成功',
  308. type: 'success',
  309. duration: 500,
  310. offset: window.screen.height / 3
  311. })
  312. }
  313. })
  314. },
  315. // 格式化bool值
  316. formatBool(val) {
  317. const rs = val.not.toString()
  318. return rs
  319. },
  320. // 获取用例
  321. getDeviceExamples(pageObj) {
  322. this.vloading = true
  323. // 翻页时pageObj对象才会有值,属性分别为page和limit
  324. if (pageObj == null) {
  325. pageObj = {
  326. page: 0,
  327. limit: this.deviceExamples.pageLimit
  328. }
  329. this.deviceExamples.paginationNumber = 0
  330. } else {
  331. this.deviceExamples.pageLimit = pageObj.limit
  332. }
  333. // 获取用例表格数据
  334. httpGet(`/test/plan/${this.componentParames.curPlanId}/units?page=${pageObj.page}&size=${pageObj.limit}`).then((response) => {
  335. this.vloading = false
  336. this.tableData = response.content
  337. // 格式化参数设置显示
  338. this.tableData.forEach(item => {
  339. item.params = json2ArrayContext(item.params)
  340. item.units = []
  341. })
  342. this.deviceExamples.paginationTotalElements = response.totalElements * 1
  343. this.deviceExamples.paginationNumber = response.number * 1 + 1
  344. // 刷新一次用例状态
  345. this.refreshManual(false)
  346. }).catch((res) => {
  347. this.vloading = false
  348. })
  349. },
  350. // 编辑
  351. editRow(index) {
  352. // console.log('this.tableData[index]=', this.tableData[index])
  353. // 如果是添加,则index为空,modelFormData也为空
  354. this.modelFormData = this.tableData[index]
  355. this.showModelForm = true
  356. },
  357. // 删除
  358. delRow(index) {
  359. this.$confirm(
  360. '此操作将永久删除该记录, 是否继续?',
  361. `删除`,
  362. {
  363. confirmButtonText: '确定',
  364. cancelButtonText: '取消',
  365. type: 'warning'
  366. }
  367. ).then(() => {
  368. // console.log('delRow index=', index)
  369. // 接口 删除用例 /test/unit/:unit
  370. // :unit 例:2300000036
  371. const delUrl = `/test/unit/${this.tableData[index].id}`
  372. // console.log('delRow delUrl=', delUrl)
  373. delRecord(delUrl).then(res => {
  374. this.$message({
  375. message: '删除成功',
  376. type: 'success',
  377. offset: window.screen.height / 3
  378. })
  379. // 后端成功执行后,前端再删除选中行
  380. this.tableData.splice(index, 1)
  381. })
  382. }).catch(() => {
  383. this.$message({
  384. type: 'info',
  385. message: '已取消删除',
  386. offset: window.screen.height / 3
  387. })
  388. })
  389. },
  390. // 查看报文
  391. checkReport() {
  392. // console.log('checkReport 查看报文 开始')
  393. this.showModelReport = true
  394. },
  395. // 关闭 model
  396. closeModel(modelName, modelShow) {
  397. // console.log('closeModel modelName=', modelName)
  398. // console.log('closeModel modelShow=', modelShow)
  399. switch (modelName) {
  400. // case 'ModelAddStep':
  401. // this.deviceDetail.showModelAddStep = modelShow
  402. // break
  403. case 'ModelReport':
  404. this.showModelReport = modelShow
  405. break
  406. case 'ModelFormExample':
  407. this.showModelForm = modelShow
  408. // 操作过用例模态框 刷新一次用例数据 保持页数不变
  409. this.getDeviceExamples({
  410. page: this.deviceExamples.paginationNumber - 1,
  411. limit: this.deviceExamples.pageLimit
  412. })
  413. break
  414. case 'ModelFormFileTransferOpt104':
  415. this.showFileTransferOpt104ModelForm = false
  416. break
  417. default:
  418. console.log('未获取到 modelName')
  419. break
  420. }
  421. }
  422. }
  423. }
  424. </script>
  425. <style lang="scss" scoped>
  426. .title-container {
  427. display: flex;
  428. justify-content: space-between;
  429. padding: 20px 0;
  430. .title-right {
  431. display: flex;
  432. align-items: center;
  433. .check-resaults {
  434. padding-right: 16px;
  435. .success {
  436. color: #00706b;
  437. }
  438. .faild {
  439. color: #f00;
  440. padding-right: 6px;
  441. }
  442. span {
  443. font-weight: bold;
  444. }
  445. }
  446. }
  447. }
  448. .title-main {
  449. color: #111;
  450. font-weight: bold;
  451. }
  452. // 用例表格样式
  453. .table-container {
  454. padding: 0;
  455. .el-table {
  456. font-size: 12px;
  457. }
  458. .unit {
  459. list-style: none;
  460. padding-left: 0;
  461. li {
  462. display: flex;
  463. // 总数使用默认颜色
  464. // .total {
  465. // // color: #00706b;
  466. // }
  467. .successful {
  468. color: #00706b;
  469. }
  470. .failed {
  471. color: #c51437;
  472. }
  473. }
  474. }
  475. .setting-json {
  476. padding: 0;
  477. margin: 0;
  478. list-style: none;
  479. li {
  480. display: inline;
  481. }
  482. }
  483. }
  484. // 底部按钮
  485. .bottom-button {
  486. display: flex;
  487. justify-content: center;
  488. padding-bottom: 20px;
  489. .cancel-plan {
  490. padding-right: 20px;
  491. }
  492. }
  493. // 按钮公用样式
  494. .dark-button {
  495. background-color: #00706B;
  496. border: 1px #00706B solid;
  497. color: #fff;
  498. }
  499. .light-button {
  500. color: #00706B;
  501. border: 1px #00706B solid;
  502. }
  503. </style>