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 16 kB

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