@ithinkdt/naive
Version:
iThinkDT Naive UI
362 lines (340 loc) • 14.2 kB
JSX
import { defineComponent, h, reactive, ref, watch } from 'vue'
import { NForm, NFormItem, NInput, NButton, NIcon } from 'ithinkdt-ui'
import { promiseTimeout } from '@vueuse/core'
import { useI18n, useLogin, useTheme, usePageTab } from '@ithinkdt/core'
import {
flexCenter,
flexDirCol,
flexGap,
flexAlignCenter,
flexJustifySB,
fullWidth,
cB,
cE,
cM,
c,
CSS_MOUNT_ANCHOR_META_NAME,
CSS_STYLE_PREFIX as p,
} from '@ithinkdt/core/cssr'
import { DtLang } from './layout/l-lang'
import { DtAppearence } from './layout/l-appearence'
import { IAccount, IPwd, IClose as IClear, IError, ICheck } from './assets.jsx'
export const DtLogin = defineComponent({
name: 'DtLogin',
props: {
logo: {
type: [String, Object, Function],
required: false,
default: undefined,
},
background: {
type: [Object, Function],
required: false,
default: undefined,
},
defaultUser: {
type: Object,
required: false,
default: undefined,
},
},
async setup(props) {
const cls = `${p}-login`
createStyle(cls)
const theme = useTheme('scoped', ['fullTab', 'multiTab', 'watermark'])
theme.fullTab = true
theme.multiTab = false
theme.watermark = false
const { t } = useI18n()
usePageTab('登录')
const user = reactive({})
watch(
() => props.defaultUser,
(def) => {
if (def) Object.assign(user, def)
},
{ immediate: true },
)
const { user: _user, login, loging, next } = useLogin()
const result = ref()
watch(user, () => (result.value = undefined))
async function onLogin(e) {
e?.preventDefault()
try {
await login(user)
result.value = true
await promiseTimeout(1300)
next()
} catch (error) {
result.value = error.message
}
}
return () => {
return (
<div class={[cls, { [`${cls}--dark`]: theme.isDark }]}>
<div class={`${cls}__wrapper`}>
<div class={`${cls}__wrapper-before`} />
<div class={`${cls}__wrapper-after`} />
<span class={`${cls}__top`}>
{typeof props.logo === 'string' ? <img src={props.logo} alt="logo" /> : h(props.logo)}
{theme.showAppearence ? <DtAppearence /> : undefined}
{theme.showI18n ? <DtLang /> : undefined}
</span>
<div class={`${cls}__pic`}>
{typeof props.background === 'string' ? (
<img src={props.background} alt="background" />
) : (
h(props.background)
)}
</div>
<div class={`${cls}__panel`}>
<div class={`${cls}__panel-title`}>{t('sys.login.title')}</div>
<NForm class={`${cls}__form`} model={user} showLabel={false} onSubmit={onLogin}>
<NFormItem class={`${cls}__form-item ${cls}__form-username`} path="username">
<NInput
v-model:value={user.username}
autofocus
clearable
placeholder={t('sys.login.username')}
>
{{
prefix: () => (
<NIcon size={20}>
<IAccount />
</NIcon>
),
'clear-icon': () => (
<NIcon>
<IClear />
</NIcon>
),
}}
</NInput>
</NFormItem>
<NFormItem class={`${cls}__form-item ${cls}__form-pwd`} path="password">
<NInput
v-model:value={user.password}
type="password"
showPasswordOn="mousedown"
clearable
inputProps={{ autocomplete: 'off' }}
placeholder={t('sys.login.pwd')}
>
{{
prefix: () => (
<NIcon size={20}>
<IPwd />
</NIcon>
),
'clear-icon': () => (
<NIcon>
<IClear />
</NIcon>
),
}}
</NInput>
</NFormItem>
<div class={`${cls}__form-submit`}>
<div class={`${cls}__result`}>
{typeof result.value === 'string' ? (
<>
<NIcon size={22}>
<IError />
</NIcon>
{result.value}
</>
) : undefined}
</div>
<NButton
type="primary"
size="large"
block
loading={loging.value}
disabled={typeof result.value === 'string'}
bordered={false}
attrType="submit"
>
{{
default: () =>
result.value === true ? t('sys.login.success') : t('sys.login.btn'),
icon: () =>
result.value === true ? (
<NIcon size={22}>
<ICheck />
</NIcon>
) : undefined,
}}
</NButton>
</div>
</NForm>
<div class={`${cls}__panel-tip`}>{t('sys.login.tip')}</div>
</div>
</div>
</div>
)
}
},
})
let style
function createStyle(cls) {
if (!style) {
style = cB(
'login',
{
...flexCenter,
height: `var(--${p}_body-height)`,
position: 'relative',
minHeight: '700px',
[`--${cls}__shadow-color`]: `rgba(0, 0, 0, .08)`,
color: `var(--${p}-base-color)`,
},
[
cM('dark', {
[`--${cls}__shadow-color`]: `rgba(255, 255, 255, .08)`,
}),
cE('wrapper', {
boxSizing: 'border-box',
width: '1200px',
height: '660px',
position: 'relative',
padding: '24px 40px',
borderRadius: '3px',
boxShadow: `0 0 32px 24px var(--${cls}__shadow-color)`,
overflow: 'hidden',
}),
cE('top', {
...fullWidth,
...flexGap('32px'),
}),
cE(
'wrapper-before, wrapper-after',
{
display: 'inline-block',
position: 'absolute',
borderRadius: '50%',
},
[
c('&::before', {
display: 'inline-block',
content: `''`,
position: 'absolute',
borderRadius: '50%',
backgroundColor: `var(--${p}-body-color)`,
top: '15%',
left: '15%',
width: '70%',
height: '70%',
}),
],
),
cE(
'wrapper-before',
{
width: '180px',
height: '180px',
bottom: '-80px',
left: '-80px',
backgroundColor: '#8CC63E',
},
[
c('&::before', {
top: '17%',
left: '17%',
width: '66%',
height: '66%',
}),
],
),
cE('wrapper-after', {
width: '830px',
height: '830px',
top: '-200px',
right: '-415px',
background: 'linear-gradient(0deg, #0074FF 0%, #049AFB 100%)',
}),
cE('pic', { width: '520px', position: 'absolute', top: '150px', left: '80px' }, [c('img', fullWidth)]),
cE('panel', {
position: 'absolute',
top: '13%',
right: '90px',
zIndex: '1',
borderRadius: '3px',
padding: '40px 50px 30px',
boxSizing: 'border-box',
width: '33%',
height: '74%',
boxShadow: `0 0 12px 4px var(--${cls}__shadow-color)`,
...flexDirCol,
...flexAlignCenter,
...flexJustifySB,
background: `var(--${p}-card-color)`,
}),
cE('panel-title', {
fontWeight: 'bold',
fontSize: '20px',
letterSpacing: '2px',
color: `var(--${p}-text-color1)`,
}),
cE('panel-tip', {
fontSize: '13px',
color: `var(--${p}-text-color3)`,
}),
cE('form', {
width: '100%',
}),
cE('form-item', [
c('.n-input__border, .n-input__state-border', {
borderRadius: '0',
borderLeft: 'none !important',
borderTop: 'none !important',
borderRight: 'none !important',
boxShadow: 'none !important',
}),
c('.n-input__prefix', {
marginRight: '12px',
}),
c('.n-input--focus .n-input__prefix > .n-icon', {
color: `var(--${p}-primary-color-hover)`,
}),
c('.n-input ::-ms-reveal', {
display: 'none',
}),
]),
cE('form-username', {
marginBottom: '28px',
}),
cE('form-pwd', [
c('.n-base-clear', {
marginRight: '8px',
}),
]),
cE('result', {
height: '54px',
padding: '6px 0 0 10px',
...flexGap('12px'),
color: `var(--${p}-error-color)`,
}),
cE('form-submit', [
c(
'button',
{
borderRadius: '5px',
height: '45px',
transition: 'box-shadow 0.3s ease-in-out',
background: 'linear-gradient(to right, #0074FF 0%, #049AFB 100%)',
},
[
c('&:hover', {
boxShadow: `0 0 12px 8px rgba(4, 154, 251, .1)`,
}),
],
),
]),
],
)
style.mount({
id: cls,
anchorMetaName: CSS_MOUNT_ANCHOR_META_NAME,
})
}
}