Browse Source

feat: IAgree

kailong321200875 1 year ago
parent
commit
abb69064df

+ 9 - 0
mock/role/index.mock.ts

@@ -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',

+ 3 - 1
src/components/Form/src/helper/componentMap.ts

@@ -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 }

+ 4 - 1
src/components/Form/src/types/index.ts

@@ -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
 
 
   /**
   /**

+ 4 - 0
src/components/IAgree/index.ts

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

+ 41 - 0
src/components/IAgree/src/IAgree.vue

@@ -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>

+ 10 - 0
src/components/IAgree/src/types/index.ts

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

+ 14 - 1
src/hooks/web/useValidator.ts

@@ -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
   }
   }
 }
 }

+ 6 - 3
src/locales/en.ts

@@ -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',

+ 6 - 3
src/locales/zh-CN.ts

@@ -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: '引导页',

+ 8 - 0
src/router/index.ts

@@ -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')
+        }
       }
       }
     ]
     ]
   },
   },

+ 19 - 0
src/views/Components/Form/DefaultForm.vue

@@ -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>

+ 21 - 0
src/views/Components/IAgree.vue

@@ -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>

+ 55 - 3
src/views/Login/components/RegisterForm.vue

@@ -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 = () => {