Update.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <template>
  2. <base-dialog @cancel="cancelDialog">
  3. <div slot="header">{{action}}</div>
  4. <div slot="body">
  5. <dialog-selected-tips :name="$t('compute.container', [])" :count="params.data.length" :action="action" />
  6. <dialog-table :data="params.data" :columns="columns" />
  7. <a-form :form="form.fc" hideRequiredMark v-bind="formItemLayout">
  8. <a-form-item :label="$t('compute.repo.edit_mode')">
  9. <a-radio-group v-model="editMode">
  10. <a-radio-button value="custom">{{ $t('compute.repo.edit_mode.custom') }}</a-radio-button>
  11. <a-radio-button value="yaml">{{ $t('compute.repo.edit_mode.yaml') }}</a-radio-button>
  12. </a-radio-group>
  13. </a-form-item>
  14. <template v-if="editMode === 'custom'">
  15. <a-form-item :label="$t('compute.repo.image.source')">
  16. <a-radio-group default-value="custom" @change="handleSourceChange">
  17. <a-radio-button value="custom">{{ $t('compute.repo.image.custom') }}</a-radio-button>
  18. <a-radio-button value="registry">{{ $t('compute.repo.image.registry') }}</a-radio-button>
  19. </a-radio-group>
  20. </a-form-item>
  21. <a-form-item v-if="source === 'custom'" :label="$t('compute.repo.container_image')">
  22. <a-input
  23. v-decorator="decorators.image"
  24. :placeholder="$t('common.tips.input', [$t('compute.repo.container_image')])" />
  25. </a-form-item>
  26. <a-form-item v-else :label="$t('compute.repo.container_image')">
  27. <mirror-registry v-decorator="decorators.registryImage" />
  28. </a-form-item>
  29. <a-form-item :label="$t('compute.repo.command')">
  30. <a-input v-decorator="decorators.command" :placeholder="$t('compute.repo.command.placeholder')" />
  31. </a-form-item>
  32. <a-form-item :label="$t('compute.repo.command.params')">
  33. <a-input v-decorator="decorators.arg" :placeholder="$t('compute.repo.command.params.placeholder')" />
  34. </a-form-item>
  35. <a-form-item :label="$t('compute.repo.env_variables')">
  36. <labels ref="envRef" :decorators="decorators.env(0)" :title="$t('compute.repo.variables')" :keyLabel="$t('compute.repo.variables')" />
  37. </a-form-item>
  38. <a-form-item label="">
  39. <a-checkbox v-decorator="decorators.privileged">{{$t('compute.repo.privileged_mode')}}</a-checkbox>
  40. </a-form-item>
  41. </template>
  42. <template v-else>
  43. <a-form-item :label="$t('compute.yaml_config')">
  44. <div class="yaml-config-wrapper">
  45. <code-mirror v-decorator="decorators.yaml" :options="cmOptions" />
  46. </div>
  47. </a-form-item>
  48. </template>
  49. </a-form>
  50. </div>
  51. <div slot="footer">
  52. <a-button type="primary" @click="handleConfirm" :loading="loading">{{ $t('dialog.ok') }}</a-button>
  53. <a-button @click="cancelDialog">{{ $t('dialog.cancel') }}</a-button>
  54. </div>
  55. </base-dialog>
  56. </template>
  57. <script>
  58. import jsYaml from 'js-yaml'
  59. import DialogMixin from '@/mixins/dialog'
  60. import WindowsMixin from '@/mixins/windows'
  61. import MirrorRegistry from '@Compute/sections/MirrorRegistry'
  62. import Labels from '@Compute/sections/Labels'
  63. import { validateYaml } from '@/utils/validate'
  64. export default {
  65. name: 'ContainerUpdateDialog',
  66. components: {
  67. MirrorRegistry,
  68. Labels,
  69. },
  70. mixins: [DialogMixin, WindowsMixin],
  71. data () {
  72. const specData = this.params.data[0].spec || {}
  73. return {
  74. loading: false,
  75. action: this.$t('common.edit'),
  76. source: 'custom', // custom or registry
  77. editMode: 'custom',
  78. form: {
  79. fc: this.$form.createForm(this, {
  80. onValuesChange: (props, values) => {
  81. Object.keys(values).forEach((key) => {
  82. this.$set(this.form.fd, key, values[key])
  83. })
  84. },
  85. }),
  86. fd: {},
  87. },
  88. cmOptions: {
  89. tabSize: 2,
  90. styleActiveLine: true,
  91. lineNumbers: true,
  92. line: true,
  93. mode: 'text/x-yaml',
  94. theme: 'material',
  95. },
  96. decorators: {
  97. registryImage: [
  98. 'registryImage',
  99. {
  100. rules: [
  101. { required: true, message: this.$t('common.tips.select', [this.$t('compute.eci.repo.image.registry')]) },
  102. ],
  103. },
  104. ],
  105. image: [
  106. 'image',
  107. {
  108. initialValue: specData.image,
  109. rules: [
  110. { required: true, message: `${this.$t('common.placeholder')}${this.$t('compute.repo.container_image')}` },
  111. ],
  112. },
  113. ],
  114. command: [
  115. 'command',
  116. {
  117. initialValue: specData.command?.join(' '),
  118. },
  119. ],
  120. arg: [
  121. 'arg',
  122. {
  123. initialValue: specData.args?.join(' '),
  124. },
  125. ],
  126. env: i => ({
  127. key: j => [
  128. `envNames[${i}][${j}]`,
  129. {
  130. rules: [
  131. { required: true, message: this.$t('common.tips.input', [this.$t('compute.repo.variables')]) },
  132. ],
  133. },
  134. ],
  135. value: j => [
  136. `envValues[${i}][${j}]`,
  137. {
  138. rules: [
  139. { required: true, message: this.$t('common.tips.input', [this.$t('compute.repo.value')]) },
  140. ],
  141. },
  142. ],
  143. }),
  144. privileged: [
  145. 'privileged',
  146. {
  147. valuePropName: 'checked',
  148. initialValue: specData.privileged,
  149. },
  150. ],
  151. yaml: [
  152. 'yaml',
  153. {
  154. validateFirst: true,
  155. initialValue: jsYaml.safeDump(this.params.data[0]),
  156. rules: [
  157. { required: true, message: this.$t('common.tips.input', ['Yaml']) },
  158. {
  159. validator: (rule, value, _callback) => {
  160. validateYaml(value)
  161. .then(() => {
  162. return _callback()
  163. })
  164. .catch(() => {
  165. return _callback(this.$t('compute.yaml_check_tip'))
  166. })
  167. },
  168. },
  169. ],
  170. },
  171. ],
  172. },
  173. formItemLayout: {
  174. wrapperCol: {
  175. span: 21,
  176. },
  177. labelCol: {
  178. span: 3,
  179. },
  180. },
  181. }
  182. },
  183. computed: {
  184. columns () {
  185. const showFields = ['name', 'status']
  186. return this.params.columns.filter((item) => { return showFields.includes(item.field) })
  187. },
  188. selectItems () {
  189. return this.params.data
  190. },
  191. },
  192. mounted () {
  193. setTimeout(() => {
  194. const envs = this.selectItems[0].spec?.envs || []
  195. envs.forEach((v, idx) => {
  196. this.$refs.envRef.add()
  197. this.$nextTick(() => {
  198. const labelList = this.$refs.envRef.labelList
  199. this.form.fc.setFieldsValue({
  200. [`envNames[0][${labelList[idx].key}]`]: v.key,
  201. [`envValues[0][${labelList[idx].key}]`]: v.value,
  202. })
  203. })
  204. })
  205. }, 500)
  206. },
  207. methods: {
  208. handleSourceChange (e) {
  209. this.source = e.target.value
  210. },
  211. async doSubmit (values) {
  212. const { id, spec } = this.params.data[0]
  213. const getEnvs = (names, values) => {
  214. const envs = []
  215. if (names) {
  216. for (const k in names) {
  217. envs.push({ key: names[k], value: values[k] })
  218. }
  219. }
  220. return envs
  221. }
  222. let specData = {
  223. ...spec,
  224. }
  225. if (this.editMode === 'custom') {
  226. const { image, registryImage, command, arg, envNames, envValues, privileged } = values
  227. if (image || registryImage) {
  228. specData.image = image || registryImage
  229. }
  230. if (command) {
  231. specData.command = command.split(' ')
  232. }
  233. if (arg) {
  234. specData.args = arg.split(' ')
  235. }
  236. if (envNames) {
  237. specData.envs = getEnvs(envNames[0], envValues[0])
  238. } else {
  239. specData.envs = []
  240. }
  241. specData.privileged = privileged
  242. } else {
  243. const data = jsYaml.safeLoad(values.yaml)
  244. specData = data.spec || {}
  245. }
  246. return this.params.onManager('update', {
  247. id,
  248. managerArgs: {
  249. data: {
  250. spec: specData,
  251. },
  252. },
  253. })
  254. },
  255. async handleConfirm () {
  256. this.loading = true
  257. try {
  258. const values = await this.form.fc.validateFields()
  259. await this.doSubmit(values)
  260. this.loading = false
  261. this.$message.success(this.$t('common.success'))
  262. this.cancelDialog()
  263. } catch (error) {
  264. this.loading = false
  265. this.$message.error(this.$t('common.failed'))
  266. throw error
  267. }
  268. },
  269. },
  270. }
  271. </script>
  272. <style lang="less">
  273. .yaml-config-wrapper {
  274. .CodeMirror {
  275. height: calc(100vh - 530px);
  276. min-height: 500px;
  277. max-height: 80vh;
  278. }
  279. }
  280. </style>