List.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  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. :defaultSearchKey="defaultSearchKey"
  15. :export-data-options="exportDataOptions"
  16. :tag-config-params="tagConfigParams"
  17. :show-page="!isTemplate" />
  18. </template>
  19. <script>
  20. import ListMixin from '@/mixins/list'
  21. import ResTemplateListMixin from '@/mixins/resTemplateList'
  22. import { getNameFilter, getFilter, getTenantFilter, getDomainFilter, getStatusFilter, getBrandFilter, getCloudProviderFilter, getAccountFilter, getDescriptionFilter, getCreatedAtFilter } from '@/utils/common/tableFilter'
  23. import { disableDeleteAction } from '@/utils/common/tableActions'
  24. import expectStatus from '@/constants/expectStatus'
  25. import WindowsMixin from '@/mixins/windows'
  26. import globalSearchMixins from '@/mixins/globalSearch'
  27. import { HYPERVISORS_MAP } from '@/constants'
  28. import regexp from '@/utils/regexp'
  29. import SingleActionsMixin from '../mixins/singleActions'
  30. import ColumnsMixin from '../mixins/columns'
  31. export default {
  32. name: 'RDSList',
  33. mixins: [WindowsMixin, ListMixin, globalSearchMixins, ColumnsMixin, SingleActionsMixin, ResTemplateListMixin],
  34. props: {
  35. id: String,
  36. cloudEnv: String,
  37. getParams: {
  38. type: Object,
  39. },
  40. cloudEnvOptions: {
  41. type: Array,
  42. },
  43. },
  44. data () {
  45. return {
  46. list: this.$list.createList(this, {
  47. ctx: this,
  48. id: this.id,
  49. resource: 'dbinstances',
  50. getParams: this.getParam,
  51. isTemplate: this.isTemplate,
  52. templateLimit: this.templateLimit,
  53. steadyStatus: Object.values(expectStatus.rds).flat(),
  54. filterOptions: {
  55. external_id: {
  56. label: this.$t('table.title.external_id'),
  57. },
  58. id: {
  59. label: this.$t('table.title.id'),
  60. },
  61. name: getNameFilter(),
  62. description: getDescriptionFilter(),
  63. status: getStatusFilter('rds'),
  64. brand: getBrandFilter('rds_engine_brands'),
  65. account: getAccountFilter(),
  66. manager: getCloudProviderFilter(),
  67. projects: getTenantFilter(),
  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: getFilter({
  77. field: 'engine',
  78. title: this.$t('db.text_57'),
  79. items: [
  80. { label: 'MySQL', key: 'MySQL' },
  81. { label: 'PostgreSQL', key: 'PostgreSQL' },
  82. { label: 'SQLServer', key: 'SQLServer' },
  83. ],
  84. }),
  85. internal_connection_str: getFilter({
  86. field: 'internal_connection_str',
  87. title: this.$t('db.text_58'),
  88. }),
  89. connection_str: getFilter({
  90. hiddenField: 'internal_connection_str',
  91. field: 'connection_str',
  92. title: this.$t('db.text_59'),
  93. }),
  94. ip_addr: { hiddenField: 'internal_connection_str', label: this.$t('db.url_ip') },
  95. region: {
  96. label: this.$t('db.text_40'),
  97. },
  98. project_domains: getDomainFilter(),
  99. created_at: getCreatedAtFilter(),
  100. },
  101. responseData: this.responseData,
  102. hiddenColumns: ['metadata', 'vcpu_count', 'account', 'created_at'],
  103. autoHiddenFilterKey: 'rds_hidden_columns',
  104. }),
  105. groupActions: [
  106. {
  107. label: this.$t('common.create'),
  108. permission: 'rds_dbinstances_create',
  109. action: () => {
  110. this.$router.push('/rds/create')
  111. },
  112. meta: () => {
  113. return {
  114. buttonType: 'primary',
  115. validate: !this.cloudEnvEmpty,
  116. tooltip: this.cloudEnvEmpty ? this.$t('common.no_platform_available') : '',
  117. }
  118. },
  119. },
  120. {
  121. label: this.$t('db.text_69'),
  122. permission: 'rds_dbinstances_perform_syncstatus',
  123. action: () => {
  124. this.onManager('batchPerformAction', {
  125. id: this.list.selectedItems.map(item => item.id),
  126. managerArgs: {
  127. action: 'sync-status',
  128. },
  129. })
  130. },
  131. meta: () => {
  132. return {
  133. validate: this.list.selectedItems.length > 0,
  134. }
  135. },
  136. },
  137. {
  138. label: this.$t('common.batchAction'),
  139. actions: (obj) => {
  140. const selectedLength = this.list.selectedItems.length
  141. const notSelectedTooltip = selectedLength <= 0 ? this.$t('db.text_68') : ''
  142. const isRunning = this.list.selectedItems.every(item => item.status.toLowerCase() === 'running')
  143. const notRunninTip = !isRunning ? this.$t('db.text_156') : null
  144. return [
  145. {
  146. label: this.$t('db.text_70'),
  147. permission: 'rds_dbinstances_perform_reboot',
  148. action: () => {
  149. this.createDialog('RDSRestartdialog', {
  150. title: this.$t('db.text_70'),
  151. data: this.list.selectedItems,
  152. columns: this.columns,
  153. onManager: this.onManager,
  154. refresh: this.refresh,
  155. })
  156. },
  157. meta: () => {
  158. const ret = {
  159. validate: selectedLength,
  160. tooltip: notSelectedTooltip,
  161. }
  162. // aws 和 azure禁用
  163. let awsOrAzure = ''
  164. this.list.selectedItems.map((item) => {
  165. if (item.brand === HYPERVISORS_MAP.aws.brand || item.brand === HYPERVISORS_MAP.azure.brand) {
  166. awsOrAzure = item.brand
  167. }
  168. })
  169. if (awsOrAzure) {
  170. ret.validate = false
  171. ret.tooltip = this.$t('db.text_384', [awsOrAzure])
  172. }
  173. return ret
  174. },
  175. },
  176. {
  177. label: this.$t('db.text_71'),
  178. permission: 'rds_dbinstances_perform_postpaid_expire',
  179. action: () => {
  180. this.createDialog('SetDurationDialog', {
  181. data: this.list.selectedItems,
  182. columns: this.columns,
  183. alert: this.$t('db.text_391'),
  184. onManager: this.onManager,
  185. refresh: this.refresh,
  186. name: this.$t('dictionary.dbinstances'),
  187. })
  188. },
  189. meta: () => {
  190. const ret = {
  191. validate: false,
  192. tooltip: null,
  193. }
  194. // 包年包月机器,不支持此操作
  195. const isSomePrepaid = this.list.selectedItems.some((item) => {
  196. return item.billing_type === 'prepaid'
  197. })
  198. if (isSomePrepaid) {
  199. ret.tooltip = this.$t('db.text_72')
  200. return ret
  201. }
  202. // 暂只支持同时操作已设置到期或未设置到期释放的机器
  203. const isSomeExpired = this.list.selectedItems.some((item) => {
  204. return item.release_at
  205. })
  206. const isSomeNotExpired = this.list.selectedItems.some((item) => {
  207. return !item.release_at
  208. })
  209. if (isSomeExpired && isSomeNotExpired) {
  210. ret.tooltip = this.$t('db.text_73')
  211. return ret
  212. }
  213. ret.validate = true
  214. return ret
  215. },
  216. },
  217. {
  218. label: this.$t('table.action.set_tag'),
  219. permission: 'rds_dbinstances_perform_set_user_metadata',
  220. action: () => {
  221. this.createDialog('SetTagDialog', {
  222. data: this.list.selectedItems,
  223. columns: this.columns,
  224. onManager: this.onManager,
  225. mode: 'add',
  226. params: {
  227. resources: 'dbinstance',
  228. },
  229. tipName: this.$t('dictionary.dbinstance'),
  230. })
  231. },
  232. },
  233. {
  234. label: this.$t('db.text_157'),
  235. permission: 'rds_dbinstances_perform_renew',
  236. action: () => {
  237. this.createDialog('RedisRenewDialog', {
  238. title: this.$t('db.text_157'),
  239. name: this.$t('dictionary.dbinstances'),
  240. alert: this.$t('network.text_765'),
  241. data: this.list.selectedItems,
  242. columns: this.columns,
  243. onManager: this.onManager,
  244. refresh: this.refresh,
  245. })
  246. },
  247. meta: () => {
  248. const isPrepaid = this.list.selectedItems.every(item => item.billing_type === 'prepaid')
  249. const validate = (isRunning && isPrepaid)
  250. return {
  251. validate: validate,
  252. tooltip: notRunninTip || (!isPrepaid ? this.$t('db.text_158') : null),
  253. }
  254. },
  255. },
  256. {
  257. label: this.$t('db.text_351'),
  258. permission: 'rds_dbinstances_perform_set_auto_renew',
  259. action: () => {
  260. this.createDialog('AutoRenewDialog', {
  261. name: this.$t('dictionary.dbinstances'),
  262. data: this.list.selectedItems,
  263. alert: this.$t('network.text_766'),
  264. columns: this.columns,
  265. onManager: this.onManager,
  266. refresh: this.refresh,
  267. })
  268. },
  269. meta: () => {
  270. const isPrepaid = this.list.selectedItems.every(item => item.billing_type === 'prepaid')
  271. const validate = (isRunning && isPrepaid)
  272. return {
  273. validate: validate,
  274. tooltip: notRunninTip || (!isPrepaid ? this.$t('db.text_158') : null),
  275. }
  276. },
  277. },
  278. disableDeleteAction(Object.assign(this, { permission: 'rds_dbinstances_update' }), {
  279. name: this.$t('dictionary.dbinstances'),
  280. }),
  281. {
  282. label: this.$t('db.text_42'),
  283. permission: 'rds_dbinstances_delete',
  284. action: () => {
  285. this.createDialog('DeleteResDialog', {
  286. vm: this,
  287. title: this.$t('db.text_42'),
  288. data: this.list.selectedItems,
  289. columns: this.columns,
  290. onManager: this.onManager,
  291. refresh: this.refresh,
  292. name: this.$t('dictionary.dbinstances'),
  293. })
  294. },
  295. meta: () => this.$getDeleteResult(this.list.selectedItems),
  296. },
  297. ]
  298. },
  299. meta: () => {
  300. const selectedLength = this.list.selectedItems.length
  301. const notSelectedTooltip = selectedLength <= 0 ? this.$t('db.text_68') : ''
  302. return {
  303. validate: selectedLength,
  304. tooltip: notSelectedTooltip,
  305. }
  306. },
  307. },
  308. ],
  309. tagConfigParams: {
  310. resource: 'dbinstances',
  311. queryTreeId: 'project-tag-value-tree',
  312. },
  313. }
  314. },
  315. computed: {
  316. showActions () {
  317. return !this.$isScopedPolicyMenuHidden('rds_hidden_columns.perform_action')
  318. },
  319. exportDataOptions () {
  320. const ret = {
  321. items: [
  322. { label: 'ID', key: 'id' },
  323. { label: this.$t('dictionary.external_id'), key: 'external_id' },
  324. ...this.columns,
  325. ],
  326. title: this.$t('dictionary.dbinstance'),
  327. downloadType: 'local',
  328. }
  329. ret.items.push({
  330. field: 'expired_at',
  331. title: this.$t('scope.text_791'),
  332. formatter: ({ row }) => {
  333. if (!row.expired_at) return '-'
  334. return this.$moment(row.expired_at).format()
  335. },
  336. })
  337. return ret
  338. },
  339. },
  340. created () {
  341. this.webconsoleManager = new this.$Manager('webconsole', 'v1')
  342. this.list.fetchData()
  343. this.initSidePageTab('detail')
  344. this.$bus.$on('RdsRefresh', () => {
  345. this.refresh()
  346. })
  347. },
  348. beforeDestroy () {
  349. this.$bus.$off('RdsRefresh')
  350. },
  351. methods: {
  352. getParam () {
  353. const ret = {
  354. ...this.getParams,
  355. details: true,
  356. }
  357. return ret
  358. },
  359. handleOpenSidepage (row, tab) {
  360. this.sidePageTriggerHandle(this, 'RDSSidePage', {
  361. id: row.id,
  362. resource: 'dbinstances',
  363. getParams: {
  364. details: true,
  365. },
  366. steadyStatus: Object.values(expectStatus.rds).flat(),
  367. }, {
  368. list: this.list,
  369. tab,
  370. })
  371. },
  372. refresh () {
  373. this.list.refresh()
  374. },
  375. defaultSearchKey (search) {
  376. if (regexp.isIPv4(search)) {
  377. return 'ip_addr'
  378. }
  379. return 'name'
  380. },
  381. },
  382. }
  383. </script>
  384. <style lang="less">
  385. .td-ellipsis {
  386. width: 150px;
  387. word-break: keep-all;
  388. white-space: nowrap;
  389. overflow: hidden;
  390. text-overflow: ellipsis;
  391. }
  392. </style>