feat: IAgree

This commit is contained in:
kailong321200875 2024-02-29 15:05:05 +08:00
parent ab25622b66
commit abb69064df
13 changed files with 200 additions and 12 deletions

View File

@ -332,6 +332,14 @@ const adminList = [
meta: { meta: {
title: 'router.avatars' title: 'router.avatars'
} }
},
{
path: 'i-agree',
component: 'views/Components/IAgree',
name: 'IAgree',
meta: {
title: 'router.iAgree'
}
} }
] ]
}, },
@ -695,6 +703,7 @@ const testList: string[] = [
'/components/image-cropping', '/components/image-cropping',
'/components/video-player', '/components/video-player',
'/components/avatars', '/components/avatars',
'/components/i-agree',
'function', 'function',
'/function/multiple-tabs', '/function/multiple-tabs',
'/function/multiple-tabs-demo/:id', '/function/multiple-tabs-demo/:id',

View File

@ -24,6 +24,7 @@ import { InputPassword } from '@/components/InputPassword'
import { Editor } from '@/components/Editor' import { Editor } from '@/components/Editor'
import { JsonEditor } from '@/components/JsonEditor' import { JsonEditor } from '@/components/JsonEditor'
import { IconPicker } from '@/components/IconPicker' import { IconPicker } from '@/components/IconPicker'
import { IAgree } from '@/components/IAgree'
import { ComponentName } from '../types' import { ComponentName } from '../types'
const componentMap: Recordable<Component, ComponentName> = { const componentMap: Recordable<Component, ComponentName> = {
@ -51,7 +52,8 @@ const componentMap: Recordable<Component, ComponentName> = {
TreeSelect: ElTreeSelect, TreeSelect: ElTreeSelect,
Upload: ElUpload, Upload: ElUpload,
JsonEditor: JsonEditor, JsonEditor: JsonEditor,
IconPicker: IconPicker IconPicker: IconPicker,
IAgree: IAgree
} }
export { componentMap } export { componentMap }

View File

@ -22,6 +22,7 @@ import {
} from 'element-plus' } from 'element-plus'
import { IEditorConfig } from '@wangeditor/editor' import { IEditorConfig } from '@wangeditor/editor'
import { JsonEditorProps } from '@/components/JsonEditor' import { JsonEditorProps } from '@/components/JsonEditor'
import { IAgreeProps } from '@/components/IAgree'
import { CSSProperties } from 'vue' import { CSSProperties } from 'vue'
export interface PlaceholderModel { export interface PlaceholderModel {
@ -56,7 +57,8 @@ export enum ComponentNameEnum {
TREE_SELECT = 'TreeSelect', TREE_SELECT = 'TreeSelect',
UPLOAD = 'Upload', UPLOAD = 'Upload',
JSON_EDITOR = 'JsonEditor', JSON_EDITOR = 'JsonEditor',
ICON_PICKER = 'IconPicker' ICON_PICKER = 'IconPicker',
I_AGREE = 'IAgree'
} }
type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K
@ -624,6 +626,7 @@ export interface FormSchema {
| TreeSelectComponentProps | TreeSelectComponentProps
| UploadComponentProps | UploadComponentProps
| JsonEditorProps | JsonEditorProps
| IAgreeProps
| any | any
/** /**

View File

@ -0,0 +1,4 @@
import IAgree from './src/IAgree.vue'
export type { LinkItem, IAgreeProps } from './src/types'
export { IAgree }

View File

@ -0,0 +1,41 @@
<script lang="ts" setup>
import { ElCheckbox } from 'element-plus'
import { Highlight } from '@/components/Highlight'
import { PropType, computed } from 'vue'
import { LinkItem } from './types'
const props = defineProps({
text: {
type: String,
default: ''
},
link: {
type: Array as PropType<LinkItem[]>,
default: undefined
}
})
const modelValue = defineModel<boolean>()
const highlightKeys = computed(() => {
return props.link?.map((item) => item.text) || []
})
const keyClick = (key: string) => {
const linkItem = props.link?.find((item) => item.text === key)
if (linkItem?.url) {
window.open(linkItem.url)
return
}
if (linkItem?.onClick) {
linkItem.onClick()
}
}
</script>
<template>
<div class="flex items-center">
<ElCheckbox v-model="modelValue" class="mr-0px!" />
<Highlight class="ml-10px" :keys="highlightKeys" @click="keyClick">{{ text }}</Highlight>
</div>
</template>

View File

@ -0,0 +1,10 @@
export interface LinkItem {
text: string
url?: string
onClick?: () => void
}
export interface IAgreeProps {
text: string
link: LinkItem[]
}

View File

@ -84,6 +84,18 @@ export const useValidator = () => {
} }
} }
const check = (message?: string): FormItemRule => {
return {
validator: (_, val, callback) => {
if (!val) {
callback(new Error(message || t('common.required')))
} else {
callback()
}
}
}
}
return { return {
required, required,
lengthRange, lengthRange,
@ -91,6 +103,7 @@ export const useValidator = () => {
notSpecialCharacters, notSpecialCharacters,
phone, phone,
email, email,
maxlength maxlength,
check
} }
} }

View File

@ -121,7 +121,8 @@ export default {
usernamePlaceholder: 'Please input username', usernamePlaceholder: 'Please input username',
passwordPlaceholder: 'Please input password', passwordPlaceholder: 'Please input password',
code: 'Verification code', code: 'Verification code',
codePlaceholder: 'Please input verification code' codePlaceholder: 'Please input verification code',
getCode: 'Get code'
}, },
router: { router: {
login: 'Login', login: 'Login',
@ -187,7 +188,8 @@ export default {
cardTable: 'Card table', cardTable: 'Card table',
personalCenter: 'Personal center', personalCenter: 'Personal center',
personal: 'Personal', personal: 'Personal',
avatars: 'Avatars' avatars: 'Avatars',
iAgree: 'I agree'
}, },
permission: { permission: {
hasPermission: 'Please set the operation permission value' hasPermission: 'Please set the operation permission value'
@ -334,7 +336,8 @@ export default {
upload: 'Upload', upload: 'Upload',
// 用户头像 // 用户头像
userAvatar: 'User avatar', userAvatar: 'User avatar',
iconPicker: 'Icon picker' iconPicker: 'Icon picker',
iAgree: 'I agree'
}, },
guideDemo: { guideDemo: {
guide: 'Guide', guide: 'Guide',

View File

@ -119,7 +119,8 @@ export default {
usernamePlaceholder: '请输入用户名', usernamePlaceholder: '请输入用户名',
passwordPlaceholder: '请输入密码', passwordPlaceholder: '请输入密码',
code: '验证码', code: '验证码',
codePlaceholder: '请输入验证码' codePlaceholder: '请输入验证码',
getCode: '获取验证码'
}, },
router: { router: {
login: '登录', login: '登录',
@ -183,7 +184,8 @@ export default {
cardTable: '卡片表格', cardTable: '卡片表格',
personalCenter: '个人中心', personalCenter: '个人中心',
personal: '个人', personal: '个人',
avatars: '头像列表' avatars: '头像列表',
iAgree: '我同意'
}, },
permission: { permission: {
hasPermission: '请设置操作权限值' hasPermission: '请设置操作权限值'
@ -327,7 +329,8 @@ export default {
lazyLoad: '懒加载', lazyLoad: '懒加载',
upload: '上传', upload: '上传',
userAvatar: '用户头像', userAvatar: '用户头像',
iconPicker: '图标选择器' iconPicker: '图标选择器',
iAgree: '我同意'
}, },
guideDemo: { guideDemo: {
guide: '引导页', guide: '引导页',

View File

@ -398,6 +398,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
meta: { meta: {
title: t('router.avatars') title: t('router.avatars')
} }
},
{
path: 'i-agree',
component: () => import('@/views/Components/IAgree.vue'),
name: 'IAgree',
meta: {
title: t('router.iAgree')
}
} }
] ]
}, },

View File

@ -1785,6 +1785,25 @@ const schema = reactive<FormSchema[]>([
component: 'IconPicker', component: 'IconPicker',
label: t('formDemo.default'), label: t('formDemo.default'),
value: 'tdesign:archway' value: 'tdesign:archway'
},
{
field: 'field89',
component: 'Divider',
label: t('formDemo.iAgree')
},
{
field: 'field90',
component: 'IAgree',
label: t('formDemo.default'),
componentProps: {
text: '我同意《用户协议》',
link: [
{
text: '《用户协议》',
url: 'https://element-plus.org/'
}
]
}
} }
]) ])
</script> </script>

View File

@ -0,0 +1,21 @@
<script setup lang="ts">
import { ContentWrap } from '@/components/ContentWrap'
import { useI18n } from '@/hooks/web/useI18n'
import { IAgree } from '@/components/IAgree'
const { t } = useI18n()
</script>
<template>
<ContentWrap :title="t('router.iAgree')">
<IAgree
:link="[
{
text: '《隐私政策》',
url: 'https://www.baidu.com'
}
]"
text="我同意《隐私政策》"
/>
</ContentWrap>
</template>

View File

@ -1,11 +1,12 @@
<script setup lang="tsx"> <script setup lang="tsx">
import { Form, FormSchema } from '@/components/Form' import { Form, FormSchema } from '@/components/Form'
import { reactive, ref } from 'vue' import { reactive, ref, unref } from 'vue'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { useForm } from '@/hooks/web/useForm' import { useForm } from '@/hooks/web/useForm'
import { ElInput, FormRules } from 'element-plus' import { ElInput, FormRules } from 'element-plus'
import { useValidator } from '@/hooks/web/useValidator' import { useValidator } from '@/hooks/web/useValidator'
import { BaseButton } from '@/components/Button' import { BaseButton } from '@/components/Button'
import { IAgree } from '@/components/IAgree'
const emit = defineEmits(['to-login']) const emit = defineEmits(['to-login'])
@ -14,7 +15,21 @@ const { getElFormExpose } = formMethods
const { t } = useI18n() const { t } = useI18n()
const { required } = useValidator() const { required, check } = useValidator()
const getCodeTime = ref(60)
const getCodeLoading = ref(false)
const getCode = () => {
getCodeLoading.value = true
const timer = setInterval(() => {
getCodeTime.value--
if (getCodeTime.value <= 0) {
clearInterval(timer)
getCodeTime.value = 60
getCodeLoading.value = false
}
}, 1000)
}
const schema = reactive<FormSchema[]>([ const schema = reactive<FormSchema[]>([
{ {
@ -86,12 +101,48 @@ const schema = reactive<FormSchema[]>([
return ( return (
<div class="w-[100%] flex"> <div class="w-[100%] flex">
<ElInput v-model={formData.code} placeholder={t('login.codePlaceholder')} /> <ElInput v-model={formData.code} placeholder={t('login.codePlaceholder')} />
<BaseButton
type="primary"
disabled={unref(getCodeLoading)}
class="ml-10px"
onClick={getCode}
>
{t('login.getCode')}
{unref(getCodeLoading) ? `(${unref(getCodeTime)})` : ''}
</BaseButton>
</div> </div>
) )
} }
} }
} }
}, },
{
field: 'iAgree',
colProps: {
span: 24
},
formItemProps: {
slots: {
default: (formData: any) => {
return (
<>
<IAgree
v-model={formData.iAgree}
text="我同意《用户协议》"
link={[
{
text: '《用户协议》',
url: 'https://element-plus.org/'
}
]}
/>
</>
)
}
}
}
},
{ {
field: 'register', field: 'register',
colProps: { colProps: {
@ -129,7 +180,8 @@ const rules: FormRules = {
username: [required()], username: [required()],
password: [required()], password: [required()],
check_password: [required()], check_password: [required()],
code: [required()] code: [required()],
iAgree: [required(), check()]
} }
const toLogin = () => { const toLogin = () => {