UNPKG

@ithinkdt/naive

Version:

iThinkDT Naive UI

362 lines (340 loc) 14.2 kB
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, }) } }