mirror of https://github.com/certd/certd
refactor: form input
parent
b4ee3d0dfc
commit
eab0c3be60
|
@ -1,6 +1,5 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
],
|
||||
plugins: ['@babel/plugin-proposal-optional-chaining']
|
||||
]
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,36 +9,43 @@
|
|||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.12.7",
|
||||
"@certd/plugins": "^0.1.11",
|
||||
"@certd/providers": "^0.1.11",
|
||||
"ant-design-vue": "^2.0.0-rc.8",
|
||||
"core-js": "^3.6.5",
|
||||
"lodash-es": "^4.17.20",
|
||||
"vue": "^3.0.0",
|
||||
"vue-i18n": "^9.0.0-rc.2",
|
||||
"vue-router": "^4.0.0-0"
|
||||
"core-js": "^3.8.1",
|
||||
"vue": "^3.0.4",
|
||||
"vue-router": "^4.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-plugin-router": "~4.5.0",
|
||||
"@vue/cli-plugin-unit-mocha": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"@vue/eslint-config-standard": "^5.1.2",
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/eslint-parser": "^7.12.1",
|
||||
"@vue/cli-plugin-babel": "~5.0.0-alpha.3",
|
||||
"@vue/cli-plugin-eslint": "~5.0.0-alpha.3",
|
||||
"@vue/cli-plugin-router": "~5.0.0-alpha.3",
|
||||
"@vue/cli-plugin-unit-mocha": "~5.0.0-alpha.3",
|
||||
"@vue/cli-plugin-webpack-4": "^5.0.0-alpha.3",
|
||||
"@vue/cli-service": "~5.0.0-alpha.3",
|
||||
"@vue/compiler-sfc": "^3.0.4",
|
||||
"@vue/eslint-config-standard": "^6.0.0",
|
||||
"@vue/test-utils": "^2.0.0-0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"chai": "^4.1.2",
|
||||
"eslint": "^6.7.2",
|
||||
"chai": "^4.2.0",
|
||||
"eslint": "^7.15.0",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
"eslint-plugin-vue": "^7.0.0-0",
|
||||
"eslint-plugin-standard": "^5.0.0",
|
||||
"eslint-plugin-vue": "^7.2.0",
|
||||
"less": "^3.0.4",
|
||||
"less-loader": "^5.0.0",
|
||||
"lint-staged": "^9.5.0"
|
||||
"lint-staged": "^9.5.0",
|
||||
"postcss": "^8.2.4",
|
||||
"webpack": "^4.0.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@vue/cli-*/webpack": "^4.0.0"
|
||||
},
|
||||
"gitHooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<a-list
|
||||
class="list"
|
||||
item-layout="horizontal"
|
||||
:data-source="providerList"
|
||||
:data-source="getProviders()"
|
||||
>
|
||||
<template #renderItem="{ item ,index }">
|
||||
<a-list-item>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<a-button type="danger" @click="remove(item,index)"><template #icon ><DeleteOutlined /></template></a-button>
|
||||
</template>
|
||||
|
||||
<a-radio :checked="item.key===selectedKey" @update:checked="selectedKey = item.key">
|
||||
<a-radio :disabled="isDisabled(item)" :checked="item.key===selectedKey" @update:checked="selectedKey = item.key" >
|
||||
{{ item.name }} ({{item.type}})
|
||||
</a-radio>
|
||||
|
||||
|
@ -39,10 +39,12 @@
|
|||
|
||||
<a-modal v-model:visible="editVisible" dialogClass="d-dialog" width="700px" title="编辑授权" @ok="onSubmit">
|
||||
|
||||
<a-alert v-if="currentProvider?.desc" :message="currentProvider.desc" type="success" />
|
||||
|
||||
<a-form ref="formRef" class="domain-form" :model="formData" labelWidth="150px" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-form-item label="类型" name="type" :rules="rules.type">
|
||||
<a-radio-group :disabled="editIndex!=null" v-model:value="formData.type" @change="onTypeChanged" >
|
||||
<a-radio-button v-for="(option) of providerDefineList" :key="option.name" :value="option.name">
|
||||
<a-radio-button v-for="(option) of providerDefineList" :disabled="isDisabled(option,'name')" :key="option.name" :value="option.name">
|
||||
{{option.label}}
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
|
@ -58,7 +60,9 @@
|
|||
:label="item.label || key"
|
||||
:name="key">
|
||||
<component-render v-model:value="formData[key]" v-bind="item.component || {}"></component-render>
|
||||
<div class="helper">{{item.desc}}</div>
|
||||
<template #extra >
|
||||
<div v-if="item.desc" class="helper">{{item.desc}}</div>
|
||||
</template>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
|
@ -68,12 +72,12 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive, nextTick, watch } from 'vue'
|
||||
import { ref, reactive, nextTick, watch, inject } from 'vue'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { useForm } from '@ant-design-vue/use'
|
||||
import _ from 'lodash-es'
|
||||
import providerApi from '@/api/api.providers'
|
||||
function useEdit (props, context, providerList, onEditSave) {
|
||||
function useEdit (props, context, onEditSave) {
|
||||
const formData = reactive({
|
||||
key: '',
|
||||
name: '',
|
||||
|
@ -155,6 +159,13 @@ function useEdit (props, context, providerList, onEditSave) {
|
|||
}
|
||||
}
|
||||
|
||||
const isDisabled = (item, keyName = 'type') => {
|
||||
if (!props.filter) {
|
||||
return false
|
||||
}
|
||||
return item[keyName
|
||||
] !== props.filter
|
||||
}
|
||||
return {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
|
@ -168,7 +179,8 @@ function useEdit (props, context, providerList, onEditSave) {
|
|||
editIndex,
|
||||
openEdit,
|
||||
onTypeChanged,
|
||||
add
|
||||
add,
|
||||
isDisabled
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,9 +204,9 @@ export default {
|
|||
name: 'provider-manager',
|
||||
props: {
|
||||
value: {},
|
||||
providers: {}
|
||||
filter: {}
|
||||
},
|
||||
emits: ['update:value', 'update:providers'],
|
||||
emits: ['update:value'],
|
||||
setup (props, context) {
|
||||
const visible = ref(false)
|
||||
|
||||
|
@ -205,47 +217,55 @@ export default {
|
|||
const onAfterVisibleChange = () => {
|
||||
|
||||
}
|
||||
const providerList = ref([])
|
||||
|
||||
const getProviders = inject('get:accessProviders')
|
||||
// const providerList = ref([])
|
||||
const selectedKey = ref(null)
|
||||
|
||||
watch(() => props.providers, () => {
|
||||
providerList.value = _.cloneDeep(props.providers || [])
|
||||
}, { immediate: true })
|
||||
watch(() => props.value, () => {
|
||||
selectedKey.value = props.value
|
||||
}, { immediate: true })
|
||||
|
||||
const onEditSave = (newProvider, editIndex) => {
|
||||
const providerList = getProviders()
|
||||
if (editIndex == null) {
|
||||
// add 生成一个key
|
||||
newProvider.key = generateNewKey(providerList.value)
|
||||
providerList.value.push(newProvider)
|
||||
newProvider.key = generateNewKey(providerList)
|
||||
providerList.push(newProvider)
|
||||
} else {
|
||||
_.merge(providerList.value[editIndex], newProvider)
|
||||
_.merge(providerList[editIndex], newProvider)
|
||||
}
|
||||
}
|
||||
|
||||
const editModule = useEdit(props, context, providerList, onEditSave)
|
||||
const editModule = useEdit(props, context, onEditSave)
|
||||
|
||||
const open = () => {
|
||||
visible.value = true
|
||||
if (providerList.value.length === 0) {
|
||||
const providerList = getProviders()
|
||||
if (providerList.length === 0) {
|
||||
nextTick(() => {
|
||||
editModule.add()
|
||||
})
|
||||
}
|
||||
}
|
||||
const remove = (item, index) => {
|
||||
providerList.value.splice(index, 1)
|
||||
const providerList = getProviders()
|
||||
providerList.splice(index, 1)
|
||||
}
|
||||
|
||||
const updateProviders = inject('update:accessProviders')
|
||||
|
||||
// watch(() => providers, () => {
|
||||
// providerList.value = _.cloneDeep(props.providers || [])
|
||||
// }, { immediate: true })
|
||||
|
||||
const onProviderSelectSubmit = () => {
|
||||
context.emit('update:providers', providerList.value)
|
||||
const providerList = getProviders()
|
||||
updateProviders(providerList)
|
||||
context.emit('update:value', selectedKey.value)
|
||||
close()
|
||||
}
|
||||
return {
|
||||
providerList,
|
||||
visible,
|
||||
open,
|
||||
close,
|
||||
|
@ -253,6 +273,7 @@ export default {
|
|||
remove,
|
||||
selectedKey,
|
||||
onProviderSelectSubmit,
|
||||
getProviders,
|
||||
...editModule
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
:value="value"
|
||||
@update:value="valueUpdate"
|
||||
>
|
||||
<a-select-option v-for="item of providers" :key="item.key" :value="item.key" :disabled="isDisabled(item)">
|
||||
<a-select-option v-for="item of getProviders()" :key="item.key" :value="item.key" :disabled="isDisabled(item)">
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
|
@ -13,15 +13,14 @@
|
|||
</a-button>
|
||||
</div>
|
||||
<provider-manager ref="providerManagerRef"
|
||||
:providers="providers"
|
||||
:value="value"
|
||||
:filter="filter"
|
||||
@update:value="valueUpdate"
|
||||
@update:providers="providersUpdate"
|
||||
></provider-manager>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import { ref } from 'vue'
|
||||
import { ref, inject } from 'vue'
|
||||
import ProviderManager from './provider-manager'
|
||||
|
||||
export default {
|
||||
|
@ -33,9 +32,6 @@ export default {
|
|||
value: {
|
||||
type: String
|
||||
},
|
||||
providers: {
|
||||
type: Object
|
||||
},
|
||||
filter: {}
|
||||
},
|
||||
setup (props, context) {
|
||||
|
@ -58,14 +54,18 @@ export default {
|
|||
if (!props.filter) {
|
||||
return false
|
||||
}
|
||||
return item.type === props.filter
|
||||
return item.type !== props.filter
|
||||
}
|
||||
|
||||
const getProviders = inject('get:accessProviders')
|
||||
|
||||
return {
|
||||
providersUpdate,
|
||||
valueUpdate,
|
||||
providerManagerOpen,
|
||||
providerManagerRef,
|
||||
isDisabled
|
||||
isDisabled,
|
||||
getProviders
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,25 @@ h1, h2, h3, h4, h5, h6 {
|
|||
height: 100%
|
||||
}
|
||||
|
||||
.ant-form{
|
||||
.ant-form-item-children {
|
||||
&>{
|
||||
min-height: 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-form-explain, .ant-form-extra{
|
||||
font-size:12px;
|
||||
line-height: 1.4;
|
||||
min-height: 20px;
|
||||
margin:0px;
|
||||
padding:0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ant-drawer-body{
|
||||
padding:0px;
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
v-model:value="formData.domains"
|
||||
:open="false"
|
||||
></a-select>
|
||||
<div class="helper">例如:*.yourdomain.com</div>
|
||||
<template #extra >
|
||||
例如:*.yourdomain.com,输入完成后回车,支持多个
|
||||
</template>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :label="$t('email')" v-bind="validateInfos.email">
|
||||
|
@ -27,10 +29,14 @@
|
|||
</a-form-item>
|
||||
|
||||
<a-form-item label="dns验证" v-bind="validateInfos.dnsProvider">
|
||||
<provider-selector v-model:value="formData.dnsProvider"
|
||||
:providers="accessProviders"
|
||||
@update:providers="accessProvidersUpdate"
|
||||
></provider-selector>
|
||||
<provider-selector v-model:value="formData.dnsProvider"></provider-selector>
|
||||
</a-form-item>
|
||||
<a-form-item label="CA" v-bind="validateInfos.ca">
|
||||
<a-radio-group v-model:value="formData.ca" >
|
||||
<a-radio value="LetEncrypt">
|
||||
LetEncrypt
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
|
||||
<h3>CSR <span>必须全英文</span></h3>
|
||||
|
@ -110,6 +116,7 @@ export default {
|
|||
domains: [],
|
||||
email: undefined,
|
||||
dnsProvider: '',
|
||||
ca: 'LetEncrypt',
|
||||
csr: {
|
||||
country: '',
|
||||
state: 'GuangDong',
|
||||
|
|
|
@ -31,16 +31,19 @@
|
|||
</a-button>
|
||||
</d-container>
|
||||
<d-container v-else class="d-container" >
|
||||
<a-form class="task-form" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-form-item label="任务名称">
|
||||
<a-form ref="taskFormRef" class="task-form" :model="currentTask" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-form-item label="任务名称" name="taskName" :rules="rules.name">
|
||||
<a-input
|
||||
placeholder="请输入任务名称"
|
||||
v-model:value="currentTask.taskName"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item v-for="(item,key) in currentPlugin.input" :key="key" :label="item.label">
|
||||
<a-form-item v-for="(item,key) in currentPlugin.input" v-bind="item.component || {}" :key="key" :label="item.label" :name="key">
|
||||
<component-render v-model:value="currentTask[key]" v-bind="item.component || {}"></component-render>
|
||||
<template #extra v-if="item.desc" >
|
||||
{{item.desc}}
|
||||
</template>
|
||||
</a-form-item>
|
||||
|
||||
</a-form>
|
||||
|
@ -78,13 +81,19 @@ function useTaskForm (context) {
|
|||
|
||||
onCreated()
|
||||
|
||||
const currentTask = ref()
|
||||
const currentTask = ref({ taskName: undefined })
|
||||
const currentTaskIndex = ref()
|
||||
const currentDeploy = ref()
|
||||
const currentPlugin = ref(null)
|
||||
const taskFormRef = ref(null)
|
||||
const taskDrawerVisible = ref(false)
|
||||
|
||||
const rules = ref({
|
||||
name: [{
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: '请输入名称'
|
||||
}]
|
||||
})
|
||||
const taskAdd = (deploy) => {
|
||||
const task = { taskName: '新任务', type: undefined, _isAdd: true }
|
||||
currentDeploy.value = deploy
|
||||
|
@ -142,8 +151,11 @@ function useTaskForm (context) {
|
|||
currentPlugin.value = currentPlugins[0]
|
||||
}
|
||||
|
||||
const taskSave = () => {
|
||||
const taskSave = async (e) => {
|
||||
console.log('currentTask', currentTask)
|
||||
|
||||
e.preventDefault()
|
||||
await taskFormRef.value.validate()
|
||||
// context.emit('update', currentTask.value)
|
||||
taskDrawerClose()
|
||||
}
|
||||
|
@ -161,7 +173,8 @@ function useTaskForm (context) {
|
|||
currentTask,
|
||||
currentTaskIndex,
|
||||
currentPlugin,
|
||||
taskSave
|
||||
taskSave,
|
||||
rules
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,38 +37,47 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="title">CSR
|
||||
<span>必须全英文</span></div>
|
||||
<br/>
|
||||
<div class="title">
|
||||
CSR
|
||||
<span>必须全英文</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<label>country:</label>
|
||||
<label>国家:</label>
|
||||
<div>
|
||||
{{ options.cert.csr.country }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<label>state:</label>
|
||||
<label>省份:</label>
|
||||
<div>
|
||||
{{ options.cert.csr.state }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<label>locality:</label>
|
||||
<label>市区:</label>
|
||||
<div>
|
||||
{{ options.cert.csr.locality }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<label>org:</label>
|
||||
<label>组织:</label>
|
||||
<div>
|
||||
{{ options.cert.csr.organization }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<label>orgUnit:</label>
|
||||
<label>部门:</label>
|
||||
<div>
|
||||
{{ options.cert.csr.organizationUnit }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<label>邮箱:</label>
|
||||
<div>
|
||||
{{ options.cert.csr.emailAddress }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -136,7 +145,7 @@
|
|||
<script>
|
||||
import { message } from 'ant-design-vue'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { reactive, ref, toRef } from 'vue'
|
||||
import { reactive, ref, toRef, provide, readonly } from 'vue'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { useRoute } from 'vue-router'
|
||||
import CertForm from '@/views/detail/components/cert-form'
|
||||
|
@ -169,6 +178,15 @@ function useDeploy (options) {
|
|||
}
|
||||
}
|
||||
|
||||
function useProvideAccessProviders (options) {
|
||||
provide('get:accessProviders', () => {
|
||||
return options.accessProviders
|
||||
})
|
||||
provide('update:accessProviders', (providers) => {
|
||||
options.accessProviders = providers
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
components: { CertForm, TaskForm },
|
||||
setup () {
|
||||
|
@ -189,6 +207,7 @@ export default {
|
|||
deploy: []
|
||||
}
|
||||
_.merge(optionsDefault, optionParams)
|
||||
// optionsDefault.accessProviders = reactive(optionsDefault.accessProviders)
|
||||
const options = reactive(optionsDefault)
|
||||
|
||||
const certFormChanged = (value) => {
|
||||
|
@ -209,6 +228,8 @@ export default {
|
|||
taskFormRef.value.taskEdit(deploy, task, index)
|
||||
}
|
||||
|
||||
useProvideAccessProviders(options)
|
||||
|
||||
return {
|
||||
options,
|
||||
certFormChanged,
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.test.js", "*.spec.js"],
|
||||
|
|
|
@ -8,23 +8,31 @@ const define = {
|
|||
input: {
|
||||
domainName: {
|
||||
label: 'cdn加速域名',
|
||||
required: true,
|
||||
attrs: {
|
||||
component: {
|
||||
placeholder: 'cdn加速域名',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
},
|
||||
certName: {
|
||||
label: '证书名称'
|
||||
label: '证书名称',
|
||||
component: {
|
||||
placeholder: '上传后将以此名称作为前缀'
|
||||
}
|
||||
},
|
||||
from: {
|
||||
value: 'upload',
|
||||
label: '证书来源',
|
||||
options: [
|
||||
{ value: 'upload', label: '直接上传' },
|
||||
{ value: 'cas', label: '从证书库', desc: '需要uploadCertToAliyun作为前置任务' }
|
||||
],
|
||||
required: true
|
||||
component: {
|
||||
placeholder: '证书来源',
|
||||
required: true,
|
||||
name: 'a-select',
|
||||
options: [
|
||||
{ value: 'upload', label: '直接上传' },
|
||||
{ value: 'cas', label: '从证书库', title: '需要uploadCertToAliyun作为前置任务' }
|
||||
]
|
||||
},
|
||||
desc: '如果选择cas类型,则需要以《上传证书到阿里云》作为前置任务'
|
||||
|
||||
},
|
||||
// serverCertificateStatus: {
|
||||
// label: '启用https',
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.test.js", "*.spec.js"],
|
||||
|
|
|
@ -10,7 +10,7 @@ export class AliyunDnsProvider extends AbstractDnsProvider {
|
|||
input: {
|
||||
accessKeyId: {
|
||||
type: String,
|
||||
attrs: {
|
||||
component: {
|
||||
placeholder: 'accessKeyId',
|
||||
rules: [{ required: true, message: '必填项' }]
|
||||
},
|
||||
|
@ -18,7 +18,7 @@ export class AliyunDnsProvider extends AbstractDnsProvider {
|
|||
},
|
||||
accessKeySecret: {
|
||||
type: String,
|
||||
attrs: {
|
||||
component: {
|
||||
placeholder: 'accessKeySecret',
|
||||
rules: [{ required: true, message: '必填项' }]
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@ export class DnspodDnsProvider extends AbstractDnsProvider {
|
|||
static define () {
|
||||
return {
|
||||
name: 'dnspod',
|
||||
label: 'dnspod',
|
||||
label: 'dnspod(腾讯云)',
|
||||
desc: '腾讯云的域名解析接口已迁移到dnspod',
|
||||
input: {
|
||||
id: {
|
||||
type: String,
|
||||
attrs: {
|
||||
component: {
|
||||
placeholder: 'dnspod接口账户id',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ export class DnspodDnsProvider extends AbstractDnsProvider {
|
|||
token: {
|
||||
type: String,
|
||||
label: 'token',
|
||||
attrs: {
|
||||
component: {
|
||||
placeholder: '开放接口token',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue