index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <template>
  2. <div>
  3. <page-header :title="$t('common_628', [$t('dictionary.cdn_domain')])" />
  4. <page-body needMarginBottom>
  5. <a-form :form="form.fc" class="mt-3" v-bind="formItemLayout" hideRequiredMark>
  6. <a-form-item :label="$t('network.text_205', [$t('dictionary.project')])" class="mb-0">
  7. <domain-project
  8. :fc="form.fc"
  9. :form-layout="formItemLayout"
  10. :decorators="{ project: decorators.project, domain: decorators.domain }" />
  11. </a-form-item>
  12. <a-form-item :label="$t('network.cdn.cloudprovider')">
  13. <base-select
  14. resource="cloudproviders"
  15. v-decorator="decorators.cloudprovider"
  16. :params="params.cloudprovider"
  17. :isDefaultSelect="true"
  18. :showSync="true"
  19. :select-props="{ placeholder: $t('compute.text_149') }" />
  20. </a-form-item>
  21. <a-form-item :label="$t('network.cdn.accelerated_domain')">
  22. <a-input v-decorator="decorators.accelerated_domain" />
  23. </a-form-item>
  24. <a-form-item :label="$t('network.cdn.area')">
  25. <a-radio-group v-decorator="decorators.area">
  26. <a-radio-button v-for="item in areaOpts" :value="item.key" :key="item.key">{{ item.label }}</a-radio-button>
  27. </a-radio-group>
  28. </a-form-item>
  29. <a-form-item :label="$t('network.cdn.service_type')">
  30. <a-select v-decorator="decorators.service_type">
  31. <a-select-option v-for="item in serviceTypeOpts" :key="item.key">{{ item.label }}</a-select-option>
  32. </a-select>
  33. </a-form-item>
  34. <a-form-item :label="$t('network.cdn.origin_types')">
  35. <a-radio-group v-decorator="decorators.origin_type">
  36. <a-radio-button v-for="item in originTypeOpts" :value="item.key" :key="item.key">{{ item.label }}</a-radio-button>
  37. </a-radio-group>
  38. </a-form-item>
  39. <a-form-item :label="$t('network.cdn.source_protocol')">
  40. <a-radio-group v-decorator="decorators.origin_protocol">
  41. <a-radio-button v-for="item in originProtocols" :value="item.key" :key="item.key">{{ item.label }}</a-radio-button>
  42. </a-radio-group>
  43. </a-form-item>
  44. <a-form-item
  45. v-for="(k, index) in form.fc.getFieldValue('keys')"
  46. :key="k"
  47. v-bind="index === 0 ? formItemLayout : formItemLayoutWithOutLabel"
  48. :label="index === 0 ? $t('network.cdn.source_origin') : ''"
  49. :required="false">
  50. <a-row :gutter="6">
  51. <a-col :span="8">
  52. <a-form-item
  53. :wrapperCol="{ span: 24 }"
  54. class="mb-0 mr-1">
  55. <a-input v-decorator="decorators.originAddress.origin(k)" :placeholder="$t('network.cdn.origin')" />
  56. </a-form-item>
  57. </a-col>
  58. <a-col :span="8">
  59. <a-form-item
  60. :wrapperCol="{ span: 24 }"
  61. class="mb-0 mr-1">
  62. <a-input v-decorator="decorators.originAddress.port(k)" :placeholder="$t('network.text_165')" />
  63. </a-form-item>
  64. </a-col>
  65. <a-col :span="7">
  66. <a-form-item
  67. :wrapperCol="{ span: 24 }"
  68. class="mb-0 mr-1">
  69. <a-input v-decorator="decorators.originAddress.priority(k)" :placeholder="$t('network.text_166')" />
  70. </a-form-item>
  71. </a-col>
  72. <a-col :span="1">
  73. <a-button v-if="index === 0" type="primary" shape="circle" icon="plus" size="small" @click="add" />
  74. <a-button v-else shape="circle" icon="minus" size="small" @click="remove(k)" />
  75. </a-col>
  76. </a-row>
  77. </a-form-item>
  78. </a-form>
  79. </page-body>
  80. <page-footer>
  81. <div slot="right">
  82. <a-button class="mr-3" type="primary" @click="handleConfirm" :loading="loading">
  83. {{$t('compute.text_907')}}
  84. </a-button>
  85. <a-button @click="handleCancel">{{$t('compute.text_908')}}</a-button>
  86. </div>
  87. </page-footer>
  88. </div>
  89. </template>
  90. <script>
  91. import { validate, isRequired } from '@/utils/validate'
  92. import { Manager } from '@/utils/manager'
  93. import DomainProject from '@/sections/DomainProject'
  94. import { AREAS, SERVICE_TYPES, ORIGIN_TYPES, ORIGIN_PROTOCOLS } from '../constants'
  95. let id = 0
  96. export default {
  97. name: 'CdnCreate',
  98. components: {
  99. DomainProject,
  100. },
  101. data () {
  102. return {
  103. areaOpts: AREAS,
  104. serviceTypeOpts: SERVICE_TYPES,
  105. originTypeOpts: ORIGIN_TYPES,
  106. originProtocols: ORIGIN_PROTOCOLS,
  107. loading: false,
  108. decorators: {
  109. domain: [
  110. 'domain',
  111. {
  112. rules: [
  113. { validator: isRequired(), message: this.$t('rules.domain'), trigger: 'change' },
  114. ],
  115. },
  116. ],
  117. project: [
  118. 'project',
  119. {
  120. rules: [
  121. { validator: isRequired(), message: this.$t('dictionary.project'), trigger: 'change' },
  122. ],
  123. },
  124. ],
  125. cloudprovider: [
  126. 'cloudprovider',
  127. {
  128. rules: [
  129. { required: true, message: this.$t('network.text_689') },
  130. ],
  131. },
  132. ],
  133. accelerated_domain: [
  134. 'accelerated_domain',
  135. {
  136. validateFirst: true,
  137. rules: [
  138. { required: true, message: this.$t('common.tips.input', [this.$t('network.cdn.accelerated_domain')]) },
  139. { validator: this.checkDomainHandle },
  140. ],
  141. },
  142. ],
  143. area: [
  144. 'area',
  145. {
  146. rules: [
  147. { required: true, message: this.$t('network.cdn.area_require_message') },
  148. ],
  149. initialValue: 'mainland',
  150. },
  151. ],
  152. service_type: [
  153. 'service_type',
  154. {
  155. initialValue: 'web',
  156. },
  157. ],
  158. origin_type: [
  159. 'origin_type',
  160. {
  161. initialValue: 'domain',
  162. },
  163. ],
  164. origin_protocol: [
  165. 'origin_protocol',
  166. {
  167. initialValue: 'http',
  168. },
  169. ],
  170. originAddress: {
  171. origin: i => [
  172. `origin[${i}]`,
  173. {
  174. validateFirst: true,
  175. validateTrigger: ['change', 'blur'],
  176. rules: [
  177. { required: true, message: this.$t('network.cdn.origin_require_message') },
  178. { validator: this.validateIpOrDomain },
  179. { validator: this.validateOriginRepeat },
  180. ],
  181. },
  182. ],
  183. port: i => [
  184. `port[${i}]`,
  185. {
  186. // validateTrigger: ['change', 'blur'],
  187. // rules: [
  188. // { required: true, message: this.$t('network.cdn.port_require_message') },
  189. // ],
  190. },
  191. ],
  192. priority: i => [
  193. `priority[${i}]`,
  194. {
  195. validateTrigger: ['change', 'blur'],
  196. rules: [
  197. // { required: true, message: this.$t('network.cdn.priority_require_message') },
  198. { validator: this.validatePriority },
  199. ],
  200. },
  201. ],
  202. },
  203. },
  204. params: {
  205. domain: {
  206. scope: this.$store.getters.scope,
  207. limit: 0,
  208. },
  209. cloudprovider: {
  210. scope: this.$store.getters.scope,
  211. brand: 'Qcloud',
  212. },
  213. },
  214. formItemLayout: {
  215. wrapperCol: {
  216. md: { span: 18 },
  217. xl: { span: 20 },
  218. xxl: { span: 22 },
  219. },
  220. labelCol: {
  221. md: { span: 6 },
  222. xl: { span: 4 },
  223. xxl: { span: 2 },
  224. },
  225. },
  226. formItemLayoutWithOutLabel: {
  227. wrapperCol: {
  228. md: { span: 18, offset: 6 },
  229. xl: { span: 20, offset: 4 },
  230. xxl: { span: 22, offset: 2 },
  231. },
  232. },
  233. }
  234. },
  235. beforeCreate () {
  236. this.form = {}
  237. this.form.fc = this.$form.createForm(this, { name: 'cdn_create_form' })
  238. this.form.fc.getFieldDecorator('keys', { initialValue: [id], preserve: true })
  239. },
  240. methods: {
  241. handleCancel () {
  242. this.goBack()
  243. },
  244. generateValues (values) {
  245. const data = {
  246. domain: values.domain.key,
  247. tenant: values.project.key,
  248. cloudprovider_id: values.cloudprovider,
  249. name: values.accelerated_domain,
  250. area: values.area,
  251. service_type: values.service_type,
  252. }
  253. const origins = []
  254. values.keys.forEach(key => {
  255. origins.push({
  256. origin: values.origin[key],
  257. port: values.port[key],
  258. priority: values.priority[key],
  259. protocol: values.origin_protocol,
  260. type: this.getType(values.origin[key]),
  261. })
  262. })
  263. data.origins = origins
  264. return data
  265. },
  266. async handleConfirm () {
  267. const { validateFields } = this.form.fc
  268. const manager = new Manager('cdn_domains')
  269. try {
  270. const values = await validateFields()
  271. this.loading = true
  272. await manager.create({
  273. data: Object.assign({}, this.generateValues(values)),
  274. })
  275. this.goBack()
  276. } catch (err) {
  277. throw err
  278. } finally {
  279. this.loading = false
  280. }
  281. },
  282. checkDomainHandle (rule, value, callback) {
  283. if (validate(value, 'domain') === false || validate(value, 'domain').result === false) {
  284. callback(new Error(this.$t('network.text_178')))
  285. }
  286. callback()
  287. },
  288. add () {
  289. const { form } = this
  290. const keys = form.fc.getFieldValue('keys')
  291. const nextKeys = keys.concat(++id)
  292. form.fc.setFieldsValue({
  293. keys: nextKeys,
  294. })
  295. form.fc.validateFields(['origin', 'priority'], { force: true })
  296. },
  297. remove (k) {
  298. const { form } = this
  299. const keys = form.fc.getFieldValue('keys')
  300. const orgins = form.fc.getFieldValue('origin')
  301. if (keys.length === 1) {
  302. return
  303. }
  304. form.fc.setFieldsValue({
  305. keys: keys.filter(key => key !== k),
  306. origin: orgins.filter(origin => origin !== orgins[k]),
  307. })
  308. form.fc.validateFields(['origin', 'priority'], { force: true })
  309. },
  310. goBack () {
  311. this.$router.push({
  312. name: 'CdnList',
  313. })
  314. },
  315. validateOriginRepeat (rule, value, callback) {
  316. const { form } = this
  317. this.$nextTick(() => {
  318. const orgins = form.fc.getFieldValue('origin')
  319. const isRepeat = orgins.filter(item => item === value).length > 1
  320. if (value && orgins.length > 1 && isRepeat) {
  321. // eslint-disable-next-line standard/no-callback-literal
  322. callback(this.$t('network.cdn.origin_repeat_validate'))
  323. } else {
  324. callback()
  325. }
  326. })
  327. },
  328. validatePriority (rule, value, callback) {
  329. const { form } = this
  330. this.$nextTick(() => {
  331. const prioritys = form.fc.getFieldValue('priority')
  332. if (value && prioritys.length === 1) {
  333. // eslint-disable-next-line standard/no-callback-literal
  334. callback(this.$t('network.cdn.priority_validate'))
  335. } else {
  336. callback()
  337. }
  338. })
  339. },
  340. validateIpOrDomain (rule, value, callback) {
  341. if (/^[a-zA-Z]/.test(value)) {
  342. return this.$validate('domain')(rule, value, callback)
  343. } else if (/^[0-9]/.test(value)) {
  344. return this.$validate('IPv4')(rule, value, callback)
  345. }
  346. callback()
  347. },
  348. getType (value) {
  349. if (/^[0-9]/.test(value) && validate(value, 'IPv4')) {
  350. return 'ip'
  351. } else if (/^[a-zA-Z]/.test(value) && validate(value, 'domain')) {
  352. return 'domain'
  353. }
  354. return ''
  355. },
  356. },
  357. }
  358. </script>
  359. <style>
  360. </style>