List.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. <template>
  2. <page-list
  3. show-tag-columns
  4. show-tag-columns2
  5. show-tag-filter
  6. show-tag-config
  7. :columns="templateListColumns || columns"
  8. :group-actions="groupActions"
  9. :list="list"
  10. :single-actions="singleActions"
  11. :showSearchbox="showSearchbox"
  12. :showSingleActions="isTemplate ? false : showActions"
  13. :showGroupActions="showActions && showGroupActions"
  14. :export-data-options="exportDataOptions"
  15. :tag-config-params="tagConfigParams"
  16. :show-page="!isTemplate" />
  17. </template>
  18. <script>
  19. import ListMixin from '@/mixins/list'
  20. import ResTemplateListMixin from '@/mixins/resTemplateList'
  21. import { getNameFilter, getStatusFilter, getTenantFilter, getFilter, getDomainFilter, getBrandFilter, getCloudProviderFilter, getAccountFilter, getDescriptionFilter, getCreatedAtFilter } from '@/utils/common/tableFilter'
  22. import { disableDeleteAction } from '@/utils/common/tableActions'
  23. import expectStatus from '@/constants/expectStatus'
  24. import WindowsMixin from '@/mixins/windows'
  25. import globalSearchMixins from '@/mixins/globalSearch'
  26. import { HYPERVISORS_MAP } from '@/constants'
  27. import SingleActionsMixin from '../mixins/singleActions'
  28. import ColumnsMixin from '../mixins/columns'
  29. import { ENGINE_ARCH } from '../constants/index.js'
  30. export default {
  31. name: 'RedisList',
  32. mixins: [WindowsMixin, globalSearchMixins, ListMixin, ColumnsMixin, SingleActionsMixin, ResTemplateListMixin],
  33. props: {
  34. id: String,
  35. cloudEnv: String,
  36. getParams: {
  37. type: Object,
  38. },
  39. cloudEnvOptions: {
  40. type: Array,
  41. },
  42. },
  43. data () {
  44. return {
  45. list: this.$list.createList(this, {
  46. ctx: this,
  47. id: this.id,
  48. resource: 'elasticcaches',
  49. getParams: this.getParam,
  50. isTemplate: this.isTemplate,
  51. templateLimit: this.templateLimit,
  52. steadyStatus: Object.values(expectStatus.redis).flat(),
  53. filterOptions: {
  54. external_id: {
  55. label: this.$t('table.title.external_id'),
  56. },
  57. id: {
  58. label: this.$t('table.title.id'),
  59. },
  60. name: getNameFilter(),
  61. description: getDescriptionFilter(),
  62. status: getStatusFilter('redis'),
  63. brand: getBrandFilter('redis_engine_brands'),
  64. account: getAccountFilter(),
  65. manager: getCloudProviderFilter(),
  66. projects: getTenantFilter(),
  67. project_domains: getDomainFilter(),
  68. billing_type: getFilter({
  69. field: 'billing_type',
  70. title: this.$t('db.text_54'),
  71. items: [
  72. { label: this.$t('db.text_55'), key: 'postpaid' },
  73. { label: this.$t('db.text_56'), key: 'prepaid' },
  74. ],
  75. }),
  76. engine_version: {
  77. label: this.$t('db.text_236'),
  78. dropdown: true,
  79. multiple: true,
  80. hiddenField: 'engine',
  81. distinctField: {
  82. type: 'field',
  83. key: 'engine_version',
  84. },
  85. },
  86. local_category: {
  87. label: this.$t('db.text_119'),
  88. hiddenField: 'instance_type',
  89. dropdown: true,
  90. multiple: true,
  91. items: Object.keys(ENGINE_ARCH).map(key => {
  92. return { label: ENGINE_ARCH[key], key }
  93. }),
  94. },
  95. private_dns: getFilter({
  96. field: 'private_dns',
  97. title: this.$t('db.text_58'),
  98. }),
  99. public_dns: getFilter({
  100. field: 'public_dns',
  101. hiddenField: 'private_dns',
  102. title: this.$t('db.text_59'),
  103. }),
  104. region: {
  105. label: this.$t('db.text_40'),
  106. },
  107. created_at: getCreatedAtFilter(),
  108. },
  109. responseData: this.responseData,
  110. hiddenColumns: ['metadata', 'instance_type', 'created_at'],
  111. autoHiddenFilterKey: 'redis_hidden_columns',
  112. }),
  113. groupActions: [
  114. {
  115. label: this.$t('db.text_41'),
  116. permission: 'redis_elasticcaches_create',
  117. action: () => {
  118. this.createServer()
  119. },
  120. meta: () => {
  121. return {
  122. buttonType: 'primary',
  123. validate: !this.cloudEnvEmpty,
  124. tooltip: this.cloudEnvEmpty ? this.$t('common.no_platform_available') : '',
  125. }
  126. },
  127. },
  128. {
  129. label: this.$t('db.text_69'),
  130. permission: 'redis_elasticcaches_perform_sync',
  131. action: () => {
  132. this.onManager('batchPerformAction', {
  133. id: this.list.selectedItems.map(item => item.id),
  134. managerArgs: {
  135. action: 'Sync',
  136. },
  137. })
  138. },
  139. meta: () => {
  140. return {
  141. validate: this.list.selectedItems.length > 0,
  142. }
  143. },
  144. },
  145. {
  146. label: this.$t('db.text_213'),
  147. actions: (obj) => {
  148. const selectedLength = this.list.selectedItems.length
  149. const notSelectedTooltip = selectedLength <= 0 ? this.$t('db.text_68') : ''
  150. const isRunning = this.list.selectedItems.every(item => item.status.toLowerCase() === 'running')
  151. const notRunninTip = !isRunning ? this.$t('db.text_156') : null
  152. return [
  153. {
  154. label: this.$t('db.text_239'),
  155. permission: 'redis_elasticcaches_perform_flush_instance',
  156. action: () => {
  157. this.createDialog('RedisClearDataDialog', {
  158. title: this.$t('db.text_239'),
  159. data: this.list.selectedItems,
  160. columns: this.columns,
  161. onManager: this.onManager,
  162. refresh: this.refresh,
  163. name: this.$t('dictionary.elasticcaches'),
  164. })
  165. },
  166. meta: () => {
  167. const ret = {
  168. validate: selectedLength,
  169. tooltip: notSelectedTooltip,
  170. }
  171. // aws 和 azure禁用
  172. let awsOrAzure = ''
  173. this.list.selectedItems.map((item) => {
  174. if (item.brand === HYPERVISORS_MAP.aws.brand || item.brand === HYPERVISORS_MAP.azure.brand) {
  175. awsOrAzure = item.brand
  176. }
  177. })
  178. if (awsOrAzure) {
  179. ret.validate = false
  180. ret.tooltip = this.$t('db.text_384', [awsOrAzure])
  181. }
  182. return ret
  183. },
  184. },
  185. {
  186. label: this.$t('table.action.set_tag'),
  187. permission: 'redis_elasticcaches_perform_set_user_metadata',
  188. action: () => {
  189. this.createDialog('SetTagDialog', {
  190. data: this.list.selectedItems,
  191. columns: this.columns,
  192. onManager: this.onManager,
  193. mode: 'add',
  194. params: {
  195. resources: 'elasticcache',
  196. },
  197. tipName: this.$t('dictionary.elasticcache'),
  198. })
  199. },
  200. },
  201. {
  202. label: this.$t('db.text_70'),
  203. permission: 'redis_elasticcaches_perform_restart',
  204. action: () => {
  205. this.createDialog('RedisRestartdialog', {
  206. title: this.$t('db.text_70'),
  207. data: this.list.selectedItems,
  208. columns: this.columns,
  209. onManager: this.onManager,
  210. refresh: this.refresh,
  211. name: this.$t('dictionary.elasticcaches'),
  212. })
  213. },
  214. meta: () => {
  215. const isNotQcloud = this.list.selectedItems.every(item => item.brand !== 'Qcloud')
  216. const isQcloudTip = isNotQcloud ? null : this.$t('db.text_358')
  217. const ret = {
  218. validate: selectedLength && isRunning && isNotQcloud,
  219. tooltip: notSelectedTooltip || notRunninTip || isQcloudTip,
  220. }
  221. // aws 和 azure禁用
  222. let awsOrAzure = ''
  223. this.list.selectedItems.map((item) => {
  224. if (item.brand === HYPERVISORS_MAP.aws.brand || item.brand === HYPERVISORS_MAP.azure.brand) {
  225. awsOrAzure = item.brand
  226. }
  227. })
  228. if (awsOrAzure && ret.validate) {
  229. ret.validate = false
  230. ret.tooltip = this.$t('db.text_384', [awsOrAzure])
  231. }
  232. return ret
  233. },
  234. },
  235. {
  236. label: this.$t('db.text_71'),
  237. permission: 'redis_elasticcaches_perform_postpaid_expire',
  238. action: () => {
  239. this.createDialog('SetDurationDialog', {
  240. data: this.list.selectedItems,
  241. columns: this.columns,
  242. alert: this.$t('db.text_393'),
  243. onManager: this.onManager,
  244. refresh: this.refresh,
  245. name: this.$t('dictionary.elasticcaches'),
  246. })
  247. },
  248. meta: () => {
  249. const ret = {
  250. validate: false,
  251. tooltip: null,
  252. }
  253. // 包年包月机器,不支持此操作
  254. const isSomePrepaid = this.list.selectedItems.some((item) => {
  255. return item.billing_type === 'prepaid'
  256. })
  257. if (isSomePrepaid) {
  258. ret.tooltip = this.$t('db.text_72')
  259. return ret
  260. }
  261. // 暂只支持同时操作已设置到期或未设置到期释放的机器
  262. const isSomeExpired = this.list.selectedItems.some((item) => {
  263. return item.release_at
  264. })
  265. const isSomeNotExpired = this.list.selectedItems.some((item) => {
  266. return !item.release_at
  267. })
  268. if (isSomeExpired && isSomeNotExpired) {
  269. ret.tooltip = this.$t('db.text_73')
  270. return ret
  271. }
  272. ret.validate = true
  273. return ret
  274. },
  275. },
  276. {
  277. label: this.$t('db.text_157'),
  278. permission: 'redis_elasticcaches_perform_renew',
  279. action: () => {
  280. this.createDialog('RedisRenewDialog', {
  281. title: this.$t('db.text_157'),
  282. name: this.$t('dictionary.elasticcaches'),
  283. alert: this.$t('network.text_765'),
  284. data: this.list.selectedItems,
  285. columns: this.columns,
  286. onManager: this.onManager,
  287. refresh: this.refresh,
  288. })
  289. },
  290. meta: () => {
  291. const isPrepaid = this.list.selectedItems.every(item => item.billing_type === 'prepaid')
  292. const validate = (isRunning && isPrepaid)
  293. return {
  294. validate: validate,
  295. tooltip: notRunninTip || (!isPrepaid ? this.$t('db.text_158') : null),
  296. }
  297. },
  298. },
  299. {
  300. label: this.$t('db.text_351'),
  301. permission: 'redis_elasticcaches_perform_set_auto_renew',
  302. action: () => {
  303. this.createDialog('AutoRenewDialog', {
  304. name: this.$t('dictionary.elasticcaches'),
  305. data: this.list.selectedItems,
  306. alert: this.$t('network.text_766'),
  307. columns: this.columns,
  308. onManager: this.onManager,
  309. refresh: this.refresh,
  310. })
  311. },
  312. meta: () => {
  313. const isPrepaid = this.list.selectedItems.every(item => item.billing_type === 'prepaid')
  314. const validate = (isRunning && isPrepaid)
  315. return {
  316. validate: validate,
  317. tooltip: notRunninTip || (!isPrepaid ? this.$t('db.text_158') : null),
  318. }
  319. },
  320. },
  321. disableDeleteAction(Object.assign(this, { permission: 'redis_elasticcaches_update' }), {
  322. name: this.$t('dictionary.elasticcaches'),
  323. }),
  324. {
  325. label: this.$t('db.text_42'),
  326. permission: 'redis_elasticcaches_delete',
  327. action: () => {
  328. this.createDialog('DeleteResDialog', {
  329. vm: this,
  330. title: this.$t('db.text_42'),
  331. data: this.list.selectedItems,
  332. columns: this.columns,
  333. onManager: this.onManager,
  334. refresh: this.refresh,
  335. name: this.$t('dictionary.elasticcaches'),
  336. })
  337. },
  338. meta: () => this.$getDeleteResult(this.list.selectedItems),
  339. },
  340. ]
  341. },
  342. meta: () => {
  343. const selectedLength = this.list.selectedItems.length
  344. const notSelectedTooltip = selectedLength <= 0 ? this.$t('db.text_68') : ''
  345. return {
  346. validate: selectedLength,
  347. tooltip: notSelectedTooltip,
  348. }
  349. },
  350. },
  351. ],
  352. tagConfigParams: {
  353. resource: 'elasticcaches',
  354. queryTreeId: 'project-tag-value-tree',
  355. },
  356. }
  357. },
  358. computed: {
  359. showActions () {
  360. return !this.$isScopedPolicyMenuHidden('redis_hidden_columns.perform_action')
  361. },
  362. exportDataOptions () {
  363. const ret = {
  364. items: [
  365. { label: 'ID', key: 'id' },
  366. { label: this.$t('dictionary.external_id'), key: 'external_id' },
  367. ...this.columns,
  368. ],
  369. title: this.$t('dictionary.elasticcache'),
  370. downloadType: 'local',
  371. fixedItems: [
  372. { key: 'capacity_mb', label: this.$t('db.text_109') + '(M)' },
  373. ],
  374. hiddenFields: ['instance_type'],
  375. }
  376. ret.items.push({
  377. field: 'expired_at',
  378. title: this.$t('scope.text_791'),
  379. formatter: ({ row }) => {
  380. if (!row.expired_at) return '-'
  381. return this.$moment(row.expired_at).format()
  382. },
  383. })
  384. return ret
  385. },
  386. },
  387. created () {
  388. this.list.fetchData()
  389. this.initSidePageTab('redis-detail')
  390. },
  391. methods: {
  392. getParam () {
  393. const ret = {
  394. ...this.getParams,
  395. details: true,
  396. }
  397. return ret
  398. },
  399. createServer () {
  400. this.$router.push('/redis/create')
  401. },
  402. getSeachStatus () {
  403. const selectedStatus = ['running', 'unknown', 'sync_failed']
  404. const status = []
  405. for (const key in this.$t('status.redis')) {
  406. if (selectedStatus.indexOf(key) > -1) {
  407. status.push({
  408. key,
  409. label: this.$t('status.redis')[key],
  410. })
  411. }
  412. }
  413. return status
  414. },
  415. handleOpenSidepage (row, tab) {
  416. this.sidePageTriggerHandle(this, 'RedisSidePage', {
  417. id: row.id,
  418. resource: 'elasticcaches',
  419. getParams: {
  420. details: true,
  421. },
  422. steadyStatus: Object.values(expectStatus.redis).flat(),
  423. }, {
  424. list: this.list,
  425. tab,
  426. })
  427. },
  428. },
  429. }
  430. </script>
  431. <style lang="less">
  432. .td-ellipsis {
  433. width: 150px;
  434. word-break: keep-all;
  435. white-space: nowrap;
  436. overflow: hidden;
  437. text-overflow: ellipsis;
  438. }
  439. </style>