Server.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. <template>
  2. <div class="h-100 position-relative">
  3. <div class="dashboard-card-wrap">
  4. <div class="dashboard-card-header">
  5. <div class="dashboard-card-header-left">
  6. {{ form.fd.name || $t('dashboard.text_6') }}<a-icon class="ml-2" type="loading" v-if="loading" />
  7. <span v-if="isResDeny" class="ml-2"><a-icon class="warning-color mr-1" type="warning" />{{ $t('common.permission.403') }}</span>
  8. <span v-if="isUsageKeyDeny" class="ml-2">
  9. <a-tooltip class="mr-2"><template slot="title">{{ $t('dashboard.usage_key_deny_tips') }}</template><icon type="help" /></a-tooltip>
  10. <a-icon class="warning-color mr-1" type="warning" />
  11. {{ $t('dashboard.usage_key_deny_tips_2') }}
  12. </span>
  13. </div>
  14. <div class="dashboard-card-header-right">
  15. <slot name="actions" :handle-edit="handleEdit" />
  16. </div>
  17. </div>
  18. <div class="dashboard-card-body align-items-center">
  19. <a-progress v-if="isRing" type="circle" :percent="percent" :strokeWidth="12" :status="status" :strokeColor="percentColor">
  20. <template v-slot:format><span class="percent-tips" :style="{ color: '#000' }">{{ percentTips }}</span></template>
  21. </a-progress>
  22. <liquid-fill v-else :value="decimalPercent" />
  23. <div class="flex-fill ml-4">
  24. <div class="d-flex bottomborder-box align-items-end" :style="itemStyle">
  25. <div :class="`label-unit ${jumpParams.usedPath ? 'label-jump' : ''}`" @click="goJump('used')">{{ useLabel }}</div>
  26. <div class="flex-number mr-1 ml-1 text-right">{{isResDeny ? '-' : usage.usage}}</div>
  27. <div class="label-unit">{{usage.unit}}</div>
  28. </div>
  29. <div class="d-flex bottomborder-box align-items-end" :style="itemStyle">
  30. <div :class="`label-unit ${jumpParams.reservedPath ? 'label-jump' : ''}`" @click="goJump('reserved')">{{ unUseLabel }}<a-tooltip v-if="showTips" class="ml-1" :title="$t('dashboard.un_usage_tips')"><icon type="help" /></a-tooltip></div>
  31. <div class="flex-number mr-1 ml-1 text-right">{{isResDeny ? '-' : displayUnUsage.usage}}</div>
  32. <div class="label-unit">{{displayUnUsage.unit}}</div>
  33. </div>
  34. <div class="d-flex bottomborder-box align-items-end" :style="itemStyle" v-if="showReserved">
  35. <div :class="`flex-shrink-0 flex-grow-0 label-unit ${jumpParams.reservedPath ? 'label-jump' : ''}`" @click="goJump('reserved')">{{$t('dashboard.text_182')}}</div>
  36. <div class="flex-number mr-1 ml-1 text-right">{{isResDeny ? '-' : reserved.usage}}</div>
  37. <div class="label-unit">{{reserved.unit}}</div>
  38. </div>
  39. <div class="d-flex bottomborder-box align-items-end" :style="itemStyle" v-if="showGpuReserved">
  40. <div :class="`flex-shrink-0 flex-grow-0 label-unit ${jumpParams.reservedPath ? 'label-jump' : ''}`" @click="goJump('reserved')">
  41. {{$t('dashboard.text_183')}}<a-tooltip v-if="showTips" class="ml-1" :title="$t('dashboard.gpu_reserved_tips')"><icon type="help" /></a-tooltip>
  42. </div>
  43. <div class="flex-number mr-1 ml-1 text-right">{{isResDeny ? '-' : gpuReserved.usage}}</div>
  44. <div class="label-unit">{{gpuReserved.unit}}</div>
  45. </div>
  46. <div class="d-flex bottomborder-box align-items-end" :style="itemStyle">
  47. <div :class="`label-unit ${jumpParams.allPath ? 'label-jump' : ''}`" @click="goJump('all')">{{ $t('dashboard.text_181') }}<a-tooltip v-if="showTips" class="ml-1" :title="$t('dashboard.all_usage_tips')"><icon type="help" /></a-tooltip></div>
  48. <div class="flex-number mr-1 ml-1 text-right">{{isResDeny ? '-' : allUsage.usage}}</div>
  49. <div class="label-unit">{{allUsage.unit}}</div>
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. <base-drawer class="ring-drawer-wrapper" @update:visible="updateVisible" :visible="visible" :title="$t('dashboard.text_5')" @ok="handleSubmit">
  55. <slot />
  56. <a-form
  57. hideRequiredMark
  58. :form="form.fc"
  59. v-bind="formItemLayout">
  60. <a-form-item :label="$t('dashboard.text_6')">
  61. <a-input v-decorator="decorators.name" />
  62. </a-form-item>
  63. <quota-config :fc="form.fc" :fd="form.fd" :decorators="decorators" @update:usage_key="setDefaultName" />
  64. <a-form-item :label="$t('dashboard.chart_type')">
  65. <a-radio-group v-decorator="decorators.chart_type">
  66. <a-radio-button value="ring">{{ $t('dashboard.ring') }}</a-radio-button>
  67. <a-radio-button value="liquidfill">{{ $t('dashboard.liquidfill') }}</a-radio-button>
  68. </a-radio-group>
  69. </a-form-item>
  70. <a-form-item v-if="isRing" :label="colorLabel || $t('dashboard.color.scheme')" class="mb-0">
  71. <a-select
  72. @change="colorChange"
  73. v-decorator="decorators.color">
  74. <a-select-option v-for="item in ringColors" :key="item.key" :value="item.key">
  75. <div>
  76. <a-progress :show-info="false" :stroke-color="{ '60%': item.percent60, '80%': item.percent80, '100%': item.percent100}" :percent="100" />
  77. </div>
  78. <div class="text-color-help">{{ item.label }}</div>
  79. </a-select-option>
  80. </a-select>
  81. </a-form-item>
  82. </a-form>
  83. </base-drawer>
  84. </div>
  85. </template>
  86. <script>
  87. import { mapGetters } from 'vuex'
  88. import BaseDrawer from '@Dashboard/components/BaseDrawer'
  89. import QuotaConfig from '@Dashboard/sections/QuotaConfig'
  90. import { USAGE_CONFIG, getTargetRangeUsageKey } from '@Dashboard/constants'
  91. import { load } from '@Dashboard/utils/cache'
  92. import { getRequestT, sizestrWithUnit } from '@/utils/utils'
  93. import { hasPermission } from '@/utils/auth'
  94. import { numerify } from '@/filters'
  95. import { chartColors } from '@/constants'
  96. import mixin from './mixin'
  97. export default {
  98. name: 'RingServer',
  99. components: {
  100. BaseDrawer,
  101. QuotaConfig,
  102. },
  103. mixins: [mixin],
  104. props: {
  105. dataRangeParams: {
  106. type: Object,
  107. },
  108. },
  109. data () {
  110. const all_usage_key = this.$store.getters.isAdminMode ? 'all.servers' : this.$store.getters.isDomainMode ? 'domain.servers' : 'servers'
  111. const usage_key = this.$store.getters.isAdminMode ? 'all.running_servers' : this.$store.getters.isDomainMode ? 'domain.running_servers' : 'running_servers'
  112. const initialNameValue = ((this.params && this.params.type !== 'k8s') && this.params.name) || this.$t('usage')[usage_key]
  113. const initialCloudEnvValue = ((this.params && this.params.type !== 'k8s') && this.params.cloud_env) || ''
  114. const initialBrandValue = ((this.params && this.params.type !== 'k8s') && this.params.brand) || ''
  115. const initialRegionValue = ((this.params && this.params.type !== 'k8s') && this.params.region) || ''
  116. const initialAllUsageKeyValue = ((this.params && this.params.type !== 'k8s') && this.params.all_usage_key) || all_usage_key
  117. const initialUsageKeyValue = ((this.params && this.params.type !== 'k8s') && this.params.usage_key) || usage_key
  118. const initialRegionAccountType = ((this.params && this.params.type !== 'k8s') && this.params.regionAccountType) || 'region'
  119. const initialColorValue = ((this.params && this.params.type !== 'k8s') && this.params.color) || 'default'
  120. const initialUsageLabelValue = ((this.params && this.params.type !== 'k8s') && this.params.usage_label && this.params.usage_label.length > 0) ? this.params.usage_label : this.$t('dashboard.text_33')
  121. const initialUnUsageLabelValue = ((this.params && this.params.type !== 'k8s') && this.params.un_usage_label && this.params.un_usage_label.length > 0) ? this.params.un_usage_label : this.$t('dashboard.text_34')
  122. const initialChartTypeValue = ((this.params && this.params.type !== 'k8s') && this.params.chart_type) || 'liquidfill'
  123. return {
  124. data: {},
  125. loading: false,
  126. form: {
  127. fc: this.$form.createForm(this, { onValuesChange: this.onValuesChange }),
  128. fd: {
  129. name: initialNameValue,
  130. cloud_env: initialCloudEnvValue,
  131. brand: initialBrandValue,
  132. region: initialRegionValue,
  133. all_usage_key: initialAllUsageKeyValue,
  134. usage_key: initialUsageKeyValue,
  135. usage_label: initialUsageLabelValue,
  136. un_usage_label: initialUnUsageLabelValue,
  137. color: initialColorValue,
  138. chart_type: initialChartTypeValue,
  139. },
  140. },
  141. decorators: {
  142. name: [
  143. 'name',
  144. {
  145. initialValue: initialNameValue,
  146. rules: [
  147. { required: true, message: this.$t('dashboard.text_8') },
  148. ],
  149. },
  150. ],
  151. cloud_env: [
  152. 'cloud_env',
  153. {
  154. initialValue: initialCloudEnvValue,
  155. },
  156. ],
  157. brand: [
  158. 'brand',
  159. {
  160. initialValue: initialBrandValue,
  161. },
  162. ],
  163. regionAccountType: [
  164. 'regionAccountType',
  165. {
  166. initialValue: initialRegionAccountType,
  167. },
  168. ],
  169. region: [
  170. 'region',
  171. {
  172. initialValue: initialRegionValue,
  173. },
  174. ],
  175. account: [
  176. 'account',
  177. {
  178. initialValue: this.params && this.params.account,
  179. },
  180. ],
  181. all_usage_key: [
  182. 'all_usage_key',
  183. {
  184. initialValue: initialAllUsageKeyValue,
  185. rules: [
  186. { required: true, message: this.$t('dashboard.text_22') },
  187. ],
  188. },
  189. ],
  190. usage_key: [
  191. 'usage_key',
  192. {
  193. initialValue: initialUsageKeyValue,
  194. rules: [
  195. { required: true, message: this.$t('dashboard.text_22') },
  196. ],
  197. },
  198. ],
  199. color: [
  200. 'color',
  201. {
  202. initialValue: initialColorValue,
  203. },
  204. ],
  205. usage_label: [
  206. 'usage_label',
  207. {
  208. initialValue: initialUsageLabelValue,
  209. rules: [
  210. { required: true, message: this.$t('dashboard.usage_label_title') },
  211. ],
  212. },
  213. ],
  214. un_usage_label: [
  215. 'un_usage_label',
  216. {
  217. initialValue: initialUnUsageLabelValue,
  218. rules: [
  219. { required: true, message: this.$t('dashboard.un_usage_label_title') },
  220. ],
  221. },
  222. ],
  223. chart_type: [
  224. 'chart_type',
  225. {
  226. initialValue: initialChartTypeValue,
  227. },
  228. ],
  229. },
  230. }
  231. },
  232. computed: {
  233. ...mapGetters(['permission', 'scope', 'isAdminMode', 'isDomainMode']),
  234. isUsageKeyDeny () {
  235. const usageConfig = getTargetRangeUsageKey(this.form.fd.usage_key, this.scope, this.dataRangeParams?.scope)
  236. const allUsageConfig = getTargetRangeUsageKey(this.form.fd.all_usage_key, this.scope, this.dataRangeParams?.scope)
  237. if (usageConfig.error || usageConfig.usageKey === 'null' || !usageConfig.usageKey || allUsageConfig.error || allUsageConfig.usageKey === 'null' || !allUsageConfig.usageKey) {
  238. return true
  239. }
  240. return false
  241. },
  242. isRing () {
  243. return this.form.fd.chart_type === 'ring'
  244. },
  245. itemStyle () {
  246. const ret = {}
  247. if (this.showReserved || this.showGpuReserved) {
  248. ret.margin = '0'
  249. }
  250. if (this.showGpuReserved && this.showReserved) {
  251. ret.padding = '3px 0'
  252. }
  253. return ret
  254. },
  255. allUsageNumber () {
  256. const usageKey = getTargetRangeUsageKey(this.form.fd.all_usage_key, this.scope, this.dataRangeParams?.scope).usageKey
  257. if (!usageKey || usageKey === 'null') {
  258. return 0
  259. }
  260. return (this.data && this.data[usageKey]) || 0
  261. },
  262. usageNumber () {
  263. const usageKey = getTargetRangeUsageKey(this.form.fd.usage_key, this.scope, this.dataRangeParams?.scope).usageKey
  264. if (!usageKey || usageKey === 'null') {
  265. return 0
  266. }
  267. return (this.data && this.data[usageKey]) || 0
  268. },
  269. allUsageConfig () {
  270. return USAGE_CONFIG[this.form.fd.all_usage_key]
  271. },
  272. usageConfig () {
  273. return USAGE_CONFIG[this.form.fd.usage_key]
  274. },
  275. colorConfig () {
  276. return (this.params && this.params.color) || 'blue'
  277. },
  278. allUsage () {
  279. let ret = this.allUsageNumber
  280. if (this.allUsageConfig && this.allUsageConfig.formatter) {
  281. ret = this.allUsageConfig.formatter(ret)
  282. }
  283. if (this.allUsageConfig && this.allUsageConfig.unit) {
  284. ret = `${ret} ${this.allUsageConfig.unit}`
  285. }
  286. return {
  287. usage: ret.toString().split(' ')[0],
  288. unit: ret.toString().split(' ')[1] || '',
  289. }
  290. },
  291. usage () {
  292. let ret = this.usageNumber
  293. if (this.usageConfig && this.usageConfig.formatter) {
  294. ret = this.usageConfig.formatter(ret)
  295. }
  296. if (this.usageConfig && this.usageConfig.unit) {
  297. ret = `${ret} ${this.usageConfig.unit}`
  298. }
  299. return {
  300. usage: ret.toString().split(' ')[0],
  301. unit: ret.toString().split(' ')[1] || '',
  302. }
  303. },
  304. unUsage () {
  305. const ret = this.allUsageNumber - this.usageNumber
  306. return ret < 0 ? 0 : ret
  307. },
  308. displayUnUsage () {
  309. let ret = this.unUsage
  310. if (
  311. (this.allUsageConfig && this.allUsageConfig.formatter) &&
  312. (this.usageConfig && this.usageConfig.formatter)
  313. ) {
  314. ret = this.usageConfig.formatter(this.unUsage)
  315. }
  316. if (
  317. (this.allUsageConfig && this.allUsageConfig.unit) &&
  318. (this.usageConfig && this.usageConfig.unit)
  319. ) {
  320. ret = `${ret} ${this.usageConfig.unit}`
  321. }
  322. return {
  323. usage: ret.toString().split(' ')[0],
  324. unit: ret.toString().split(' ')[1] || this.usage.unit,
  325. }
  326. },
  327. decimalPercent () {
  328. if (this.isResDeny) return '0'
  329. if (this.usageNumber === 0 || this.allUsageNumber === 0) return '0'
  330. const percent = this.usageNumber / this.allUsageNumber
  331. if (percent > 0 && percent < 0.01) {
  332. return '0.004'
  333. }
  334. return numerify(this.usageNumber / this.allUsageNumber, '0.0000')
  335. },
  336. percent () {
  337. if (this.isResDeny) return '0'
  338. const data = parseFloat(this.decimalPercent)
  339. if (data > 0 && data < 0.01) {
  340. return 0.4
  341. }
  342. return data * 100
  343. },
  344. percentTips () {
  345. if (this.percent === 0) return '0%'
  346. if (this.percent < 1) {
  347. return '< 1%'
  348. }
  349. if (this.percent > 99 && this.percent < 100) {
  350. return '> 99%'
  351. }
  352. return `${numerify(this.percent, 0.0)} %`
  353. },
  354. percentColor () {
  355. switch (this.colorConfig) {
  356. case 'default':
  357. if (this.percent < 60) {
  358. return chartColors[3]
  359. }
  360. if (this.percent < 80) {
  361. return chartColors[1]
  362. }
  363. return chartColors[2]
  364. case 'reverse':
  365. if (this.percent < 60) {
  366. return chartColors[2]
  367. }
  368. if (this.percent < 80) {
  369. return chartColors[1]
  370. }
  371. return chartColors[3]
  372. default:
  373. return chartColors[0]
  374. }
  375. },
  376. status () {
  377. let ret = 'normal'
  378. if (this.percent > 100) {
  379. ret = 'exception'
  380. }
  381. return ret
  382. },
  383. showReserved () {
  384. return this.form.fd.usage_key === 'all.servers.memory' && this.form.fd.all_usage_key === 'hosts.memory.total'
  385. },
  386. showGpuReserved () {
  387. const isMemory = this.form.fd.usage_key === 'all.servers.memory' && this.form.fd.all_usage_key === 'hosts.memory.total'
  388. const isCpu = this.form.fd.usage_key === 'all.servers.cpu' && this.form.fd.all_usage_key === 'hosts.cpu.total'
  389. const isStorage = this.form.fd.usage_key === 'all.servers.disk' && this.form.fd.all_usage_key === 'storages'
  390. return isMemory || isCpu || isStorage
  391. },
  392. reserved () {
  393. if (this.showReserved) {
  394. const reserved = sizestrWithUnit(this.data['hosts.memory.reserved'], 'M', 1024)
  395. return {
  396. usage: reserved.toString().split(' ')[0],
  397. unit: reserved.toString().split(' ')[1],
  398. }
  399. }
  400. return '-'
  401. },
  402. gpuReserved () {
  403. let gpuReserved = ''
  404. if (this.form.fd.all_usage_key === 'hosts.memory.total') {
  405. gpuReserved = sizestrWithUnit(this.data['hosts.memory.reserved.isolated'], 'M', 1024)
  406. } else if (this.form.fd.all_usage_key === 'hosts.cpu.total') {
  407. gpuReserved = `${this.data['hosts.cpu.reserved.isolated'] || 0} ${this.usageConfig.unit}`
  408. } if (this.form.fd.all_usage_key === 'storages') {
  409. gpuReserved = sizestrWithUnit(this.data['hosts.storage.reserved.isolated'], 'M', 1024)
  410. }
  411. return gpuReserved && {
  412. usage: gpuReserved.toString().split(' ')[0],
  413. unit: gpuReserved.toString().split(' ')[1],
  414. }
  415. },
  416. showTips () {
  417. const keyTips = ['hosts.memory.total', 'hosts.cpu.total', 'storages']
  418. return keyTips.includes(this.form.fd.all_usage_key)
  419. },
  420. useLabel () {
  421. if (this.params) {
  422. return this.params.usage_label || this.$t('dashboard.text_43')
  423. }
  424. return this.$t('dashboard.text_43')
  425. },
  426. unUseLabel () {
  427. if (this.params) {
  428. return this.params.un_usage_label || this.$t('dashboard.text_34')
  429. }
  430. return this.$t('dashboard.text_34')
  431. },
  432. isResDeny () {
  433. const usage_key = this.params?.all_usage_key || this.form.fd?.all_usage_key || ''
  434. if (usage_key.split('.').includes('containers') || usage_key.split('.').includes('pending_delete_containers') || usage_key.split('.').includes('ready_containers')) {
  435. return !hasPermission({ key: 'servers_list', permissionData: this.permission })
  436. }
  437. if (usage_key.endsWith('servers')) {
  438. return !hasPermission({ key: 'servers_list', permissionData: this.permission })
  439. } else if (usage_key.endsWith('disks.count')) {
  440. return !hasPermission({ key: 'disks_list', permissionData: this.permission })
  441. } else if (usage_key.endsWith('ports')) {
  442. return !hasPermission({ key: 'networks_list', permissionData: this.permission })
  443. } else if (usage_key.endsWith('eip.floating_ip')) {
  444. return !hasPermission({ key: 'eips_list', permissionData: this.permission })
  445. }
  446. return !hasPermission({ key: 'compute_usages_get' })
  447. },
  448. isCanJump () {
  449. return {
  450. all: true,
  451. used: true,
  452. reserved: true,
  453. }
  454. },
  455. jumpParams () {
  456. const params = this.parseUsageKey(this.form.fd.all_usage_key || '', this.form.fd.usage_key || '')
  457. return params
  458. },
  459. },
  460. watch: {
  461. 'form.fd' (val) {
  462. this.fetchUsage()
  463. for (const key in this.decorators) {
  464. let config = this.decorators[key][1] || {}
  465. config = {
  466. ...config,
  467. initialValue: val[key],
  468. }
  469. this.decorators[key][1] = config
  470. }
  471. },
  472. 'dataRangeParams.scope': {
  473. handler (val) {
  474. this.fetchUsage()
  475. },
  476. immediate: true,
  477. },
  478. 'dataRangeParams.domain': {
  479. handler (val) {
  480. this.fetchUsage()
  481. },
  482. immediate: true,
  483. },
  484. 'dataRangeParams.project': {
  485. handler (val) {
  486. this.fetchUsage()
  487. },
  488. immediate: true,
  489. },
  490. },
  491. created () {
  492. if (this.params && this.params.type !== 'k8s') {
  493. this.form.fd = { chart_type: 'ring', ...this.params }
  494. } else if (this.form.fd.usage_key) {
  495. this.$emit('update', this.options.i, this.form.fd)
  496. this.setDefaultName(this.form.fd.usage_key)
  497. this.refresh()
  498. }
  499. },
  500. methods: {
  501. onValuesChange (props, values) {
  502. Object.keys(values).forEach((key) => {
  503. this.form.fd[key] = values[key]
  504. })
  505. },
  506. colorChange (color) {
  507. this.$emit('update:color', color)
  508. },
  509. refresh () {
  510. return this.fetchUsage()
  511. },
  512. genUsageParams () {
  513. const params = {
  514. scope: this.$store.getters.scope,
  515. $t: getRequestT(),
  516. ignoreErrorStatusCode: [403],
  517. }
  518. const fd = this.form.fd
  519. if (fd.cloud_env) params.cloud_env = fd.cloud_env
  520. if (fd.region) {
  521. params.range_type = 'cloudregions'
  522. params.range_id = fd.region
  523. }
  524. if (fd.account) {
  525. params.range_type = 'cloudaccounts'
  526. params.range_id = fd.account
  527. }
  528. if (fd.brand) params.brand = fd.brand
  529. return params
  530. },
  531. async fetchUsage () {
  532. if (this.isResDeny) return
  533. this.loading = true
  534. try {
  535. const params = this.genUsageParams()
  536. if (this.isAdminMode) {
  537. if (this.dataRangeParams?.scope === 'domain' && this.dataRangeParams?.domain) {
  538. params.scope = 'domain'
  539. params.domain_id = this.dataRangeParams?.domain
  540. }
  541. if (this.dataRangeParams?.scope === 'project' && this.dataRangeParams?.project) {
  542. params.scope = 'project'
  543. params.project_id = this.dataRangeParams?.project
  544. }
  545. }
  546. if (this.isDomainMode) {
  547. if (this.dataRangeParams?.scope === 'project' && this.dataRangeParams?.project) {
  548. params.scope = 'project'
  549. params.project_id = this.dataRangeParams?.project
  550. }
  551. }
  552. const data = await load({
  553. res: 'usages',
  554. actionArgs: {
  555. url: '/v2/rpc/usages/general-usage',
  556. method: 'GET',
  557. params,
  558. },
  559. useManager: false,
  560. resPath: 'data',
  561. })
  562. this.data = data
  563. } finally {
  564. this.loading = false
  565. }
  566. },
  567. handleEdit () {
  568. this.updateVisible(true)
  569. },
  570. updateVisible (val) {
  571. this.$emit('update:visible', val)
  572. },
  573. parseUsageKey (allKey, usageKey) {
  574. const str = allKey.replace(/^(all\.)|(domain\.)|(project\.)/, '')
  575. const list = str.split('.')
  576. const allFilterKey = list[1]
  577. const allFilterValue = list[2]
  578. const usageStr = usageKey.replace(/^(all\.)|(domain\.)|(project\.)/, '')
  579. const usageList = usageStr.split('.')
  580. const usageResource = usageList[0]
  581. const usageFilterKey = usageList[1]
  582. const usageFilterValue = usageList[2]
  583. // const usageFilterValue = usageList[2]
  584. let allPath = ''
  585. let usedPath = ''
  586. let reservedPath = ''
  587. const allParams = {}
  588. const usedParams = {}
  589. const reservedParams = {}
  590. switch (list[0]) {
  591. case 'servers':
  592. allPath = '/vminstance'
  593. usedPath = '/vminstance'
  594. // reservedPath = '/vminstance'
  595. // allParams.status = ['running', 'ready']
  596. if (usageResource === 'running_servers') {
  597. usedParams.status = ['running']
  598. // reservedParams.status = ['ready']
  599. } else if (usageResource === 'ready_servers') {
  600. usedParams.status = ['ready']
  601. // reservedParams.status = ['running']
  602. } else if (usageResource === 'pending_delete_servers') {
  603. usedPath = '/serverrecovery'
  604. reservedPath = '/vminstance'
  605. // reservedParams.status = ['running', 'ready']
  606. }
  607. break
  608. case 'containers':
  609. allPath = '/vminstance-container'
  610. usedPath = '/vminstance-container'
  611. reservedPath = '/vminstance-container'
  612. if (usageResource === 'running_containers') {
  613. usedParams.status = ['running']
  614. } else if (usageResource === 'ready_containers') {
  615. usedParams.status = ['ready']
  616. } else if (usageResource === 'pending_delete_containers') {
  617. usedPath = '/serverrecovery'
  618. reservedPath = '/vminstance-container'
  619. }
  620. break
  621. case 'disks':
  622. allPath = '/disk'
  623. usedPath = '/disk'
  624. reservedPath = '/disk'
  625. if (usageFilterKey === 'mounted') {
  626. usedParams.unused = false
  627. reservedParams.unused = true
  628. } else if (usageFilterKey === 'unmounted') {
  629. usedParams.unused = true
  630. reservedParams.unused = false
  631. }
  632. break
  633. case 'storages':
  634. if (allFilterKey === 'medium_type') {
  635. allPath = '/disk'
  636. usedPath = '/disk'
  637. reservedPath = '/disk'
  638. allParams.medium_type = allFilterValue
  639. usedParams.medium_type = allFilterValue
  640. reservedParams.medium_type = allFilterValue
  641. reservedParams.unused = true
  642. allParams.unused = false
  643. usedParams.unused = false
  644. }
  645. break
  646. case 'eip':
  647. allPath = '/eip'
  648. usedPath = '/eip'
  649. reservedPath = '/eip'
  650. if (usageFilterKey === 'floating_ip' && usageFilterValue === 'used') {
  651. usedParams.is_associated = true
  652. reservedParams.is_associated = false
  653. }
  654. break
  655. // case 'ports':
  656. // allPath = '/network2'
  657. // break
  658. case 'hosts':
  659. allPath = '/host'
  660. usedPath = '/host'
  661. reservedPath = '/host'
  662. if (usageResource === 'enabled_hosts') {
  663. usedParams.enabled = true
  664. reservedParams.enabled = false
  665. }
  666. break
  667. // case 'baremetals':
  668. // allPath = '/baremetal'
  669. // usedPath = '/vminstance'
  670. case 'isolated_devices':
  671. allPath = '/gpu'
  672. usedPath = '/gpu'
  673. reservedPath = '/gpu'
  674. if (usageResource === 'servers' && usageFilterKey === 'isolated_devices') {
  675. usedParams.is_associated = true
  676. reservedParams.is_associated = false
  677. }
  678. break
  679. // case 'imgiso':
  680. // path = ''
  681. }
  682. return {
  683. allPath,
  684. allParams,
  685. usedPath,
  686. usedParams,
  687. reservedPath,
  688. reservedParams,
  689. }
  690. },
  691. goJump (type) {
  692. this.$router.push({
  693. path: this.jumpParams[`${type}Path`],
  694. query: this.jumpParams[`${type}Params`],
  695. })
  696. },
  697. async handleSubmit () {
  698. try {
  699. const values = await this.form.fc.validateFields()
  700. this.form.fd = values
  701. this.$emit('update', this.options.i, values)
  702. this.updateVisible(false)
  703. } catch (error) {
  704. throw error
  705. }
  706. },
  707. },
  708. }
  709. </script>
  710. <style lang="less" scoped>
  711. .flex-number{
  712. font-size: 15px;
  713. line-height: 21px;
  714. flex: 1 1 auto;
  715. color: #000;
  716. font-weight: 600;
  717. }
  718. .label-unit{
  719. color: #666666;
  720. }
  721. .label-jump{
  722. color: var(--antd-wave-shadow-color);
  723. cursor: pointer;
  724. }
  725. .percent-tips {
  726. font-size: 20px;
  727. // font-weight: bold;
  728. }
  729. .ring-drawer-wrapper {
  730. &::v-deep.ant-drawer.ant-drawer-open .ant-drawer-mask {
  731. animation: none;
  732. }
  733. }
  734. .bottomborder-box{
  735. border-bottom: 1px solid #F2F2F2;
  736. margin: 10px 0;
  737. padding: 5px 0;
  738. }
  739. </style>