autoRunProjectDetail.vue 21 KB

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