wip(Login): Login developing
This commit is contained in:
parent
3810b8c3b2
commit
4d52f7bf58
|
@ -48,6 +48,7 @@
|
|||
"@typescript-eslint/parser": "^5.8.1",
|
||||
"@vitejs/plugin-vue": "^2.0.1",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.3",
|
||||
"@windicss/plugin-animations": "^1.0.9",
|
||||
"async-validator": "^4.0.7",
|
||||
"autoprefixer": "^10.4.1",
|
||||
"commitizen": "^4.2.4",
|
||||
|
|
|
@ -14,6 +14,7 @@ specifiers:
|
|||
'@vitejs/plugin-vue': ^2.0.1
|
||||
'@vitejs/plugin-vue-jsx': ^1.3.3
|
||||
'@vueuse/core': ^7.5.1
|
||||
'@windicss/plugin-animations': ^1.0.9
|
||||
'@zxcvbn-ts/core': ^1.2.0
|
||||
async-validator: ^4.0.7
|
||||
autoprefixer: ^10.4.1
|
||||
|
@ -79,6 +80,7 @@ devDependencies:
|
|||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser/5.8.1_eslint@8.6.0+typescript@4.5.4
|
||||
'@vitejs/plugin-vue': registry.npmmirror.com/@vitejs/plugin-vue/2.0.1_vite@2.7.10+vue@3.2.26
|
||||
'@vitejs/plugin-vue-jsx': registry.npmmirror.com/@vitejs/plugin-vue-jsx/1.3.3
|
||||
'@windicss/plugin-animations': registry.npmmirror.com/@windicss/plugin-animations/1.0.9
|
||||
async-validator: registry.npmmirror.com/async-validator/4.0.7
|
||||
autoprefixer: registry.npmmirror.com/autoprefixer/10.4.1_postcss@8.4.5
|
||||
commitizen: registry.npmmirror.com/commitizen/4.2.4_@types+node@17.0.5
|
||||
|
@ -5210,7 +5212,7 @@ packages:
|
|||
{
|
||||
integrity: sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=,
|
||||
registry: https://registry.npm.taobao.org/,
|
||||
tarball: https://registry.nlark.com/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1631500167672&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz
|
||||
tarball: https://registry.nlark.com/semver/download/semver-5.7.1.tgz
|
||||
}
|
||||
name: semver
|
||||
version: 5.7.1
|
||||
|
@ -5222,7 +5224,7 @@ packages:
|
|||
{
|
||||
integrity: sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=,
|
||||
registry: https://registry.npm.taobao.org/,
|
||||
tarball: https://registry.nlark.com/semver/download/semver-6.3.0.tgz?cache=0&sync_timestamp=1631500167672&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-6.3.0.tgz
|
||||
tarball: https://registry.nlark.com/semver/download/semver-6.3.0.tgz
|
||||
}
|
||||
name: semver
|
||||
version: 6.3.0
|
||||
|
@ -8230,6 +8232,17 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@windicss/plugin-animations/1.0.9:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha1-q9fILZBuvX1hzcYqMBm2DoxXynI=,
|
||||
registry: https://registry.npm.taobao.org/,
|
||||
tarball: https://registry.npmmirror.com/@windicss/plugin-animations/download/@windicss/plugin-animations-1.0.9.tgz
|
||||
}
|
||||
name: '@windicss/plugin-animations'
|
||||
version: 1.0.9
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@windicss/plugin-utils/1.6.1:
|
||||
resolution:
|
||||
{
|
||||
|
|
|
@ -10,18 +10,21 @@ const appStore = useAppStore()
|
|||
|
||||
const localeStore = useLocaleStore()
|
||||
|
||||
const local = computed(() => localeStore.locale)
|
||||
const locale = computed(() => localeStore.locale)
|
||||
|
||||
const size = computed(() => appStore.size)
|
||||
|
||||
function initDark() {
|
||||
const isDarkTheme = isDark()
|
||||
appStore.setIsDark(isDarkTheme)
|
||||
}
|
||||
|
||||
initDark()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ConfigGlobal>
|
||||
<ElConfigProvider :locale="local.elLocale">
|
||||
<ConfigGlobal :size="size">
|
||||
<ElConfigProvider :locale="locale.elLocale" :size="size">
|
||||
<RouterView />
|
||||
</ElConfigProvider>
|
||||
</ConfigGlobal>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 55 KiB |
|
@ -3,7 +3,7 @@ import { provide, defineComponent } from 'vue'
|
|||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'VConfigGlobal',
|
||||
name: 'ConfigGlobal',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
size: propTypes.oneOf(['default', 'medium', 'small', 'mini']).def('default')
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import VFrom from './src/Form.vue'
|
||||
import Form from './src/Form.vue'
|
||||
|
||||
export interface VFormExpose {
|
||||
export interface FormExpose {
|
||||
count: number
|
||||
sayHello: () => void
|
||||
}
|
||||
|
||||
export { VFrom }
|
||||
export { Form }
|
||||
|
|
|
@ -16,7 +16,7 @@ import { useRenderRadio } from './components/useRenderRadio'
|
|||
import { useRenderChcekbox } from './components/useRenderChcekbox'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'VForm',
|
||||
name: 'Form',
|
||||
props: {
|
||||
// 生成Form的布局结构数组
|
||||
schema: {
|
||||
|
|
|
@ -20,10 +20,10 @@ const props = defineProps({
|
|||
|
||||
const elRef = ref<ElRef>(null)
|
||||
|
||||
const isLocal = computed(() => props.icon.startsWith('icon:'))
|
||||
const isLocal = computed(() => props.icon.startsWith('svg-icon:'))
|
||||
|
||||
const symbolId = computed(() => {
|
||||
return unref(isLocal) ? `#icon-${props.icon.split('icon:')[1]}` : props.icon
|
||||
return unref(isLocal) ? `#icon-${props.icon.split('svg-icon:')[1]}` : props.icon
|
||||
})
|
||||
|
||||
const getIconifyStyle = computed(() => {
|
||||
|
@ -76,11 +76,3 @@ watch(
|
|||
</span>
|
||||
</ElIcon>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{namespace}-icon';
|
||||
|
||||
.@{prefix-cls} {
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -19,16 +19,19 @@ const emit = defineEmits(['update:modelValue'])
|
|||
|
||||
// 生成class前缀
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = ref(getPrefixCls('input-password'))
|
||||
|
||||
// 设置input的type属性
|
||||
const textType = ref<'password' | 'text'>('password')
|
||||
|
||||
function changeTextType() {
|
||||
textType.value = unref(textType) === 'text' ? 'password' : 'text'
|
||||
}
|
||||
|
||||
// 输入框的值
|
||||
const valueRef = ref('')
|
||||
|
||||
// 监听
|
||||
watch(
|
||||
() => valueRef.value,
|
||||
|
@ -36,6 +39,7 @@ watch(
|
|||
emit('update:modelValue', val)
|
||||
}
|
||||
)
|
||||
|
||||
// 获取密码强度
|
||||
const getPasswordStrength = computed(() => {
|
||||
const value = unref(valueRef)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import SizeDropdown from './src/SizeDropdown.vue'
|
||||
|
||||
export { SizeDropdown }
|
|
@ -0,0 +1,31 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { ElDropdown, ElDropdownMenu, ElDropdownItem } from 'element-plus'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { useCssVar } from '@vueuse/core'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
const sizeMap = computed(() => appStore.sizeMap)
|
||||
|
||||
const textColor = useCssVar('--el-text-color-primary', document.documentElement)
|
||||
|
||||
function setSize(size: ElememtPlusSzie) {
|
||||
appStore.setSize(size)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDropdown trigger="click" @command="setSize">
|
||||
<Icon icon="mdi:format-size" :color="textColor" class="cursor-pointer" />
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
<ElDropdownItem v-for="item in sizeMap" :key="item" :command="item">
|
||||
{{ t(`size.${[item]}`) }}
|
||||
</ElDropdownItem>
|
||||
</ElDropdownMenu>
|
||||
</template>
|
||||
</ElDropdown>
|
||||
</template>
|
|
@ -7,6 +7,7 @@ import { useDesign } from '@/hooks/web/useDesign'
|
|||
import { useIcon } from '@/hooks/web/useIcon'
|
||||
|
||||
const Sun = useIcon({ icon: 'emojione-monotone:sun' })
|
||||
|
||||
const CrescentMoon = useIcon({ icon: 'emojione-monotone:crescent-moon' })
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
@ -15,6 +16,7 @@ const appStore = useAppStore()
|
|||
const isDark = ref(appStore.getIsDark)
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('theme-switch')
|
||||
|
||||
// 设置switch的背景颜色
|
||||
|
|
|
@ -22,7 +22,7 @@ export function useLocale() {
|
|||
async function changeLocale(locale: LocaleType) {
|
||||
const globalI18n = i18n.global
|
||||
|
||||
const langModule = (await import(`../../locales/${locale}.ts`)) as any
|
||||
const langModule = await import(`../../locales/${locale}.ts`)
|
||||
|
||||
globalI18n.setLocaleMessage(locale, langModule.default)
|
||||
|
||||
|
|
|
@ -6,6 +6,11 @@ export default {
|
|||
endTimeText: 'End time',
|
||||
login: 'Login'
|
||||
},
|
||||
size: {
|
||||
default: 'Default',
|
||||
large: 'Large',
|
||||
small: 'Small'
|
||||
},
|
||||
formDemo: {
|
||||
input: 'Input',
|
||||
inputNumber: 'InputNumber',
|
||||
|
|
|
@ -6,6 +6,11 @@ export default {
|
|||
endTimeText: '结束时间',
|
||||
login: '登录'
|
||||
},
|
||||
size: {
|
||||
default: '默认',
|
||||
large: '大',
|
||||
small: '小'
|
||||
},
|
||||
formDemo: {
|
||||
input: '输入框',
|
||||
inputNumber: '数字输入框',
|
||||
|
|
|
@ -4,12 +4,14 @@ import type { App } from 'vue'
|
|||
import { ElLoading, ElScrollbar } from 'element-plus'
|
||||
|
||||
const plugins = [ElLoading]
|
||||
|
||||
const components = [ElScrollbar]
|
||||
|
||||
export function setupElementPlus(app: App) {
|
||||
plugins.forEach((plugin) => {
|
||||
app.use(plugin)
|
||||
})
|
||||
|
||||
components.forEach((component) => {
|
||||
app.component(component.name, component)
|
||||
})
|
||||
|
|
|
@ -23,6 +23,7 @@ export interface AppState {
|
|||
requestTime: boolean
|
||||
isDark: boolean
|
||||
size: ElememtPlusSzie
|
||||
sizeMap: ElememtPlusSzie[]
|
||||
}
|
||||
|
||||
export const useAppStore = defineStore({
|
||||
|
@ -46,7 +47,8 @@ export const useAppStore = defineStore({
|
|||
showMenuTab: false, // 是否固定一级菜单
|
||||
requestTime: false, // 是否在接口调用时添加时间戳,避免IE缓存
|
||||
isDark: false, // 是否是暗黑模式
|
||||
size: 'default' // 组件尺寸
|
||||
size: 'default', // 组件尺寸
|
||||
sizeMap: ['default', 'large', 'small']
|
||||
}),
|
||||
getters: {
|
||||
getCollapsed(): boolean {
|
||||
|
@ -105,6 +107,9 @@ export const useAppStore = defineStore({
|
|||
},
|
||||
getSize(): ElememtPlusSzie {
|
||||
return this.size
|
||||
},
|
||||
getSizeMap(): ElememtPlusSzie[] {
|
||||
return this.sizeMap
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
|
|
@ -1,34 +1,38 @@
|
|||
<script setup lang="ts">
|
||||
import { ThemeSwitch } from '@/components/ThemeSwitch'
|
||||
import { LocaleDropdown } from '@/components/LocaleDropdown'
|
||||
import { LoginForm } from './components'
|
||||
import { ElCard } from 'element-plus'
|
||||
// import { ThemeSwitch } from '@/components/ThemeSwitch'
|
||||
// import { LocaleDropdown } from '@/components/LocaleDropdown'
|
||||
// import { SizeDropdown } from '@/components/SizeDropdown'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { ElCalendar } from 'element-plus'
|
||||
import { VFrom } from '@/components/Form'
|
||||
// import { useI18n } from '@/hooks/web/useI18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
// const { t } = useI18n()
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('login')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="prefixCls" class="h-[calc(100%)] relative">
|
||||
<Icon icon="icon:icon" />
|
||||
<Icon icon="ant-design:eye-outlined" />
|
||||
<ThemeSwitch />
|
||||
<LocaleDropdown />
|
||||
<ElCalendar />
|
||||
<VFrom
|
||||
:schema="[
|
||||
{
|
||||
label: 'input',
|
||||
field: 'field1',
|
||||
component: 'InputPassword'
|
||||
}
|
||||
]"
|
||||
/>
|
||||
{{ t('formDemo.default') }}
|
||||
<div
|
||||
class="container relative h-full py-2 mx-auto flex @2xl:max-w-1600px @xl:max-w-1000px @lg:max-w-600px @md:max-w-500px @sm:max-w-500px"
|
||||
>
|
||||
<div class="flex-1 <lg:hidden">
|
||||
<img src="@/assets/svgs/login-box-bg.svg" alt="" class="w-1/2 m-auto" />
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<ElCard>
|
||||
<template #header>
|
||||
<div>
|
||||
<span>Card name</span>
|
||||
</div>
|
||||
</template>
|
||||
<LoginForm />
|
||||
</ElCard>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<script setup lang="ts">
|
||||
import { Form } from '@/components/Form'
|
||||
|
||||
const schema: FormSchema[] = [
|
||||
{
|
||||
field: 'username',
|
||||
component: 'Input'
|
||||
},
|
||||
{
|
||||
field: 'password',
|
||||
component: 'InputPassword'
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Form :schema="schema" :label-width="0" />
|
||||
</template>
|
|
@ -0,0 +1,3 @@
|
|||
import LoginForm from './LoginForm.vue'
|
||||
|
||||
export { LoginForm }
|
|
@ -12,14 +12,14 @@ export default defineConfig({
|
|||
darkMode: 'class',
|
||||
attributify: false,
|
||||
theme: {
|
||||
extend: {
|
||||
screens: {
|
||||
sm: '768px',
|
||||
md: '992px',
|
||||
lg: '1200px',
|
||||
xl: '1920px'
|
||||
}
|
||||
}
|
||||
// extend: {
|
||||
// screens: {
|
||||
// sm: '768px',
|
||||
// md: '992px',
|
||||
// lg: '1200px',
|
||||
// xl: '1920px'
|
||||
// }
|
||||
// }
|
||||
// height: {
|
||||
// ...range(50).map((i) => `h-${i}px`)
|
||||
// },
|
||||
|
@ -29,5 +29,17 @@ export default defineConfig({
|
|||
// // ...range(50).map((i) => `mb-${i}px`),
|
||||
// // ...range(50).map((i) => `ml-${i}px`)
|
||||
// }
|
||||
},
|
||||
Plugin: [
|
||||
require('@windicss/plugin-animations')({
|
||||
settings: {
|
||||
animatedSpeed: 1000,
|
||||
heartBeatSpeed: 1000,
|
||||
hingeSpeed: 2000,
|
||||
bounceInSpeed: 750,
|
||||
bounceOutSpeed: 750,
|
||||
animationDelaySpeed: 1000
|
||||
}
|
||||
})
|
||||
]
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue