feat: 登录页改造

This commit is contained in:
kailong321200875 2023-07-10 20:40:36 +08:00
parent b1a83f6018
commit 5312951359
9 changed files with 197 additions and 164 deletions

View File

@ -15,7 +15,6 @@ export interface TableExpose {
setColumn: (columnProps: TableSetProps[]) => void setColumn: (columnProps: TableSetProps[]) => void
addColumn: (column: TableColumn, index?: number) => void addColumn: (column: TableColumn, index?: number) => void
delColumn: (field: string) => void delColumn: (field: string) => void
selections: Recordable[]
elTableRef: ComponentRef<typeof ElTable> elTableRef: ComponentRef<typeof ElTable>
} }

View File

@ -230,18 +230,11 @@ export default defineComponent({
} }
} }
const selections = ref<Recordable[]>([])
const selectionChange = (selection: Recordable[]) => {
selections.value = selection
}
expose({ expose({
setProps, setProps,
setColumn, setColumn,
delColumn, delColumn,
addColumn, addColumn,
selections,
elTableRef elTableRef
}) })
@ -409,12 +402,7 @@ export default defineComponent({
return () => ( return () => (
<div v-loading={unref(getProps).loading}> <div v-loading={unref(getProps).loading}>
<ElTable <ElTable ref={elTableRef} data={unref(getProps).data} {...unref(getBindValue)}>
ref={elTableRef}
data={unref(getProps).data}
onSelection-change={selectionChange}
{...unref(getBindValue)}
>
{{ {{
default: () => renderTableColumn(), default: () => renderTableColumn(),
empty: () => getSlot(slots, 'empty') || unref(getProps).emptyText, empty: () => getSlot(slots, 'empty') || unref(getProps).emptyText,

View File

@ -143,15 +143,6 @@ export const useTable = (config: UseTableConfig) => {
table?.delColumn(field) table?.delColumn(field)
}, },
/**
* @description
* @returns
*/
getSelections: async () => {
const table = await getTable()
return table?.selections || []
},
/** /**
* @description ElTable组件的实例 * @description ElTable组件的实例
* @returns ElTable instance * @returns ElTable instance

View File

@ -421,7 +421,8 @@ export default {
delOrAddAction: 'Delete or add action', delOrAddAction: 'Delete or add action',
showOrHiddenStripe: 'Show or hidden stripe', showOrHiddenStripe: 'Show or hidden stripe',
showOrHiddenBorder: 'Show or hidden border', showOrHiddenBorder: 'Show or hidden border',
fixedHeaderOrAuto: 'Fixed header or auto' fixedHeaderOrAuto: 'Fixed header or auto',
getSelections: 'Get selections'
}, },
richText: { richText: {
richText: 'Rich text', richText: 'Rich text',

View File

@ -416,7 +416,8 @@ export default {
delOrAddAction: '删除/添加操作列', delOrAddAction: '删除/添加操作列',
showOrHiddenStripe: '显示/隐藏斑马纹', showOrHiddenStripe: '显示/隐藏斑马纹',
showOrHiddenBorder: '显示/隐藏边框', showOrHiddenBorder: '显示/隐藏边框',
fixedHeaderOrAuto: '固定头部/自动' fixedHeaderOrAuto: '固定头部/自动',
getSelections: '获取多选数据'
}, },
richText: { richText: {
richText: '富文本', richText: '富文本',

View File

@ -26,52 +26,52 @@ const whiteList = ['/login'] // 不重定向白名单
router.beforeEach(async (to, from, next) => { router.beforeEach(async (to, from, next) => {
start() start()
loadStart() loadStart()
// if (!wsCache.get(appStore.getUserInfo)) { if (wsCache.get(appStore.getUserInfo)) {
if (to.path === '/login') { if (to.path === '/login') {
next({ path: '/' }) next({ path: '/' })
} else {
if (!dictStore.getIsSetDict) {
// 获取所有字典
const res = await getDictApi()
if (res) {
dictStore.setDictObj(res.data)
dictStore.setIsSetDict(true)
}
}
if (permissionStore.getIsAddRouters) {
next()
return
}
// 开发者可根据实际情况进行修改
const roleRouters = wsCache.get('roleRouters') || []
const userInfo = wsCache.get(appStore.getUserInfo)
// 是否使用动态路由
if (appStore.getDynamicRouter) {
userInfo.role === 'admin'
? await permissionStore.generateRoutes('admin', roleRouters as AppCustomRouteRecordRaw[])
: await permissionStore.generateRoutes('test', roleRouters as string[])
} else { } else {
await permissionStore.generateRoutes('none') if (!dictStore.getIsSetDict) {
} // 获取所有字典
const res = await getDictApi()
if (res) {
dictStore.setDictObj(res.data)
dictStore.setIsSetDict(true)
}
}
if (permissionStore.getIsAddRouters) {
next()
return
}
permissionStore.getAddRouters.forEach((route) => { // 开发者可根据实际情况进行修改
router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表 const roleRouters = wsCache.get('roleRouters') || []
}) const userInfo = wsCache.get(appStore.getUserInfo)
const redirectPath = from.query.redirect || to.path
const redirect = decodeURIComponent(redirectPath as string) // 是否使用动态路由
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect } if (appStore.getDynamicRouter) {
permissionStore.setIsAddRouters(true) userInfo.role === 'admin'
next(nextData) ? await permissionStore.generateRoutes('admin', roleRouters as AppCustomRouteRecordRaw[])
: await permissionStore.generateRoutes('test', roleRouters as string[])
} else {
await permissionStore.generateRoutes('none')
}
permissionStore.getAddRouters.forEach((route) => {
router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表
})
const redirectPath = from.query.redirect || to.path
const redirect = decodeURIComponent(redirectPath as string)
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }
permissionStore.setIsAddRouters(true)
next(nextData)
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
}
} }
// } else {
// if (whiteList.indexOf(to.path) !== -1) {
// next()
// } else {
// next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
// }
// }
}) })
router.afterEach((to) => { router.afterEach((to) => {

View File

@ -207,6 +207,12 @@ const fixedHeaderOrAuto = () => {
height.value = 'auto' height.value = 'auto'
} }
} }
const getSelections = async () => {
const elTableRef = await getElTableExpose()
const selections = elTableRef?.getSelectionRows()
console.log(selections)
}
</script> </script>
<template> <template>
@ -236,6 +242,8 @@ const fixedHeaderOrAuto = () => {
<ElButton @click="showOrHiddenStripe">{{ t('tableDemo.showOrHiddenStripe') }}</ElButton> <ElButton @click="showOrHiddenStripe">{{ t('tableDemo.showOrHiddenStripe') }}</ElButton>
<ElButton @click="fixedHeaderOrAuto">{{ t('tableDemo.fixedHeaderOrAuto') }}</ElButton> <ElButton @click="fixedHeaderOrAuto">{{ t('tableDemo.fixedHeaderOrAuto') }}</ElButton>
<ElButton @click="getSelections">{{ t('tableDemo.getSelections') }}</ElButton>
</ContentWrap> </ContentWrap>
<ContentWrap :title="`UseTable ${t('tableDemo.example')}`"> <ContentWrap :title="`UseTable ${t('tableDemo.example')}`">
<Table <Table

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="tsx">
import { reactive, ref, unref, watch } from 'vue' import { reactive, ref, watch } from 'vue'
import { Form } from '@/components/Form' import { Form, FormSchema } from '@/components/Form'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { ElButton, ElCheckbox, ElLink } from 'element-plus' import { ElButton, ElCheckbox, ElLink } from 'element-plus'
import { useForm } from '@/hooks/web/useForm' import { useForm } from '@/hooks/web/useForm'
@ -12,7 +12,7 @@ import { useRouter } from 'vue-router'
import type { RouteLocationNormalizedLoaded, RouteRecordRaw } from 'vue-router' import type { RouteLocationNormalizedLoaded, RouteRecordRaw } from 'vue-router'
import { UserType } from '@/api/login/types' import { UserType } from '@/api/login/types'
import { useValidator } from '@/hooks/web/useValidator' import { useValidator } from '@/hooks/web/useValidator'
import { FormSchema } from '@/types/form' import { Icon } from '@/components/Icon'
const { required } = useValidator() const { required } = useValidator()
@ -38,6 +38,13 @@ const schema = reactive<FormSchema[]>([
field: 'title', field: 'title',
colProps: { colProps: {
span: 24 span: 24
},
formItemProps: {
slots: {
default: () => {
return <h2 class="text-2xl font-bold text-center w-[100%]">{t('login.login')}</h2>
}
}
} }
}, },
{ {
@ -71,12 +78,48 @@ const schema = reactive<FormSchema[]>([
field: 'tool', field: 'tool',
colProps: { colProps: {
span: 24 span: 24
},
formItemProps: {
slots: {
default: () => {
return (
<>
<div class="flex justify-between items-center w-[100%]">
<ElCheckbox v-model={remember.value} label={t('login.remember')} size="small" />
<ElLink type="primary" underline={false}>
{t('login.forgetPassword')}
</ElLink>
</div>
</>
)
}
}
} }
}, },
{ {
field: 'login', field: 'login',
colProps: { colProps: {
span: 24 span: 24
},
formItemProps: {
slots: {
default: () => {
return (
<>
<div class="w-[100%]">
<ElButton loading={loading.value} type="primary" class="w-[100%]" onClick={signIn}>
{t('login.login')}
</ElButton>
</div>
<div class="w-[100%] mt-15px">
<ElButton class="w-[100%]" onClick={toRegister}>
{t('login.register')}
</ElButton>
</div>
</>
)
}
}
} }
}, },
{ {
@ -91,6 +134,42 @@ const schema = reactive<FormSchema[]>([
field: 'otherIcon', field: 'otherIcon',
colProps: { colProps: {
span: 24 span: 24
},
formItemProps: {
slots: {
default: () => {
return (
<>
<div class="flex justify-between w-[100%]">
<Icon
icon="ant-design:github-filled"
size={iconSize}
class="cursor-pointer ant-icon"
color={iconColor}
/>
<Icon
icon="ant-design:wechat-filled"
size={iconSize}
class="cursor-pointer ant-icon"
color={iconColor}
/>
<Icon
icon="ant-design:alipay-circle-filled"
size={iconSize}
color={iconColor}
class="cursor-pointer ant-icon"
/>
<Icon
icon="ant-design:weibo-circle-filled"
size={iconSize}
color={iconColor}
class="cursor-pointer ant-icon"
/>
</div>
</>
)
}
}
} }
} }
]) ])
@ -99,7 +178,8 @@ const iconSize = 30
const remember = ref(false) const remember = ref(false)
const { register, elFormRef, methods } = useForm() const { formRegister, formMethods } = useForm()
const { getFormData, getElFormExpose } = formMethods
const loading = ref(false) const loading = ref(false)
@ -126,11 +206,10 @@ const signIn = async () => {
permissionStore.setIsAddRouters(true) permissionStore.setIsAddRouters(true)
push({ path: redirect.value || permissionStore.addRouters[0].path }) push({ path: redirect.value || permissionStore.addRouters[0].path })
const formRef = unref(elFormRef) const formRef = await getElFormExpose()
await formRef?.validate(async (isValid) => { await formRef?.validate(async (isValid) => {
if (isValid) { if (isValid) {
loading.value = true loading.value = true
const { getFormData } = methods
const formData = await getFormData<UserType>() const formData = await getFormData<UserType>()
try { try {
@ -159,7 +238,6 @@ const signIn = async () => {
// //
const getRole = async () => { const getRole = async () => {
const { getFormData } = methods
const formData = await getFormData<UserType>() const formData = await getFormData<UserType>()
const params = { const params = {
roleName: formData.username roleName: formData.username
@ -199,66 +277,13 @@ const toRegister = () => {
hide-required-asterisk hide-required-asterisk
size="large" size="large"
class="dark:(border-1 border-[var(--el-border-color)] border-solid)" class="dark:(border-1 border-[var(--el-border-color)] border-solid)"
@register="register" @register="formRegister"
> />
<template #title>
<h2 class="text-2xl font-bold text-center w-[100%]">{{ t('login.login') }}</h2>
</template>
<template #tool>
<div class="flex justify-between items-center w-[100%]">
<ElCheckbox v-model="remember" :label="t('login.remember')" size="small" />
<ElLink type="primary" :underline="false">{{ t('login.forgetPassword') }}</ElLink>
</div>
</template>
<template #login>
<div class="w-[100%]">
<ElButton :loading="loading" type="primary" class="w-[100%]" @click="signIn">
{{ t('login.login') }}
</ElButton>
</div>
<div class="w-[100%] mt-15px">
<ElButton class="w-[100%]" @click="toRegister">
{{ t('login.register') }}
</ElButton>
</div>
</template>
<template #otherIcon>
<div class="flex justify-between w-[100%]">
<Icon
icon="ant-design:github-filled"
:size="iconSize"
class="cursor-pointer anticon"
:color="iconColor"
/>
<Icon
icon="ant-design:wechat-filled"
:size="iconSize"
class="cursor-pointer anticon"
:color="iconColor"
/>
<Icon
icon="ant-design:alipay-circle-filled"
:size="iconSize"
:color="iconColor"
class="cursor-pointer anticon"
/>
<Icon
icon="ant-design:weibo-circle-filled"
:size="iconSize"
:color="iconColor"
class="cursor-pointer anticon"
/>
</div>
</template>
</Form>
</template> </template>
<style lang="less" scoped> <style lang="less" scoped>
:deep(.anticon) { :deep(.ant-icon) {
&:hover { & > svg:hover {
color: var(--el-color-primary) !important; color: var(--el-color-primary) !important;
} }
} }

View File

@ -1,15 +1,15 @@
<script setup lang="ts"> <script setup lang="tsx">
import { Form } from '@/components/Form' import { Form, FormSchema } from '@/components/Form'
import { reactive, ref, unref } from 'vue' import { reactive, ref } 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 { ElButton, ElInput, FormRules } from 'element-plus' import { ElButton, ElInput, FormRules } from 'element-plus'
import { useValidator } from '@/hooks/web/useValidator' import { useValidator } from '@/hooks/web/useValidator'
import { FormSchema } from '@/types/form'
const emit = defineEmits(['to-login']) const emit = defineEmits(['to-login'])
const { register, elFormRef } = useForm() const { formRegister, formMethods } = useForm()
const { getElFormExpose } = formMethods
const { t } = useI18n() const { t } = useI18n()
@ -20,6 +20,13 @@ const schema = reactive<FormSchema[]>([
field: 'title', field: 'title',
colProps: { colProps: {
span: 24 span: 24
},
formItemProps: {
slots: {
default: () => {
return <h2 class="text-2xl font-bold text-center w-[100%]">{t('login.register')}</h2>
}
}
} }
}, },
{ {
@ -71,12 +78,48 @@ const schema = reactive<FormSchema[]>([
label: t('login.code'), label: t('login.code'),
colProps: { colProps: {
span: 24 span: 24
},
formItemProps: {
slots: {
default: (formData) => {
return (
<div class="w-[100%] flex">
<ElInput v-model={formData.code} placeholder={t('login.codePlaceholder')} />
</div>
)
}
}
} }
}, },
{ {
field: 'register', field: 'register',
colProps: { colProps: {
span: 24 span: 24
},
formItemProps: {
slots: {
default: () => {
return (
<>
<div class="w-[100%]">
<ElButton
type="primary"
class="w-[100%]"
loading={loading.value}
onClick={loginRegister}
>
{t('login.register')}
</ElButton>
</div>
<div class="w-[100%] mt-15px">
<ElButton class="w-[100%]" onClick={toLogin}>
{t('login.hasUser')}
</ElButton>
</div>
</>
)
}
}
} }
} }
]) ])
@ -95,7 +138,7 @@ const toLogin = () => {
const loading = ref(false) const loading = ref(false)
const loginRegister = async () => { const loginRegister = async () => {
const formRef = unref(elFormRef) const formRef = await getElFormExpose()
formRef?.validate(async (valid) => { formRef?.validate(async (valid) => {
if (valid) { if (valid) {
try { try {
@ -117,29 +160,6 @@ const loginRegister = async () => {
hide-required-asterisk hide-required-asterisk
size="large" size="large"
class="dark:(border-1 border-[var(--el-border-color)] border-solid)" class="dark:(border-1 border-[var(--el-border-color)] border-solid)"
@register="register" @register="formRegister"
> />
<template #title>
<h2 class="text-2xl font-bold text-center w-[100%]">{{ t('login.register') }}</h2>
</template>
<template #code="form">
<div class="w-[100%] flex">
<ElInput v-model="form['code']" :placeholder="t('login.codePlaceholder')" />
</div>
</template>
<template #register>
<div class="w-[100%]">
<ElButton type="primary" class="w-[100%]" :loading="loading" @click="loginRegister">
{{ t('login.register') }}
</ElButton>
</div>
<div class="w-[100%] mt-15px">
<ElButton class="w-[100%]" @click="toLogin">
{{ t('login.hasUser') }}
</ElButton>
</div>
</template>
</Form>
</template> </template>