List.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <template>
  2. <page-list
  3. show-tag-columns
  4. show-tag-filter
  5. :list="list"
  6. :columns="templateListColumns || columns"
  7. :group-actions="groupActions"
  8. :single-actions="singleActions"
  9. :export-data-options="exportDataOptions"
  10. :showSearchbox="showSearchbox"
  11. :defaultSearchKey="defaultSearchKey"
  12. :showGroupActions="showGroupActions"
  13. :show-single-actions="!isTemplate"
  14. :show-page="!isTemplate" />
  15. </template>
  16. <script>
  17. import * as R from 'ramda'
  18. import { getNameFilter, getStatusFilter, getEnabledFilter, getProjectDomainFilter, getDescriptionFilter, getCreatedAtFilter } from '@/utils/common/tableFilter'
  19. import expectStatus from '@/constants/expectStatus'
  20. import WindowsMixin from '@/mixins/windows'
  21. import GlobalSearchMixin from '@/mixins/globalSearch'
  22. import ListMixin from '@/mixins/list'
  23. import ResTemplateListMixin from '@/mixins/resTemplateList'
  24. import { getDomainChangeOwnerAction, getSetPublicAction, getEnabledSwitchActions } from '@/utils/common/tableActions'
  25. import { hasServices } from '@/utils/auth'
  26. import regexp from '@/utils/regexp'
  27. import ColumnsMixin from '../mixins/columns'
  28. import SingleActionsMixin from '../mixins/singleActions'
  29. import { canIpmiProbe } from '../utils/status'
  30. import { hostCommonActions } from '../../../utils/hostActions'
  31. export default {
  32. name: 'PhysicalmachineList',
  33. mixins: [WindowsMixin, ListMixin, GlobalSearchMixin, ColumnsMixin, SingleActionsMixin, ResTemplateListMixin],
  34. props: {
  35. id: String,
  36. getParams: {
  37. type: [Function, Object],
  38. },
  39. },
  40. data () {
  41. return {
  42. list: this.$list.createList(this, {
  43. ctx: this,
  44. id: this.id,
  45. resource: 'hosts',
  46. getParams: this.getParam,
  47. isTemplate: this.isTemplate,
  48. templateLimit: this.templateLimit,
  49. steadyStatus: {
  50. status: Object.values(expectStatus.host).flat(),
  51. },
  52. filterOptions: {
  53. id: {
  54. label: this.$t('table.title.id'),
  55. },
  56. name: getNameFilter(),
  57. description: getDescriptionFilter(),
  58. status: getStatusFilter('host'),
  59. enabled: getEnabledFilter(),
  60. sn: {
  61. label: 'SN',
  62. distinctField: {
  63. type: 'extra_field',
  64. key: 'sn',
  65. },
  66. },
  67. any_mac: {
  68. label: 'MAC',
  69. },
  70. any_ip: {
  71. label: 'IP',
  72. },
  73. access_ip: {
  74. label: this.$t('compute.text_503'),
  75. filter: true,
  76. formatter: val => {
  77. return `access_ip.contains("${val}")`
  78. },
  79. },
  80. ipmi_ip: {
  81. label: this.$t('compute.text_504'),
  82. filter: true,
  83. formatter: val => {
  84. return `ipmi_ip.contains("${val}")`
  85. },
  86. },
  87. is_maintenance: {
  88. label: this.$t('compute.text_820'),
  89. dropdown: true,
  90. items: [
  91. { label: this.$t('compute.text_820'), key: true },
  92. { label: this.$t('compute.text_821'), key: false },
  93. ],
  94. },
  95. project_domain: getProjectDomainFilter(),
  96. region: {
  97. label: this.$t('compute.text_177'),
  98. },
  99. zone: {
  100. label: this.$t('compute.text_270'),
  101. },
  102. created_at: getCreatedAtFilter(),
  103. },
  104. responseData: this.responseData,
  105. hiddenColumns: ['metadata', 'access_mac', 'sn', 'public_scope', 'project_domain', 'region', 'created_at'],
  106. fetchDataCb: (res) => {
  107. const { totals = {} } = res.data
  108. this.$emit('resStatisticsChange', totals)
  109. },
  110. }),
  111. exportDataOptions: {
  112. items: [
  113. { label: 'ID', key: 'id' },
  114. { label: this.$t('compute.text_228'), key: 'name' },
  115. { label: this.$t('compute.text_241'), key: 'enabled' },
  116. { label: this.$t('compute.text_268'), key: 'status' },
  117. { label: this.$t('compute.text_503'), key: 'access_ip' },
  118. { label: this.$t('compute.text_504'), key: 'ipmi_ip' },
  119. { label: this.$t('compute.text_847'), key: 'sys_info.manufacture' },
  120. { label: this.$t('compute.text_580'), key: 'sys_info.model' },
  121. { label: 'SN', key: 'sn' },
  122. { label: this.$t('compute.text_602'), key: 'server' },
  123. { label: this.$t('compute.text_820'), key: 'is_maintenance' },
  124. { label: this.$t('compute.text_177'), key: 'region' },
  125. { label: this.$t('compute.text_270'), key: 'zone' },
  126. {
  127. label: this.$t('compute.text_505'),
  128. key: 'public_scope',
  129. hidden: () => {
  130. return !this.$store.getters.l3PermissionEnable && (this.$store.getters.scopeResource && this.$store.getters.scopeResource.domain.includes('cloudaccounts'))
  131. },
  132. },
  133. { label: this.$t('compute.text_506', [this.$t('dictionary.domain')]), key: 'project_domain' },
  134. { label: this.$t('common.createdAt'), key: 'created_at' },
  135. ],
  136. },
  137. }
  138. },
  139. computed: {
  140. groupActions () {
  141. return [
  142. {
  143. label: this.$t('compute.text_822'),
  144. permission: 'hosts_create',
  145. action: () => {
  146. this.$router.push('/physicalmachine/add')
  147. },
  148. meta: () => {
  149. const ret = { validate: true, tooltip: '' }
  150. const hasBMAgent = hasServices('bmagent')
  151. if (!hasBMAgent) {
  152. ret.validate = false
  153. ret.tooltip = this.$t('compute.text_1334')
  154. }
  155. return {
  156. buttonType: 'primary',
  157. ...ret,
  158. }
  159. },
  160. },
  161. ...getEnabledSwitchActions(this, undefined, ['hosts_perform_enable', 'hosts_perform_disable']),
  162. {
  163. label: this.$t('compute.text_275'),
  164. actions: (obj) => {
  165. return [
  166. ...hostCommonActions(this),
  167. getDomainChangeOwnerAction(this, {
  168. name: this.$t('dictionary.host'),
  169. resource: 'hosts',
  170. }, {
  171. permission: 'hosts_perform_change_owner',
  172. }),
  173. getSetPublicAction(this, {
  174. name: this.$t('dictionary.host'),
  175. scope: 'domain',
  176. resource: 'hosts',
  177. }, {
  178. permission: 'hosts_perform_public',
  179. }),
  180. {
  181. label: this.$t('compute.host_ipmi_probe'),
  182. permission: 'hosts_perform_ipmi_probe',
  183. action: () => {
  184. this.list.batchPerformAction('ipmi-probe', null, this.list.steadyStatus)
  185. },
  186. meta: () => {
  187. if (this.list.selectedItems.length <= 0) {
  188. return {
  189. validate: false,
  190. }
  191. }
  192. for (let i = 0; i < this.list.selectedItems.length; i++) {
  193. const obj = this.list.selectedItems[i]
  194. if (!canIpmiProbe(obj)) {
  195. return {
  196. validate: false,
  197. }
  198. }
  199. }
  200. return {
  201. validate: true,
  202. }
  203. },
  204. },
  205. {
  206. label: this.$t('compute.host_prepare'),
  207. permission: 'hosts_perform_prepare',
  208. action: () => {
  209. this.list.batchPerformAction('prepare', null, this.list.steadyStatus)
  210. },
  211. meta: () => {
  212. if (this.list.selectedItems.length <= 0) {
  213. return {
  214. validate: false,
  215. }
  216. }
  217. for (let i = 0; i < this.list.selectedItems.length; i++) {
  218. const obj = this.list.selectedItems[i]
  219. if (!obj.can_prepare) {
  220. return {
  221. validate: false,
  222. }
  223. }
  224. }
  225. return {
  226. validate: true,
  227. }
  228. },
  229. },
  230. {
  231. label: this.$t('compute.text_541'),
  232. permission: 'hosts_perform_set_schedtag',
  233. action: (obj) => {
  234. this.createDialog('HostsAdjustLabelDialog', {
  235. data: this.list.selectedItems,
  236. columns: this.columns,
  237. name: this.$t('dictionary.physicalmachine'),
  238. })
  239. },
  240. meta: () => ({
  241. validate: this.list.selectedItems.length,
  242. }),
  243. },
  244. {
  245. label: this.$t('compute.text_283'),
  246. permission: 'hosts_perform_set_user_metadata',
  247. action: () => {
  248. this.createDialog('SetTagDialog', {
  249. data: this.list.selectedItems,
  250. columns: this.columns,
  251. onManager: this.onManager,
  252. params: {
  253. resources: 'host',
  254. },
  255. mode: 'add',
  256. })
  257. },
  258. meta: () => this.$isOwner(this.list.selectedItems),
  259. },
  260. {
  261. label: this.$t('compute.perform_delete'),
  262. permission: 'hosts_delete',
  263. action: () => {
  264. this.createDialog('DeleteResDialog', {
  265. vm: this,
  266. data: this.list.selectedItems,
  267. columns: this.columns,
  268. title: this.$t('compute.perform_delete'),
  269. onManager: this.onManager,
  270. })
  271. },
  272. meta: () => ({
  273. validate: this.$getDeleteResult(this.list.selectedItems).validate,
  274. tooltip: this.$getDeleteResult(this.list.selectedItems).validate ? '' : this.$t('compute.text_826'),
  275. }),
  276. },
  277. ]
  278. },
  279. meta: () => {
  280. return {
  281. validate: this.list.selected.length,
  282. }
  283. },
  284. },
  285. ]
  286. },
  287. },
  288. watch: {
  289. 'list.filter' (val) {
  290. this.$bus.$emit('ServerFilterChange', val)
  291. },
  292. },
  293. created () {
  294. this.initSidePageTab('physicalmachine-detail')
  295. this.list.fetchData()
  296. },
  297. methods: {
  298. getParam () {
  299. const ret = {
  300. ...(R.is(Function, this.getParams) ? this.getParams() : this.getParams),
  301. with_meta: true,
  302. }
  303. if (this.cloudEnv) ret.cloud_env = this.cloudEnv
  304. return ret
  305. },
  306. handleOpenSidepage (row, tab) {
  307. this.sidePageTriggerHandle(this, 'PhysicalmachineSidePage', {
  308. id: row.id,
  309. resource: 'hosts',
  310. getParams: this.getParam,
  311. steadyStatus: {
  312. status: Object.values(expectStatus.host).flat(),
  313. },
  314. }, {
  315. list: this.list,
  316. tab,
  317. })
  318. },
  319. defaultSearchKey (search) {
  320. if (regexp.isIPv4(search)) {
  321. return 'any_ip'
  322. }
  323. if (regexp.isMAC(search)) {
  324. return 'any_mac'
  325. }
  326. },
  327. },
  328. }
  329. </script>