You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.vue 18 kB

2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <template>
  2. <div>
  3. <div class="title"><span>{{ $t('resourcesManagement.resSpecificationAndPriceManagement') }}</span></div>
  4. <div class="tools-bar">
  5. <div>
  6. <el-select class="select" size="medium" v-model="selQueue" @change="selectChange">
  7. <el-option v-for="item in queueList" :key="item.k" :label="item.v" :value="item.k" />
  8. </el-select>
  9. <el-select class="select" size="medium" v-model="selStatus" @change="selectChange">
  10. <el-option v-for="item in statusList" :key="item.k" :label="item.v" :value="item.k" />
  11. </el-select>
  12. <el-select class="select" size="medium" v-model="selAvailable" @change="selectChange">
  13. <el-option v-for="item in availableList" :key="item.k" :label="item.v" :value="item.k" />
  14. </el-select>
  15. </div>
  16. <div>
  17. <el-button size="medium" icon="el-icon-refresh" @click="syncComputerNetwork" v-loading="syncLoading">
  18. {{ $t('resourcesManagement.syncAiNetwork') }}</el-button>
  19. <el-button type="primary" icon="el-icon-plus" size="medium" @click="showDialog('add')">
  20. {{ $t('resourcesManagement.addResSpecificationBtn') }}</el-button>
  21. </div>
  22. </div>
  23. <div class="table-container">
  24. <div style="min-height:600px;overflow-x:auto;">
  25. <el-table border :data="tableData" style="width:100%;" v-loading="loading" stripe>
  26. <el-table-column prop="ID" label="ID" align="center" header-align="center" width="60" fixed></el-table-column>
  27. <el-table-column prop="SpecStr" :label="$t('resourcesManagement.resourceSpecification')" align="left" fixed
  28. header-align="center" min-width="200">
  29. </el-table-column>
  30. <el-table-column prop="QueueInfo" :label="$t('resourcesManagement.resQueue')" align="center" fixed
  31. header-align="center" min-width="100">
  32. </el-table-column>
  33. <el-table-column prop="SourceSpecId" :label="$t('resourcesManagement.sourceSpecCode')" align="center" min-width="120"
  34. header-align="center">
  35. </el-table-column>
  36. <el-table-column prop="AccCardsNum" :label="$t('resourcesManagement.accCardsNum')" align="center"
  37. header-align="center"></el-table-column>
  38. <el-table-column prop="CpuCores" :label="$t('resourcesManagement.cpuNum')" align="center"
  39. header-align="center"></el-table-column>
  40. <el-table-column prop="GPUMemGiB" :label="`${$t('resourcesManagement.gpuMem')}(GB)`" align="center"
  41. header-align="center"></el-table-column>
  42. <el-table-column prop="MemGiB" :label="`${$t('resourcesManagement.mem')}(GB)`" align="center"
  43. header-align="center"></el-table-column>
  44. <el-table-column prop="ShareMemGiB" :label="`${$t('resourcesManagement.shareMem')}(GB)`" align="center"
  45. header-align="center"></el-table-column>
  46. <el-table-column prop="UpdatedTimeStr" :label="$t('resourcesManagement.lastUpdateTime')" align="center" min-width="140"
  47. header-align="center"></el-table-column>
  48. <el-table-column prop="UnitPrice"
  49. :label="`${$t('resourcesManagement.unitPrice')}(${$t('resourcesManagement.point_hr')})`" align="center"
  50. header-align="center">
  51. <template slot-scope="scope">
  52. <span style="font-weight:600;font-size:14px;">{{ scope.row.UnitPrice }}</span>
  53. </template>
  54. </el-table-column>
  55. <el-table-column prop="IsAvailableStr" :label="$t('resourcesManagement.resourceSpecificationIsAvailable')" align="center"
  56. header-align="center" width="100">
  57. <template slot-scope="scope">
  58. <span :style="{ color: scope.row.IsAvailable ? 'rgb(82, 196, 26)' : 'rgb(245, 34, 45)' }">{{
  59. scope.row.IsAvailableStr
  60. }}</span>
  61. </template>
  62. </el-table-column>
  63. <el-table-column prop="StatusStr" :label="$t('resourcesManagement.status')" align="center"
  64. header-align="center" width="100">
  65. <template slot-scope="scope">
  66. <span :style="{ color: scope.row.Status == '2' ? 'rgb(82, 196, 26)' : 'rgb(245, 34, 45)' }">{{
  67. scope.row.StatusStr
  68. }}</span>
  69. </template>
  70. </el-table-column>
  71. <el-table-column :label="$t('operation')" align="center" header-align="center" width="100">
  72. <template slot-scope="scope">
  73. <span v-if="scope.row.Status == '1' && !scope.row.UnitPrice">
  74. <span v-if="scope.row.IsAvailable" class="op-btn" @click="showDialog('edit', scope.row)">{{
  75. $t('resourcesManagement.toSetPriceAndOnShelf')
  76. }}</span>
  77. <span v-else class="op-btn" style="color: rgb(187, 187, 187); cursor: not-allowed;">{{
  78. $t('resourcesManagement.toSetPriceAndOnShelf')
  79. }}</span>
  80. </span>
  81. <span v-if="scope.row.Status == '2'">
  82. <span class="op-btn" @click="showDialog('edit', scope.row, true)">{{ $t('edit') }}</span>
  83. <span class="op-btn" @click="offShelfPrev(scope.row)">{{
  84. $t('resourcesManagement.toOffShelf')
  85. }}</span>
  86. </span>
  87. <span v-if="scope.row.Status == '3' || scope.row.Status == '1' && scope.row.UnitPrice">
  88. <span v-if="scope.row.IsAvailable" class="op-btn" @click="onShelf(scope.row)">{{
  89. $t('resourcesManagement.toOnShelf')
  90. }}</span>
  91. <span v-else class="op-btn" style="color: rgb(187, 187, 187); cursor: not-allowed;">{{
  92. $t('resourcesManagement.toSetPriceAndOnShelf')
  93. }}</span>
  94. </span>
  95. </template>
  96. </el-table-column>
  97. <template slot="empty">
  98. <span style="font-size: 12px">{{
  99. loading ? $t('loading') : $t('noData')
  100. }}</span>
  101. </template>
  102. </el-table>
  103. </div>
  104. <div class="__r_p_pagination">
  105. <div style="margin-top: 2rem">
  106. <div class="center">
  107. <el-pagination background @current-change="currentChange" :current-page="pageInfo.curpage"
  108. :page-sizes="pageInfo.pageSizes" :page-size="pageInfo.pageSize"
  109. layout="total, sizes, prev, pager, next, jumper" :total="pageInfo.total">
  110. </el-pagination>
  111. </div>
  112. </div>
  113. </div>
  114. </div>
  115. <SpecificationDialog :visible.sync="specificationDialogShow" :type="specificationDialogType"
  116. :editOr="specificationDialogEditOr" :data="specificationDialogData" @confirm="specificationDialogConfirm">
  117. </SpecificationDialog>
  118. <BaseDialog :visible.sync="offShelfDialogShow" :width="`600px`" :title="$t('tips')">
  119. <div class="form">
  120. <div class="form-row" style="flex-direction:column;">
  121. <div class="content" style="margin:8px 0">{{ $t('resourcesManagement.offShelfDlgTip1') }}</div>
  122. <div class="content" style="margin:8px 0;font-weight: bold;">{{ offSelfDialogContent }}</div>
  123. <div class="content" style="margin:8px 0">{{ $t('resourcesManagement.offShelfDlgTip2') }}</div>
  124. </div>
  125. <div class="form-row" style="margin-top: 20px">
  126. <div class="content">
  127. <el-button type="primary" class="btn confirm-btn" @click="offShelf">{{ $t('confirm') }}</el-button>
  128. <el-button class="btn" @click="offShelfDialogShow = false">{{ $t('cancel') }}</el-button>
  129. </div>
  130. </div>
  131. </div>
  132. </BaseDialog>
  133. </div>
  134. </template>
  135. <script>
  136. import SpecificationDialog from '../components/SpecificationDialog.vue';
  137. import BaseDialog from '~/components/BaseDialog.vue';
  138. import { getResQueueCode, getResSpecificationList, updateResSpecification, syncResSpecification, getResSpecificationScenes } from '~/apis/modules/resources';
  139. import { SPECIFICATION_STATUS, CLUSTERS, ACC_CARD_TYPE } from '~/const';
  140. import { getListValueWithKey } from '~/utils';
  141. import { formatDate } from 'element-ui/lib/utils/date-util';
  142. export default {
  143. data() {
  144. return {
  145. selQueue: '',
  146. queueList: [{ k: '', v: this.$t('resourcesManagement.allResQueue') }],
  147. selStatus: '',
  148. statusList: [{ k: '', v: this.$t('resourcesManagement.allStatus') }, ...SPECIFICATION_STATUS],
  149. selAvailable: '',
  150. availableList: [{ k: '', v: this.$t('resourcesManagement.resourceSpecificationIsAvailableAll') }, { k: '1', v: this.$t('resourcesManagement.available') }, { k: '2', v: this.$t('resourcesManagement.notAvailable') }],
  151. clusterList: [...CLUSTERS],
  152. accCardTypeList: [...ACC_CARD_TYPE],
  153. syncLoading: false,
  154. loading: false,
  155. tableData: [],
  156. pageInfo: {
  157. curpage: 1,
  158. pageSize: 10,
  159. pageSizes: [10],
  160. total: 0,
  161. },
  162. specificationDialogShow: false,
  163. specificationDialogType: 'add',
  164. specificationDialogEditOr: false,
  165. specificationDialogData: {},
  166. offShelfDialogShow: false,
  167. offShelfDialogData: {},
  168. offSelfDialogContent: '',
  169. };
  170. },
  171. components: { BaseDialog, SpecificationDialog },
  172. methods: {
  173. getQueueList() {
  174. getResQueueCode().then(res => {
  175. res = res.data;
  176. if (res.Code === 0) {
  177. const data = res.Data;
  178. const list = [];
  179. for (let i = 0, iLen = data.length; i < iLen; i++) {
  180. const item = data[i];
  181. list.push({
  182. k: item.ID,
  183. v: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${item.AiCenterName})`,
  184. });
  185. }
  186. this.queueList.push(...list);
  187. }
  188. }).catch(err => {
  189. console.log(err);
  190. });
  191. },
  192. getTableData() {
  193. const params = {
  194. queue: this.selQueue,
  195. status: this.selStatus,
  196. available: this.selAvailable,
  197. page: this.pageInfo.curpage,
  198. pagesize: this.pageInfo.pageSize,
  199. };
  200. this.loading = true;
  201. getResSpecificationList(params).then(res => {
  202. this.loading = false;
  203. res = res.data;
  204. if (res.Code === 0) {
  205. const list = res.Data.List;
  206. const data = list.map((item) => {
  207. const Queue = item.Queue;
  208. const Spec = item.Spec;
  209. // const NGPU = `${Queue.ComputeResource}:${Spec.AccCardsNum === 0 ? '0' : Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Queue.AccCardType)}`;
  210. const NGPU = `${Queue.ComputeResource}:${Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Queue.AccCardType)}`;
  211. return {
  212. ...Spec,
  213. SourceSpecId: Spec.SourceSpecId || '--',
  214. SpecStr: `${NGPU}, CPU:${Spec.CpuCores}, ${this.$t('resourcesManagement.gpuMem')}:${Spec.GPUMemGiB}GB, ${this.$t('resourcesManagement.mem')}:${Spec.MemGiB}GB, ${this.$t('resourcesManagement.shareMem')}:${Spec.ShareMemGiB}GB`,
  215. QueueId: Queue.ID,
  216. QueueInfo: `${Queue.QueueCode}(${getListValueWithKey(this.clusterList, Queue.Cluster)} - ${Queue.AiCenterName})`,
  217. UpdatedTimeStr: formatDate(new Date(Spec.UpdatedTime * 1000), 'yyyy-MM-dd HH:mm:ss'),
  218. Status: Spec.Status.toString(),
  219. StatusStr: getListValueWithKey(this.statusList, Spec.Status.toString()),
  220. IsAvailable: Spec.IsAvailable,
  221. IsAvailableStr: Spec.IsAvailable ? this.$t('resourcesManagement.available') : this.$t('resourcesManagement.notAvailable'),
  222. }
  223. });
  224. this.tableData = data;
  225. this.pageInfo.total = res.Data.TotalSize;
  226. }
  227. }).catch(err => {
  228. console.log(err);
  229. this.loading = false;
  230. });
  231. },
  232. syncComputerNetwork() {
  233. this.syncLoading = true;
  234. syncResSpecification().then(res => {
  235. this.syncLoading = false;
  236. res = res.data;
  237. if (res.Code === 0) {
  238. this.$message({
  239. type: 'success',
  240. message: this.$t('submittedSuccessfully')
  241. });
  242. this.getTableData();
  243. } else {
  244. this.$message({
  245. type: 'error',
  246. message: this.$t('submittedFailed')
  247. });
  248. }
  249. }).catch(err => {
  250. console.log(err);
  251. this.syncLoading = false;
  252. this.$message({
  253. type: 'error',
  254. message: this.$t('submittedFailed')
  255. });
  256. });
  257. },
  258. selectChange() {
  259. this.pageInfo.curpage = 1;
  260. this.getTableData();
  261. },
  262. currentChange(val) {
  263. this.pageInfo.curpage = val;
  264. this.getTableData();
  265. },
  266. showDialog(type, data, editOr) {
  267. this.specificationDialogType = type;
  268. this.specificationDialogEditOr = !!editOr;
  269. this.specificationDialogData = data ? { ...data } : {};
  270. this.specificationDialogShow = true;
  271. },
  272. specificationDialogConfirm() {
  273. this.specificationDialogShow = false;
  274. this.getTableData();
  275. },
  276. onShelf(data) {
  277. const type = 'on-shelf';
  278. this.$confirm(type === 'on-shelf' ? this.$t('resourcesManagement.onShelfConfirm') : this.$t('resourcesManagement.offShelfConfirm'), this.$t('tips'), {
  279. confirmButtonText: this.$t('confirm1'),
  280. cancelButtonText: this.$t('cancel'),
  281. type: 'warning',
  282. lockScroll: false,
  283. }).then(() => {
  284. updateResSpecification({
  285. ID: data.ID,
  286. action: type
  287. }).then(res => {
  288. res = res.data;
  289. if (res.Code === 0) {
  290. this.$message({
  291. type: 'success',
  292. message: this.$t('submittedSuccessfully')
  293. });
  294. this.getTableData();
  295. } else {
  296. if (type === 'on-shelf' && res.Code === 1001) {
  297. this.$message({
  298. type: 'info',
  299. message: this.$t('resourcesManagement.onShelfCode1001')
  300. });
  301. } else if (type === 'on-shelf' && res.Code === 1003) {
  302. this.$message({
  303. type: 'info',
  304. message: this.$t('resourcesManagement.onShelfCode1003')
  305. });
  306. } else {
  307. this.$message({
  308. type: 'error',
  309. message: this.$t('submittedFailed')
  310. });
  311. }
  312. }
  313. }).catch(err => {
  314. console.log(err);
  315. this.$message({
  316. type: 'error',
  317. message: this.$t('submittedFailed')
  318. });
  319. });
  320. }).catch(() => { });
  321. },
  322. offShelfPrev(data) {
  323. this.$confirm(this.$t('resourcesManagement.offShelfConfirm'), this.$t('tips'), {
  324. confirmButtonText: this.$t('confirm1'),
  325. cancelButtonText: this.$t('cancel'),
  326. type: 'warning',
  327. lockScroll: false,
  328. }).then(() => {
  329. this.offShelfDialogData = data;
  330. getResSpecificationScenes({ ID: data.ID }).then(res => {
  331. res = res.data;
  332. if (res.Code === 0) {
  333. if (res.Data.List.length) {
  334. this.offShelfDialogShow = true;
  335. this.offSelfDialogContent = res.Data.List.map((item) => `[${item.ID}]${item.SceneName}`).join(', ');
  336. } else {
  337. this.offShelf();
  338. }
  339. } else {
  340. console.log(res);
  341. }
  342. }).catch(err => {
  343. console.log(err);
  344. });
  345. }).catch(() => { });
  346. },
  347. offShelf() {
  348. updateResSpecification({
  349. ID: this.offShelfDialogData.ID,
  350. action: 'off-shelf'
  351. }).then(res => {
  352. res = res.data;
  353. if (res.Code === 0) {
  354. this.$message({
  355. type: 'success',
  356. message: this.$t('submittedSuccessfully')
  357. });
  358. this.offShelfDialogShow = false;
  359. this.getTableData();
  360. } else {
  361. this.$message({
  362. type: 'error',
  363. message: this.$t('submittedFailed')
  364. });
  365. }
  366. }).catch(err => {
  367. console.log(err);
  368. this.$message({
  369. type: 'error',
  370. message: this.$t('submittedFailed')
  371. });
  372. });
  373. },
  374. },
  375. mounted: function () {
  376. this.getQueueList();
  377. this.getTableData();
  378. },
  379. beforeDestroy: function () {
  380. },
  381. };
  382. </script>
  383. <style scoped lang="less">
  384. .title {
  385. height: 30px;
  386. display: flex;
  387. align-items: center;
  388. margin-bottom: 5px;
  389. span {
  390. font-weight: 700;
  391. font-size: 16px;
  392. color: rgb(16, 16, 16);
  393. }
  394. }
  395. .tools-bar {
  396. display: flex;
  397. align-items: center;
  398. justify-content: space-between;
  399. margin-bottom: 10px;
  400. .select {
  401. margin-right: 10px;
  402. /deep/ .el-input__inner {
  403. border-radius: 0;
  404. }
  405. }
  406. }
  407. .table-container {
  408. margin-bottom: 16px;
  409. /deep/ .el-table__header {
  410. th {
  411. background: rgb(245, 245, 246);
  412. font-size: 12px;
  413. color: rgb(36, 36, 36);
  414. }
  415. }
  416. /deep/ .el-table__body {
  417. td {
  418. font-size: 12px;
  419. }
  420. }
  421. .op-btn {
  422. cursor: pointer;
  423. font-size: 12px;
  424. color: rgb(25, 103, 252);
  425. margin-right: 4px;
  426. }
  427. }
  428. .center {
  429. display: flex;
  430. justify-content: center;
  431. }
  432. .form {
  433. margin: 5px 0 5px 0;
  434. display: flex;
  435. justify-content: center;
  436. flex-direction: column;
  437. align-items: center;
  438. }
  439. .form-row {
  440. display: flex;
  441. min-height: 42px;
  442. margin-bottom: 4px;
  443. .content {
  444. width: 500px;
  445. display: flex;
  446. align-items: center;
  447. }
  448. }
  449. .btn {
  450. color: rgb(2, 0, 4);
  451. background-color: rgb(194, 199, 204);
  452. border-color: rgb(194, 199, 204);
  453. &.confirm-btn {
  454. color: #fff;
  455. background-color: rgb(56, 158, 13);
  456. border-color: rgb(56, 158, 13);
  457. }
  458. }
  459. </style>