forked from opentiny/tiny-vue
feat(form): [form] add xDesign theme (#1507)
This commit is contained in:
parent
68abf0beea
commit
f844712a66
|
@ -385,6 +385,17 @@ export default {
|
|||
mode: ['pc'],
|
||||
pcDemo: ''
|
||||
},
|
||||
{
|
||||
name: 'extra',
|
||||
type: 'string',
|
||||
defaultValue: '',
|
||||
desc: {
|
||||
'zh-CN': '表单项额外提示',
|
||||
'en-US': 'Form item extra tip'
|
||||
},
|
||||
mode: ['pc'],
|
||||
pcDemo: 'extra-tip'
|
||||
},
|
||||
{
|
||||
name: 'inline-message',
|
||||
type: 'boolean',
|
||||
|
@ -581,6 +592,16 @@ export default {
|
|||
},
|
||||
mode: ['pc'],
|
||||
pcDemo: 'slot-label'
|
||||
},
|
||||
{
|
||||
name: 'error',
|
||||
defaultValue: '',
|
||||
desc: {
|
||||
'zh-CN': '错误提示内容',
|
||||
'en-US': 'Error content'
|
||||
},
|
||||
mode: ['pc'],
|
||||
pcDemo: 'error-label'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
<div class="demo-form">
|
||||
<tiny-form ref="ruleFormRef" :model="createData" :rules="rules">
|
||||
<tiny-form-item label="姓名" prop="name">
|
||||
<tiny-input v-model="createData.name"></tiny-input>
|
||||
</tiny-form-item>
|
||||
<tiny-form-item label="年龄" prop="age">
|
||||
<tiny-input v-model="createData.age"></tiny-input>
|
||||
<template #error>
|
||||
<span>错误提示内容插槽</span>
|
||||
</template>
|
||||
</tiny-form-item>
|
||||
<tiny-form-item label="昵称" prop="nickname" validate-type="text">
|
||||
<tiny-input v-model="createData.nickname"></tiny-input>
|
||||
<template #error="message">
|
||||
<span class="error-slot">{{ message }}</span>
|
||||
</template>
|
||||
</tiny-form-item>
|
||||
<tiny-form-item>
|
||||
<tiny-button type="primary" @click="validateField"> 校验 </tiny-button>
|
||||
</tiny-form-item>
|
||||
</tiny-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Form as TinyForm, FormItem as TinyFormItem, Input as TinyInput, Button as TinyButton } from '@opentiny/vue'
|
||||
|
||||
const createData = ref({
|
||||
name: '',
|
||||
age: '',
|
||||
nickname: ''
|
||||
})
|
||||
|
||||
const rules = ref({
|
||||
name: [
|
||||
{ required: true, message: '必填', trigger: 'blur' },
|
||||
{ min: 2, max: 11, message: '长度必须不小于2', trigger: ['change', 'blur'] }
|
||||
],
|
||||
age: { required: true },
|
||||
nickname: [
|
||||
{ required: true, message: '昵称必填' },
|
||||
{ min: 2, max: 11, message: '昵称长度必须不小于2切不大于11', trigger: ['change', 'blur'] }
|
||||
]
|
||||
})
|
||||
|
||||
const ruleFormRef = ref()
|
||||
|
||||
function validateField() {
|
||||
ruleFormRef.value.validate(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.demo-form {
|
||||
width: 380px;
|
||||
}
|
||||
.error-slot {
|
||||
color: #ffd0a6;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,15 @@
|
|||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test('错误提示插槽', async ({ page }) => {
|
||||
page.on('pageerror', (exception) => expect(exception).toBeNull())
|
||||
await page.goto('form#error-slot')
|
||||
|
||||
const demo = page.locator('#error-slot')
|
||||
const getTooltipByText = (text: string) => page.locator('.tiny-tooltip').getByText(text)
|
||||
const validBtn = demo.getByRole('button', { name: '校验' }).first()
|
||||
|
||||
await validBtn.click()
|
||||
await expect(getTooltipByText('必填')).toBeVisible()
|
||||
await expect(getTooltipByText('错误提示内容插槽')).toBeVisible()
|
||||
await expect(page.locator('.error-slot')).toBeVisible()
|
||||
})
|
|
@ -0,0 +1,71 @@
|
|||
<template>
|
||||
<div class="demo-form">
|
||||
<tiny-form ref="ruleFormRef" :model="createData" :rules="rules">
|
||||
<tiny-form-item label="姓名" prop="name">
|
||||
<tiny-input v-model="createData.name"></tiny-input>
|
||||
</tiny-form-item>
|
||||
<tiny-form-item label="年龄" prop="age">
|
||||
<tiny-input v-model="createData.age"></tiny-input>
|
||||
<template #error>
|
||||
<span>错误提示内容插槽</span>
|
||||
</template>
|
||||
</tiny-form-item>
|
||||
<tiny-form-item label="昵称" prop="nickname" validate-type="text">
|
||||
<tiny-input v-model="createData.nickname"></tiny-input>
|
||||
<template #error="message">
|
||||
<span class="error-slot">{{ message }}</span>
|
||||
</template>
|
||||
</tiny-form-item>
|
||||
<tiny-form-item>
|
||||
<tiny-button type="primary" @click="validateField"> 校验 </tiny-button>
|
||||
</tiny-form-item>
|
||||
</tiny-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Form, FormItem, Input, Button } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyForm: Form,
|
||||
TinyFormItem: FormItem,
|
||||
TinyInput: Input,
|
||||
TinyButton: Button
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
createData: {
|
||||
name: '',
|
||||
age: '',
|
||||
nickname: ''
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: '必填', trigger: 'blur' },
|
||||
{ min: 2, max: 11, message: '长度必须不小于2', trigger: ['change', 'blur'] }
|
||||
],
|
||||
age: { required: true },
|
||||
nickname: [
|
||||
{ required: true, message: '昵称必填' },
|
||||
{ min: 2, max: 11, message: '昵称长度必须不小于2切不大于11', trigger: ['change', 'blur'] }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
validateField() {
|
||||
this.$refs.ruleFormRef.validate(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.demo-form {
|
||||
width: 380px;
|
||||
}
|
||||
.error-slot {
|
||||
color: #ffd0a6;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,48 @@
|
|||
<template>
|
||||
<div class="demo-form">
|
||||
<tiny-form ref="ruleFormRef" :model="createData" :rules="rules" validate-type="text">
|
||||
<tiny-form-item label="姓名" prop="name" extra="需要填写真实姓名">
|
||||
<tiny-input v-model="createData.name"></tiny-input>
|
||||
</tiny-form-item>
|
||||
<tiny-form-item label="年龄" prop="age" extra="需要填写真实年龄">
|
||||
<tiny-input v-model="createData.age"></tiny-input>
|
||||
</tiny-form-item>
|
||||
<tiny-form-item>
|
||||
<tiny-button type="primary" @click="submit"> 提交 </tiny-button>
|
||||
</tiny-form-item>
|
||||
</tiny-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Form as TinyForm, FormItem as TinyFormItem, Input as TinyInput, Button as TinyButton } from '@opentiny/vue'
|
||||
|
||||
const createData = ref({
|
||||
name: '',
|
||||
age: ''
|
||||
})
|
||||
|
||||
const rules = ref({
|
||||
name: [
|
||||
{ required: true, message: '必填' },
|
||||
{ min: 2, max: 11, message: '长度必须不小于2' }
|
||||
],
|
||||
age: { required: true }
|
||||
})
|
||||
|
||||
const ruleFormRef = ref()
|
||||
|
||||
function submit() {
|
||||
ruleFormRef.value.validate(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.demo-form {
|
||||
width: 380px;
|
||||
}
|
||||
.error-slot {
|
||||
color: #ffd0a6;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,15 @@
|
|||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test('错误提示插槽', async ({ page }) => {
|
||||
page.on('pageerror', (exception) => expect(exception).toBeNull())
|
||||
await page.goto('form#extra-tip')
|
||||
|
||||
const demo = page.locator('#extra-tip')
|
||||
const validBtn = demo.getByRole('button', { name: '提交' }).first()
|
||||
|
||||
await expect(demo.getByText('需要填写真实姓名')).toBeVisible()
|
||||
await expect(demo.getByText('需要填写真实年龄')).toBeVisible()
|
||||
await validBtn.click()
|
||||
await expect(demo.getByText('需要填写真实姓名')).toBeVisible()
|
||||
await expect(demo.getByText('需要填写真实年龄')).toBeVisible()
|
||||
})
|
|
@ -0,0 +1,57 @@
|
|||
<template>
|
||||
<div class="demo-form">
|
||||
<tiny-form ref="ruleFormRef" :model="createData" :rules="rules" validate-type="text">
|
||||
<tiny-form-item label="姓名" prop="name" extra="需要填写真实姓名">
|
||||
<tiny-input v-model="createData.name"></tiny-input>
|
||||
</tiny-form-item>
|
||||
<tiny-form-item label="年龄" prop="age" extra="需要填写真实年龄">
|
||||
<tiny-input v-model="createData.age"></tiny-input>
|
||||
</tiny-form-item>
|
||||
<tiny-form-item>
|
||||
<tiny-button type="primary" @click="submit"> 提交 </tiny-button>
|
||||
</tiny-form-item>
|
||||
</tiny-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Form, FormItem, Input, Button } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyForm: Form,
|
||||
TinyFormItem: FormItem,
|
||||
TinyInput: Input,
|
||||
TinyButton: Button
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
createData: {
|
||||
name: '',
|
||||
age: ''
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: '必填' },
|
||||
{ min: 2, max: 11, message: '长度必须不小于2' }
|
||||
],
|
||||
age: { required: true }
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
this.$refs.ruleFormRef.validate(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.demo-form {
|
||||
width: 380px;
|
||||
}
|
||||
.error-slot {
|
||||
color: #ffd0a6;
|
||||
}
|
||||
</style>
|
|
@ -78,10 +78,16 @@ export default {
|
|||
'en-US': 'Form Validation/Clear Validation'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN':
|
||||
'<p>通过 <code>rules</code> 设置校验规则,\n 调用 <code>clearValidate</code> 方法移除表单项的校验结果。传入待移除的表单项的 <code>prop</code> 属性或者 <code>prop</code> 组成的数组,如不传则移除整个表单的校验结果,\n 调用 <code>resetFields</code> 方法重置表单并移除校验结果。\n </p>',
|
||||
'en-US':
|
||||
'<p>Includes common verification rules such as mandatory fields, date, time, URL, and email. Use <code>trigger</code> to configure the mode of triggering the validation rule. If <code>change</code> is used, the validation is triggered when the value in the text box changes. If <code>blur</code> is used, the validation is triggered after the focus is lost. \n <br />\n Use <code>clearValidate</code> method to clear the validation result. \n </p>\n '
|
||||
'zh-CN': `<p>通过 <code>rules</code> 设置校验规则,
|
||||
调用 <code>clearValidate</code> 方法移除表单项的校验结果。传入待移除的表单项的 <code>prop</code> 属性或者 <code>prop</code> 组成的数组,如不传则移除整个表单的校验结果,
|
||||
调用 <code>resetFields</code> 方法重置表单并移除校验结果
|
||||
</p>`,
|
||||
'en-US': `<p>Includes common verification rules such as mandatory fields, date, time, URL, and email.
|
||||
Use <code>trigger</code> to configure the mode of triggering the validation rule.
|
||||
If <code>change</code> is used, the validation is triggered when the value in the text box changes.
|
||||
If <code>blur</code> is used, the validation is triggered after the focus is lost.
|
||||
<br />
|
||||
Use <code>clearValidate</code> method to clear the validation result.</p>`
|
||||
},
|
||||
codeFiles: ['form-validation.vue']
|
||||
},
|
||||
|
@ -284,6 +290,30 @@ export default {
|
|||
},
|
||||
codeFiles: ['popper-options.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'error-slot',
|
||||
name: {
|
||||
'zh-CN': '错误提示插槽',
|
||||
'en-US': 'Error content'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '<p>通过 <code>error</code> 插槽,自定义标签文本的内容。</p>',
|
||||
'en-US': '<p>Use the <code>error</code> slot to customize the content of the label text. </p>'
|
||||
},
|
||||
codeFiles: ['error-slot.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'extra-tip',
|
||||
name: {
|
||||
'zh-CN': '额外提示信息',
|
||||
'en-US': 'Extra tip'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '<p>通过 <code>extra</code> 配置额外提示信息。</p>',
|
||||
'en-US': '<p>Configure additional prompt information through <code>extra</code>. </p>'
|
||||
},
|
||||
codeFiles: ['extra-tip.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'events',
|
||||
name: {
|
||||
|
|
|
@ -64,7 +64,8 @@ const changeTheme = (themeKey) => {
|
|||
router.push({
|
||||
params: {
|
||||
theme: THEME_ROUTE_MAP[themeKey]
|
||||
}
|
||||
},
|
||||
hash: router?.currentRoute.value.hash
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,13 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.@{form-item-prefix-cls}__extra-tip {
|
||||
line-height: var(--ti-form-item-extra-tip-line-height);
|
||||
margin-top: var(--ti-form-item-extra-tip-margin-top);
|
||||
color: var(--ti-form-item-extra-tip-font-color);
|
||||
font-size: var(--ti-form-item-extra-tip-font-size);
|
||||
}
|
||||
|
||||
& & {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
|
|
@ -55,4 +55,12 @@
|
|||
--ti-form-item-error-inline-margin-left: calc(var(--ti-common-space-base, 4px) * 2.5);
|
||||
// 表单校验块级错误消息上侧内边距
|
||||
--ti-form-item-error-block-padding-top: var(--ti-common-space-2x, 8px);
|
||||
// 表单额外提示信息上侧外边距
|
||||
--ti-form-item-extra-tip-margin-top: var(--ti-common-space-2x, 8px);
|
||||
// 表单额外提示信息字体颜色
|
||||
--ti-form-item-extra-tip-font-color: var(--ti-common-color-text-weaken, #8a8e99);
|
||||
// 表单额外提示信息字体大小
|
||||
--ti-form-item-extra-tip-font-size: var(--ti-common-font-size-1, 14px);
|
||||
// 表单额外提示信息字体行高
|
||||
--ti-form-item-extra-tip-line-height: var(--ti-common-line-height-number, 1.5);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,8 @@ export const formItemProps = {
|
|||
vertical: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
extra: String
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
|
|
|
@ -79,7 +79,8 @@ export default defineComponent({
|
|||
vertical: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
extra: String
|
||||
},
|
||||
setup(props, context) {
|
||||
return setup({ props, context, renderless, api }) as unknown as IFormItemApi
|
||||
|
@ -221,11 +222,18 @@ export default defineComponent({
|
|||
modelValue: isShowError ? state.canShowTip : false,
|
||||
zIndex: 'relative',
|
||||
renderContent() {
|
||||
return [
|
||||
let tooltipContent
|
||||
if (errorSlot) {
|
||||
tooltipContent = [errorSlot]
|
||||
} else {
|
||||
tooltipContent = [
|
||||
validateIconNode,
|
||||
<span class={`${classPrefix}form-item__validate-message`}>{state.validateMessage}</span>
|
||||
]
|
||||
}
|
||||
|
||||
return tooltipContent
|
||||
}
|
||||
},
|
||||
on: {
|
||||
'update:modelValue': (value) => {
|
||||
|
@ -298,6 +306,19 @@ export default defineComponent({
|
|||
: null
|
||||
]
|
||||
)
|
||||
|
||||
const ExtraTip = this.extra
|
||||
? h(
|
||||
'div',
|
||||
{
|
||||
class: {
|
||||
[`${classPrefix}form-item__extra-tip`]: true
|
||||
}
|
||||
},
|
||||
this.extra
|
||||
)
|
||||
: null
|
||||
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
|
@ -336,7 +357,8 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
[ErrorContent]
|
||||
)
|
||||
),
|
||||
isMobile ? null : ExtraTip
|
||||
]
|
||||
)
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue