index.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <template>
  2. <a-row :gutter="8">
  3. <a-col v-if="label" :span="24">
  4. <a-tag v-if="label.key">{{ label.key }}: {{ label.value }}</a-tag>
  5. <a-tag v-else>{{ label }}</a-tag>
  6. </a-col>
  7. <a-col :span="colSpan">
  8. <a-select
  9. :loading="registryLoading"
  10. :value="registry"
  11. showSearch
  12. :filterOption="filterOption"
  13. optionLabelProp="label"
  14. @change="handleRegistryChange">
  15. <a-select-option value="" label="">{{ $t('common.tips.select', [$t('compute.eci.repo.image.registry')]) }}</a-select-option>
  16. <a-select-option
  17. v-for="cr in registrys"
  18. :key="cr.value"
  19. :value="cr.value"
  20. :label="cr.label">
  21. <div>{{ cr.label }}</div>
  22. <div style="font-size: 12px; color: #999;">{{ cr.url }}</div>
  23. </a-select-option>
  24. </a-select>
  25. </a-col>
  26. <template v-if="isCustomRegistry">
  27. <a-col :span="16">
  28. <a-input
  29. :value="customImageUrl"
  30. :placeholder="$t('k8s.repo.image.custom.placeholder')"
  31. @change="handleCustomImageUrlChange" />
  32. <div v-if="previewImage" style="font-size: 12px; color: #999; margin-top: 4px;">{{ previewImage }}</div>
  33. </a-col>
  34. </template>
  35. <template v-else>
  36. <a-col :span="colSpan">
  37. <a-select
  38. :loading="imageLoading"
  39. :value="image"
  40. showSearch
  41. :filterOption="filterOption"
  42. @change="handleImageChange">
  43. <a-select-option value="">{{ $t('common.tips.select', [$t('compute.pod-image')]) }}</a-select-option>
  44. <a-select-option
  45. v-for="cr in images"
  46. :key="cr.value"
  47. :value="cr.value">{{ cr.label }}</a-select-option>
  48. </a-select>
  49. </a-col>
  50. <a-col :span="colSpan">
  51. <a-select
  52. :loading="tagLoading"
  53. :value="tag"
  54. showSearch
  55. :filterOption="filterOption"
  56. @change="handleTagChange">
  57. <a-select-option value="">{{ $t('common.tips.select', [$t('compute.repo.image.tag')]) }}</a-select-option>
  58. <a-select-option
  59. v-for="cr in tags"
  60. :key="cr.value"
  61. :value="cr.value">{{ cr.label }}</a-select-option>
  62. </a-select>
  63. </a-col>
  64. </template>
  65. </a-row>
  66. </template>
  67. <script>
  68. import { uuid } from '@/utils/utils'
  69. export default {
  70. name: 'MirrorRegistry',
  71. props: {
  72. isDefaultSelect: {
  73. type: Boolean,
  74. default: true,
  75. },
  76. label: {
  77. type: [String, Object],
  78. },
  79. },
  80. data () {
  81. return {
  82. registryLoading: false,
  83. registry: '',
  84. registrys: [],
  85. imageLoading: false,
  86. image: '',
  87. images: [],
  88. tagLoading: false,
  89. tag: '',
  90. tags: [],
  91. colSpan: 8,
  92. customImageUrl: '',
  93. }
  94. },
  95. computed: {
  96. isCustomRegistry () {
  97. const cur = this.registrys.find(o => o.value === this.registry)
  98. return cur?.type === 'custom'
  99. },
  100. previewImage () {
  101. const cur = this.registrys.find(o => o.value === this.registry)
  102. const url = cur?.url
  103. if (url && this.customImageUrl) {
  104. return `${this.stripProtocol(url)}/${this.customImageUrl}`
  105. }
  106. return ''
  107. },
  108. },
  109. watch: {
  110. registry (val) {
  111. if (!val) {
  112. this.$emit('change', '')
  113. }
  114. },
  115. },
  116. created () {
  117. this.getRegistrys()
  118. },
  119. methods: {
  120. filterOption (input, option) {
  121. return (
  122. option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  123. )
  124. },
  125. handleRegistryChange (val) {
  126. if (val) {
  127. this.registry = val
  128. this.customImageUrl = ''
  129. const cur = this.registrys.find(o => o.value === val)
  130. this.$emit('credential-change', cur?.credential_id || '')
  131. if (cur?.type === 'custom') {
  132. this.image = ''
  133. this.images = []
  134. this.tag = ''
  135. this.tags = []
  136. this.$emit('change', '')
  137. } else {
  138. this.getImagesByRegistryId(val)
  139. }
  140. } else {
  141. this.registry = ''
  142. this.image = ''
  143. this.images = []
  144. this.tag = ''
  145. this.tags = []
  146. this.customImageUrl = ''
  147. this.$emit('change', '')
  148. this.$emit('credential-change', '')
  149. }
  150. },
  151. async getRegistrys () {
  152. try {
  153. const manager = new this.$Manager('container_registries')
  154. this.registryLoading = true
  155. this.registry = ''
  156. this.registrys = []
  157. const params = { details: true, limit: 20, offset: 0, scope: this.$store.getters.scope, $t: uuid() }
  158. const result = await manager.list({ params })
  159. const dataArr = result.data.data || []
  160. this.registrys = dataArr.map(item => {
  161. return {
  162. label: item.name,
  163. value: item.id,
  164. url: item.url,
  165. type: item.type,
  166. credential_id: item.credential_id,
  167. }
  168. })
  169. if (this.isDefaultSelect && this.registrys?.length > 0) {
  170. this.registry = this.registrys?.[0].value
  171. this.getImagesByRegistryId(this.registry)
  172. } else {
  173. this.image = ''
  174. this.tag = ''
  175. }
  176. } catch (error) {
  177. throw error
  178. } finally {
  179. this.registryLoading = false
  180. }
  181. },
  182. handleImageChange (val) {
  183. if (val) {
  184. this.image = val
  185. this.getTagsByImage(this.registry, val)
  186. } else {
  187. this.image = ''
  188. this.tag = ''
  189. this.$emit('change', '')
  190. }
  191. },
  192. async getImagesByRegistryId (rId) {
  193. try {
  194. const manager = new this.$Manager('container_registries')
  195. this.imageLoading = true
  196. this.image = ''
  197. this.images = []
  198. const result = await manager.getSpecific({ id: rId, spec: 'images', params: { $t: uuid() } })
  199. const dataArr = result.data.repositories || []
  200. this.images = dataArr.map(item => {
  201. const v = item.split('/')[1]
  202. return {
  203. label: v,
  204. value: v,
  205. }
  206. })
  207. if (this.images?.length > 0) {
  208. this.image = this.images?.[0].value
  209. this.getTagsByImage(rId, this.image)
  210. }
  211. } catch (error) {
  212. throw error
  213. } finally {
  214. this.imageLoading = false
  215. }
  216. },
  217. handleTagChange (val) {
  218. if (val) {
  219. this.tag = val
  220. this.triggerChange(this.registry, this.image, this.tag)
  221. } else {
  222. this.tag = ''
  223. this.$emit('change', '')
  224. }
  225. },
  226. async getTagsByImage (rId, image) {
  227. try {
  228. const manager = new this.$Manager('container_registries')
  229. this.tagLoading = true
  230. this.tag = ''
  231. this.tags = []
  232. const result = await manager.getSpecific({ id: rId, spec: 'image-tags', params: { repository: image, $t: uuid() } })
  233. const dataArr = result.data.tags || []
  234. this.tags = dataArr.map(item => {
  235. return {
  236. label: item,
  237. value: item,
  238. }
  239. })
  240. if (this.tags?.length > 0) {
  241. this.tag = this.tags?.[0].value
  242. this.triggerChange(this.registry, this.image, this.tag)
  243. }
  244. } catch (error) {
  245. throw error
  246. } finally {
  247. this.tagLoading = false
  248. }
  249. },
  250. stripProtocol (url) {
  251. return url.replace(/^https?:\/\//, '')
  252. },
  253. handleCustomImageUrlChange (e) {
  254. const val = e.target.value
  255. this.customImageUrl = val
  256. const curRegistry = this.registrys.find(o => o.value === this.registry)
  257. const url = curRegistry?.url
  258. if (url && val) {
  259. this.$emit('change', `${this.stripProtocol(url)}/${val}`)
  260. } else {
  261. this.$emit('change', '')
  262. }
  263. },
  264. triggerChange (registry, image, tag) {
  265. const curRegistry = this.registrys.find(o => o.value === registry)
  266. const url = curRegistry?.url
  267. if (url && image && tag) {
  268. this.$emit('change', `${this.stripProtocol(url)}/${image}:${tag}`)
  269. } else {
  270. this.$emit('change', '')
  271. }
  272. },
  273. },
  274. }
  275. </script>
  276. <style>
  277. </style>