manualRunProjectDetail.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. <template>
  2. <div>
  3. <el-form ref="form" :model="form" :rules="rules" label-width="140px" class="flexBox">
  4. <div class="formItemBox">
  5. <el-form-item label="项目名称:" prop="projectName">
  6. <el-input placeholder="请输入" maxlength="120" v-autoTrim="{ obj: form, key: 'projectName' }"
  7. v-model="form.projectName">
  8. </el-input>
  9. </el-form-item>
  10. <el-form-item label="项目描述:" prop="projectDescribe">
  11. <el-input type="textarea" :autosize="{ minRows: 4, maxRows: 4 }" placeholder="请输入" maxlength="300"
  12. v-autoTrim="{ obj: form, key: 'projectDescribe' }" v-model="form.projectDescribe">
  13. </el-input>
  14. </el-form-item>
  15. <el-form-item label="算法来源:" prop="algorithmType">
  16. <el-radio v-model="form.algorithmType" label="1" @change="typeChange">私有导入</el-radio>
  17. <el-radio v-model="form.algorithmType" label="3" @change="typeChange">算法平台</el-radio>
  18. </el-form-item>
  19. <el-form-item label="选择算法:" prop="algorithmArrayS">
  20. <el-cascader ref="cascaderA" v-model="form.algorithmArrayS" :options="algorithmList" :props="props"
  21. @change="algorithmSelChange"></el-cascader>
  22. <!-- <el-select v-model="form.algorithm">
  23. <el-option
  24. v-for="item in algorithmList"
  25. :label="item.name"
  26. :value="item.id"
  27. :key="item.id"
  28. :title="item.description"
  29. ></el-option>
  30. </el-select> -->
  31. </el-form-item>
  32. <el-form-item label="选择车辆:" prop="vehicleArrayS">
  33. <el-cascader ref="cascaderB" v-model="form.vehicleArrayS" :options="vehicleList" :props="props"
  34. @change="vehicleSelChange"></el-cascader>
  35. <!-- <el-select
  36. v-model="form.vehicle"
  37. @change="vehicleSelChange"
  38. >
  39. <el-option
  40. v-for="item in vehicleList"
  41. :label="item.name"
  42. :value="item.id"
  43. :key="item.id"
  44. :title="item.description"
  45. ></el-option>
  46. </el-select> -->
  47. </el-form-item>
  48. <el-form-item label="选择场景:" prop="sceneArrayS">
  49. <el-cascader ref="cascaderC" v-model="form.sceneArrayS" :options="sceneList" :props="props"
  50. @change="sceneSelChange"></el-cascader>
  51. <!-- <el-select v-model="form.scene" @change="sceneSelChange">
  52. <el-option
  53. v-for="item in sceneList"
  54. :label="item.name"
  55. :value="item.id"
  56. :key="item.id"
  57. ></el-option>
  58. </el-select> -->
  59. </el-form-item>
  60. <el-form-item label="仿真镜像组:" prop="simulationMageGroupId">
  61. <el-select v-model="form.simulationMageGroupId">
  62. <el-option v-for="item in simulationMageGroup" :label="item.groupName" :value="item.id"
  63. :key="item.id"></el-option>
  64. </el-select>
  65. </el-form-item>
  66. <el-form-item label="并行度:" prop="parallelism">
  67. <el-input :disabled="runDisabled" placeholder="请输入" maxlength="10"
  68. v-autoTrim="{ obj: form, key: 'parallelism' }" v-model="form.parallelism">
  69. </el-input>
  70. </el-form-item>
  71. <el-form-item label="场景评价规则:"></el-form-item>
  72. <el-form-item label="危险度" class="rule-item" prop="riskEvaluationRuleId">
  73. <el-select placeholder="暂不评价" v-model="form.riskEvaluationRuleId">
  74. <el-option v-for="(item, idx) in scriptList['2']" :key="idx" :label="item.ruleName"
  75. :value="item.ruleId"></el-option>
  76. </el-select>
  77. </el-form-item>
  78. <el-form-item label="复杂度" class="rule-item" prop="complexityEvaluationRuleId">
  79. <el-select placeholder="暂不评价" v-model="form.complexityEvaluationRuleId">
  80. <el-option v-for="(item, idx) in scriptList['1']" :key="idx" :label="item.ruleName"
  81. :value="item.ruleId"></el-option>
  82. </el-select>
  83. </el-form-item>
  84. <el-form-item label="暴露率" class="rule-item" prop="exposureRateEvaluationRuleId">
  85. <el-select placeholder="暂不评价" v-model="form.exposureRateEvaluationRuleId">
  86. <el-option v-for="(item, idx) in scriptList['3']" :key="idx" :label="item.ruleName"
  87. :value="item.ruleId"></el-option>
  88. </el-select>
  89. </el-form-item>
  90. <el-form-item label="覆盖率" class="rule-item" prop="coverageRateEvaluationRuleId">
  91. <el-select placeholder="暂不评价" v-model="form.coverageRateEvaluationRuleId">
  92. <el-option v-for="(item, idx) in scriptList['4']" :key="idx" :label="item.ruleName"
  93. :value="item.ruleId"></el-option>
  94. </el-select>
  95. </el-form-item>
  96. <el-form-item label="最大仿真时间(s):" prop="maxSimulationTime">
  97. <div style="position: relative;">
  98. <el-input placeholder="请输入" maxlength="10" v-autoTrim="{ obj: form, key: 'maxSimulationTime' }"
  99. v-model="form.maxSimulationTime">
  100. </el-input>
  101. <span style="position: absolute; right: -160px;">(最小是5,最大是10000)</span>
  102. </div>
  103. </el-form-item>
  104. <el-form-item label="是否选择GPU:" prop="isChoiceGpu">
  105. <el-radio v-model="form.isChoiceGpu" label="0">是</el-radio>
  106. <el-radio v-model="form.isChoiceGpu" label="1">否</el-radio>
  107. </el-form-item>
  108. </div>
  109. <div class="tipBox">
  110. <div class="tip tipA">
  111. <!-- (传感器1:根据车辆自动带出;传感器2:根据车辆自动带出) -->
  112. <span v-for="item in sensors" :key="item" v-bind:class="{
  113. iconA: item === 'camera',
  114. iconB: item === 'ogt',
  115. iconC: item === 'lidar',
  116. iconE: item === 'gps',
  117. }"></span>
  118. </div>
  119. <div class="tip">(场景数量:{{ sceneCount }})</div>
  120. <!-- <div class="tip flexBox">
  121. <div>(下次运行时间:XX时XX分XX秒)</div>
  122. <div class="tipBtnBox">
  123. <el-button type="primary">规则查看</el-button>
  124. </div>
  125. </div> -->
  126. <div class="tip">(仿真镜像组数量:{{ simulationMageGroup.length }})</div>
  127. <div class="tip">(最多可用资源:{{ maxCount }})</div>
  128. <!-- <div class="tip">(最小是5,最大是10000)</div> -->
  129. </div>
  130. </el-form>
  131. <div class="btns">
  132. <el-button type="primary" @click="save(false)">保存</el-button>
  133. <el-button type="primary" @click="save(true)" v-if="this.$route.query.id">另存为</el-button>
  134. <el-button type="primary" @click="save(false, true)" :disabled="runDisabled">提交</el-button>
  135. <el-button type="primary" plain @click="cancel">取消</el-button>
  136. </div>
  137. </div>
  138. </template>
  139. <script>
  140. //import from '';
  141. let maxCount = 0 // 用于校验
  142. let validateNum = (rule, value, callback) => {
  143. !/^(\d+)$/.test(value) && callback(new Error(rule.message))
  144. if (+value <= 0 || +value > +maxCount) callback(new Error(rule.message))
  145. callback()
  146. }
  147. let validateNumA = (rule, value, callback) => {
  148. !/^(\d+)$/.test(value) && callback(new Error(rule.message));
  149. if (+value < 5 || +value > 10000) callback(new Error(rule.message));
  150. callback();
  151. };
  152. let validateNumB = (rule, value, callback) => {
  153. !/^(\d+)$/.test(value) && callback(new Error(rule.message))
  154. if (+value <= 0) callback(new Error(rule.message))
  155. callback()
  156. }
  157. export default {
  158. name: 'manualRunProjectDetail', // 标准化测试详情
  159. components: {},
  160. data() {
  161. return {
  162. simulationMageGroup: [],
  163. form: {
  164. id: '',
  165. projectName: '', // 项目名称
  166. projectDescribe: '', // 项目描述
  167. algorithmType: '1', // 算法来源
  168. algorithm: '', // 选择算法
  169. algorithmArrayS: '', // 选择算法
  170. vehicle: '', // 选择车辆
  171. vehicleArrayS: '', // 选择车辆
  172. scene: '', // 选择场景
  173. sceneArrayS: '', // 选择场景
  174. parallelism: '', // 并行度
  175. maxSimulationTime: '', // 最大仿真时间
  176. isChoiceGpu: '0', // 是否选择GPU
  177. nowRunState: '10', // 运行状态
  178. complexityEvaluationRuleId: '', // 复杂度
  179. riskEvaluationRuleId: '', // 危险度
  180. exposureRateEvaluationRuleId: '', // 暴露率
  181. coverageRateEvaluationRuleId: '', // 覆盖率
  182. },
  183. algorithmList: [], // 算法对应列表
  184. vehicleList: [], // 车辆对应列表
  185. sceneList: [], // 场景对应列表
  186. maxCount: 0, // 最多可用资源
  187. sceneCount: 0, // 场景数量
  188. scriptList: {}, // 评价脚本列表
  189. rules: {
  190. projectName: [{
  191. required: true,
  192. message: '请输入',
  193. trigger: 'blur'
  194. }],
  195. projectDescribe: [{
  196. required: true,
  197. message: '请输入',
  198. trigger: 'blur'
  199. }, ],
  200. algorithmType: [{
  201. required: true,
  202. message: '请选择',
  203. trigger: 'change'
  204. }, ],
  205. algorithmArrayS: [{
  206. required: true,
  207. message: '请选择',
  208. trigger: 'change'
  209. }, ],
  210. vehicleArrayS: [{
  211. required: true,
  212. message: '请选择',
  213. trigger: 'change'
  214. }, ],
  215. sceneArrayS: [{
  216. required: true,
  217. message: '请选择',
  218. trigger: 'change'
  219. }],
  220. simulationMageGroupId:[{
  221. required: true,
  222. message: '请选择',
  223. trigger: 'change'
  224. }],
  225. parallelism: [{
  226. required: true,
  227. message: '请输入',
  228. trigger: 'blur'
  229. },
  230. // {
  231. // validator: validateNum,
  232. // message: "请输入不大于最多可用资源的正整数",
  233. // trigger: ["blur"],
  234. // },
  235. ],
  236. maxSimulationTime: [{
  237. required: true,
  238. message: '请输入',
  239. trigger: 'blur'
  240. },
  241. {
  242. validator: validateNumA,
  243. message: '请输入不小于5且不大于10000的正整数',
  244. trigger: ['blur'],
  245. },
  246. ],
  247. isChoiceGpu: [{
  248. required: true,
  249. message: '请选择',
  250. trigger: 'change'
  251. }],
  252. },
  253. sensors: [], // 选中车辆后对应的传感器数组
  254. runDisabled: false, // 若最多可用资源为0,则不可点击"提交"
  255. props: {
  256. multiple: false,
  257. label: 'name',
  258. value: 'code',
  259. },
  260. }
  261. },
  262. computed: {},
  263. methods: {
  264. async getLists(dropDownType = '') {
  265. await this.$axios({
  266. method: 'post',
  267. url: this.$api.workManagement.selectDropDownByTypeNew,
  268. data: {
  269. dropDownType,
  270. algorithmType: this.form.algorithmType,
  271. },
  272. }).then((res) => {
  273. if (res.code == 200 && res.info) {
  274. res.info.forEach((item) => {
  275. if (item.type === '1') {
  276. // item.dropDownList.forEach((i) => {
  277. // if (i.share === "1") i.name = i.name + "(公有)";
  278. // });
  279. this.algorithmList = item.dropDownList
  280. } else if (item.type === '2') {
  281. // item.dropDownList.forEach((i) => {
  282. // if (i.share === "1") i.name = i.name + "(公有)";
  283. // });
  284. this.vehicleList = item.dropDownList
  285. } else if (item.type === '3') {
  286. // item.dropDownList.forEach((i) => {
  287. // if (i.share === "1") i.name = i.name + "(公有)";
  288. // });
  289. this.sceneList = item.dropDownList
  290. }
  291. // 空表示第一次进,有值表示在切换算法来源,需要清空选择算法的值
  292. if (dropDownType) {
  293. this.form.algorithm = ''
  294. this.form.algorithmArrayS = []
  295. this.$nextTick(() => {
  296. // this.$refs.form.clearValidate("algorithm");
  297. this.$refs.form.clearValidate('algorithmArrayS')
  298. })
  299. }
  300. })
  301. } else {
  302. this.$message.error(res.message || '获取信息失败')
  303. }
  304. })
  305. },
  306. typeChange() {
  307. this.getLists('1')
  308. },
  309. async getMaxSimulationTime() {
  310. await this.$axios({
  311. method: 'post',
  312. url: this.$api.workManagement.selectMaxParallelism,
  313. data: {},
  314. }).then((res) => {
  315. if (res.code == 200 && res.info && res.info != 0) {
  316. this.maxCount = maxCount = res.info
  317. if (res.info == -1) {
  318. this.rules.parallelism.push({
  319. validator: validateNumB,
  320. message: '请输入正整数',
  321. trigger: ['blur'],
  322. })
  323. } else {
  324. this.rules.parallelism.push({
  325. validator: validateNum,
  326. message: '请输入不大于最多可用资源的正整数',
  327. trigger: ['blur'],
  328. })
  329. }
  330. } else if (res.code == 200 && res.info == 0) {
  331. this.maxCount = maxCount = 0
  332. this.runDisabled = true
  333. this.form.parallelism = 0
  334. } else {
  335. this.$message.error(res.message || '获取信息失败')
  336. }
  337. })
  338. },
  339. algorithmSelChange(v) {
  340. // console.log(v);
  341. // console.log(this.$refs.cascaderA.getCheckedNodes(true)[0].data.vo);
  342. let item = this.$refs.cascaderA.getCheckedNodes(true)[0].data.vo
  343. this.form.algorithm = item.id
  344. },
  345. vehicleSelChange(v) {
  346. let item = this.$refs.cascaderB.getCheckedNodes(true)[0].data.vo
  347. this.form.vehicle = item.id
  348. let sensor = item.sensor
  349. if (!sensor) {
  350. this.sensors = []
  351. } else {
  352. this.sensors = sensor.split(',')
  353. }
  354. // let sensor = this.vehicleList.find((i) => i.id === item).sensor;
  355. // if (!sensor) {
  356. // this.sensors = [];
  357. // } else {
  358. // this.sensors = sensor.split(",");
  359. // }
  360. },
  361. sceneSelChange(v) {
  362. let item = this.$refs.cascaderC.getCheckedNodes(true)[0].data.vo
  363. this.form.scene = item.id
  364. this.sceneCount = item.sceneNum
  365. // this.sceneCount = this.sceneList.find(
  366. // (i) => i.id === item
  367. // ).sceneNum;
  368. },
  369. getScriptList() {
  370. this.$axios({
  371. method: 'post',
  372. url: this.$api.sceneLibrary.getScriptListByType,
  373. data: {
  374. sceneEvaluationType: ['1', '2', '3', '4'],
  375. },
  376. }).then((res) => {
  377. this.scriptList = res.info
  378. })
  379. },
  380. save(isAdd = false, needChange = false) {
  381. // isAdd是否强制新增,needChange是否需要改变状态
  382. this.$refs.form.validate((valid) => {
  383. if (valid) {
  384. if (isAdd) {
  385. // 另存为
  386. this.form.id = ''
  387. }
  388. this.form.nowRunState = '10'
  389. this.$axios({
  390. method: 'post',
  391. url: this.$api.workManagement.addOrUpdateProject,
  392. data: {
  393. ...this.form,
  394. },
  395. }).then((res) => {
  396. if (res.code == 200) {
  397. this.$message.success('保存成功')
  398. if (needChange) {
  399. this.form.id = res.info
  400. this.stateChange()
  401. } else {
  402. this.cancel()
  403. }
  404. } else {
  405. this.$message.error(res.message || '保存失败')
  406. }
  407. })
  408. }
  409. })
  410. },
  411. cancel() {
  412. this.$router.replace({
  413. path: '/manualRunProjectList'
  414. })
  415. },
  416. stateChange() {
  417. this.$axios({
  418. method: 'post',
  419. url: this.$api.workManagement.updateProjectNowRunState,
  420. data: {
  421. id: this.form.id,
  422. nowRunState: '20',
  423. },
  424. }).then((res) => {
  425. if (res.code == 200) {
  426. this.$message.success('提交成功')
  427. this.cancel()
  428. } else {
  429. this.$message.error(res.message || '提交失败')
  430. }
  431. })
  432. },
  433. getSimulationMageGroup() {
  434. this.$axios({
  435. method: 'post',
  436. url: this.$api.workManagement.selectAllSimulationMageGroupList,
  437. data: {},
  438. }).then((res) => {
  439. if (res.code == 200) {
  440. this.simulationMageGroup = res.info
  441. } else {
  442. this.$message.error(res.message || '获取信息失败')
  443. }
  444. })
  445. }
  446. },
  447. mounted() {
  448. if (this.$route.query.id) {
  449. let id = ''
  450. this.form.id = id = this.$route.query.id
  451. if (id) {
  452. this.$axios({
  453. method: 'post',
  454. url: this.$api.workManagement.selectProjectById,
  455. data: {
  456. id,
  457. },
  458. }).then(async (res) => {
  459. if (res.code == 200 && res.info) {
  460. this.form = res.info
  461. await this.getLists()
  462. await this.getMaxSimulationTime()
  463. this.vehicleSelChange(res.info.vehicle)
  464. this.sceneSelChange(res.info.scene)
  465. } else {
  466. this.$message.error(res.message || '获取信息失败')
  467. }
  468. })
  469. }
  470. this.getScriptList();
  471. this.getSimulationMageGroup();
  472. } else {
  473. this.getLists()
  474. this.getMaxSimulationTime()
  475. this.getScriptList()
  476. this.getSimulationMageGroup();
  477. }
  478. },
  479. }
  480. </script>
  481. <style lang='less' scoped>
  482. .el-form {
  483. width: 60%;
  484. min-width: 900px;
  485. padding-top: 60px;
  486. margin: 0 auto;
  487. .formItemBox {
  488. flex: 1;
  489. /deep/ .el-input,
  490. .el-select,
  491. .el-cascader {
  492. width: 100%;
  493. }
  494. .el-cascader {
  495. height: 32px;
  496. line-height: 32px;
  497. }
  498. }
  499. .el-textarea {
  500. height: 96px;
  501. }
  502. .tipBox {
  503. min-width: 270px;
  504. margin-left: 20px;
  505. .tip {
  506. margin-bottom: 22px;
  507. line-height: 32px;
  508. }
  509. .tip1 {
  510. margin-bottom: -100px;
  511. border: 1px solid black;
  512. }
  513. .tipA {
  514. height: 32px;
  515. // 按54往上加
  516. margin-top: 280px;
  517. .iconA {
  518. background: url('../../assets/common/image/sensor/001.png') center no-repeat;
  519. background-size: contain;
  520. }
  521. .iconB {
  522. background: url('../../assets/common/image/sensor/002.png') center no-repeat;
  523. background-size: contain;
  524. }
  525. .iconC {
  526. background: url('../../assets/common/image/sensor/003.png') center no-repeat;
  527. background-size: contain;
  528. }
  529. .iconD {
  530. background: url('../../assets/common/image/sensor/004.png') center no-repeat;
  531. background-size: contain;
  532. }
  533. .iconE {
  534. background: url('../../assets/common/image/sensor/005.png') center no-repeat;
  535. background-size: contain;
  536. }
  537. span {
  538. display: inline-block;
  539. width: 18px;
  540. height: 18px;
  541. margin-top: 7px;
  542. margin-right: 6px;
  543. }
  544. }
  545. .tipB {
  546. padding-top: 54px;
  547. }
  548. .tipBtnBox {
  549. margin-left: 20px;
  550. }
  551. }
  552. }
  553. .rule-item {
  554. margin-left: 60px;
  555. }
  556. .btns {
  557. padding-top: 30px;
  558. text-align: center;
  559. }
  560. </style>