index.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 }}<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. <!-- <router-link v-if="!edit" to="/notice" class="ml-2">{{$t('dashboard.more')}}</router-link> -->
  17. </div>
  18. </div>
  19. <div class="dashboard-card-body flex-column justify-content-center">
  20. <template v-if="!loading">
  21. <div class="flex-fill position-relative">
  22. <div class="dashboard-fco-wrap">
  23. <div class="account-health-row p-2">
  24. <div class="account-health-title mt-2">{{$t('dashboard.effective_account_health')}}</div>
  25. <div class="account-health-value green-color mt-2">{{isUsageKeyDeny ? 0 : avaliableNum}}{{$t('dashboard.each')}}</div>
  26. </div>
  27. <div class="account-health-row p-2">
  28. <div class="account-health-title">{{$t('dashboard.uneffective_account_health')}}</div>
  29. <div class="account-health-value red-color mt-2">{{isUsageKeyDeny ? 0 : unavaliableNum}}{{$t('dashboard.each')}}</div>
  30. </div>
  31. </div>
  32. </div>
  33. </template>
  34. <template v-else>
  35. <a-empty />
  36. </template>
  37. </div>
  38. </div>
  39. <base-drawer :visible.sync="visible" :title="$t('dashboard.text_5')" @ok="handleSubmit">
  40. <a-form
  41. hideRequiredMark
  42. :form="form.fc"
  43. v-bind="formItemLayout">
  44. <a-form-item :label="$t('dashboard.text_6')">
  45. <a-input v-decorator="decorators.name" />
  46. </a-form-item>
  47. </a-form>
  48. </base-drawer>
  49. </div>
  50. </template>
  51. <script>
  52. import * as R from 'ramda'
  53. import { mapGetters } from 'vuex'
  54. import BaseDrawer from '@Dashboard/components/BaseDrawer'
  55. import { resolveValueChangeField } from '@/utils/common/ant'
  56. import { uuid } from '@/utils/utils'
  57. import { hasPermission } from '@/utils/auth'
  58. export default {
  59. name: 'AccountHealth',
  60. components: {
  61. BaseDrawer,
  62. },
  63. props: {
  64. options: {
  65. type: Object,
  66. required: true,
  67. },
  68. params: Object,
  69. edit: Boolean,
  70. dataRangeParams: {
  71. type: Object,
  72. },
  73. },
  74. data () {
  75. const initialNameValue = (this.params && this.params.name) || this.$t('dashboard.cloud_account_health')
  76. return {
  77. data: [],
  78. visible: false,
  79. loading: false,
  80. avaliableNum: 0,
  81. unavaliableNum: 0,
  82. form: {
  83. fc: this.$form.createForm(this, {
  84. onValuesChange: (props, values) => {
  85. const newField = resolveValueChangeField(values)
  86. R.forEachObjIndexed((item, key) => {
  87. this.$set(this.form.fd, key, item)
  88. }, newField)
  89. },
  90. }),
  91. fd: {
  92. name: initialNameValue,
  93. },
  94. },
  95. decorators: {
  96. name: [
  97. 'name',
  98. {
  99. initialValue: initialNameValue,
  100. rules: [
  101. { required: true, message: this.$t('dashboard.text_8') },
  102. ],
  103. },
  104. ],
  105. },
  106. formItemLayout: {
  107. wrapperCol: {
  108. span: 18,
  109. },
  110. labelCol: {
  111. span: 6,
  112. },
  113. },
  114. }
  115. },
  116. computed: {
  117. ...mapGetters(['scope', 'capability', 'isAdminMode', 'isDomainMode', 'isProjectMode', 'userInfo']),
  118. isResDeny () {
  119. return !hasPermission({ key: 'bill_analysises_list' })
  120. },
  121. isUsageKeyDeny () {
  122. if (this.isAdminMode && this.dataRangeParams?.scope === 'project') {
  123. return true
  124. }
  125. if (this.isDomainMode && this.dataRangeParams?.scope === 'project') {
  126. return true
  127. }
  128. return false
  129. },
  130. },
  131. watch: {
  132. 'form.fd' (val) {
  133. this.fetchData()
  134. for (const key in this.decorators) {
  135. let config = this.decorators[key][1] || {}
  136. config = {
  137. ...config,
  138. initialValue: val[key],
  139. }
  140. this.decorators[key][1] = config
  141. }
  142. },
  143. 'dataRangeParams.scope': {
  144. handler (val) {
  145. this.fetchData()
  146. },
  147. immediate: true,
  148. },
  149. 'dataRangeParams.domain': {
  150. handler (val) {
  151. this.fetchData()
  152. },
  153. immediate: true,
  154. },
  155. 'dataRangeParams.project': {
  156. handler (val) {
  157. this.fetchData()
  158. },
  159. immediate: true,
  160. },
  161. },
  162. created () {
  163. const values = { ...this.form.fd }
  164. this.$emit('update', this.options.i, values)
  165. this.fetchData()
  166. },
  167. methods: {
  168. refresh () {
  169. return this.fetchData()
  170. },
  171. async fetchData () {
  172. this.loading = true
  173. try {
  174. const extraParams = {}
  175. if (this.isAdminMode) {
  176. if (this.dataRangeParams?.scope === 'domain' && this.dataRangeParams?.domain) {
  177. extraParams.domain_id = this.dataRangeParams?.domain
  178. extraParams.scope = 'domain'
  179. }
  180. if (this.dataRangeParams?.scope === 'project' && this.dataRangeParams?.project) {
  181. extraParams.project_id = this.dataRangeParams?.project
  182. extraParams.scope = 'project'
  183. }
  184. }
  185. if (this.isDomainMode) {
  186. if (this.dataRangeParams?.scope === 'project' && this.dataRangeParams?.project) {
  187. extraParams.project_id = this.dataRangeParams?.project
  188. }
  189. }
  190. const [avaliableData, inviladData] = await Promise.all([
  191. new this.$Manager('bill_balances', 'v1').list({
  192. params: {
  193. scope: this.scope,
  194. show_fill_reason: true,
  195. account_id: 'accountList',
  196. limit: 1,
  197. currency: 'CNY',
  198. status: ['connected'],
  199. ignoreErrorStatusCode: [403],
  200. ...extraParams,
  201. },
  202. }),
  203. new this.$Manager('bill_balances', 'v1').list({
  204. params: {
  205. $t: uuid(),
  206. scope: this.scope,
  207. show_fill_reason: true,
  208. account_id: 'accountList',
  209. limit: 1,
  210. currency: 'CNY',
  211. status: ['connected'],
  212. ignoreErrorStatusCode: [403],
  213. ...extraParams,
  214. },
  215. }),
  216. ])
  217. this.avaliableNum = avaliableData.data.total || 0
  218. this.unavaliableNum = inviladData.data.total || 0
  219. } finally {
  220. this.loading = false
  221. }
  222. },
  223. handleEdit () {
  224. this.visible = true
  225. },
  226. async handleSubmit () {
  227. try {
  228. const values = await this.form.fc.validateFields()
  229. this.form.fd = values
  230. const updateValues = { ...values }
  231. this.$emit('update', this.options.i, updateValues)
  232. this.visible = false
  233. } catch (error) {
  234. throw error
  235. }
  236. },
  237. },
  238. }
  239. </script>
  240. <style lang="less">
  241. .account-health-row{
  242. .account-health-value{
  243. font-size: 36px;
  244. }
  245. .green-color{
  246. color: #ADE4B6;
  247. }
  248. .red-color{
  249. color: #F3ADB2;
  250. }
  251. }
  252. </style>