1
0
mirror of https://github.com/chatopera/cosin.git synced 2025-08-01 16:38:02 +08:00

refactor: Authenticator Provider Page with Tailwind

Signed-off-by: Kaifuny <superbiger.github@gmail.com>
This commit is contained in:
Kaifuny 2023-09-08 12:37:06 +08:00
parent be5bbe5265
commit 156a1fb8e4
2 changed files with 138 additions and 736 deletions

View File

@ -1,14 +1,23 @@
<script setup lang="ts">
import { ROUTE_NAME } from '@cskefu/models'
import { NTabs, NTab } from 'naive-ui'
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const $router = useRouter()
const { name } = $router.currentRoute.value
const current = ref(name as ROUTE_NAME)
</script>
<template>
<div class="p-4">
<n-tabs
type="line"
:value="current"
:bar-width="32"
:on-update:value="
(value) => {
current = value
$router.push({
name: value as ROUTE_NAME,
})
@ -22,7 +31,7 @@ import { NTabs, NTab } from 'naive-ui'
<n-tab :name="ROUTE_NAME.SYSTEM_AUTHENTICATOR_TEMPLATE_INDEX" disabled>
模板
</n-tab>
<n-tab :name="ROUTE_NAME.SYSTEM_AUTHENTICATOR_SETTING_INDEX">
<n-tab :name="ROUTE_NAME.SYSTEM_AUTHENTICATOR_SETTING_INDEX" disabled>
设置
</n-tab>
</n-tabs>

View File

@ -6,780 +6,173 @@ import {
NGrid,
NGridItem,
NIcon,
FormInst,
NForm,
NFormItem,
NSwitch,
NDataTable,
NInput,
} from 'naive-ui'
import {
MailOutline,
KeyOutline,
LogoFacebook,
LogoGithub,
PersonCircleOutline,
LogoAlipay,
} from '@vicons/ionicons5'
import { ref } from 'vue'
import wechat from '@cskefu/assets/third-logo/wechat.svg'
import github from '@cskefu/assets/third-logo/github.svg'
import facebook from '@cskefu/assets/third-logo/facebook.svg'
import google from '@cskefu/assets/third-logo/google.svg'
import microsoft from '@cskefu/assets/third-logo/microsoft.svg'
const formProvider = ref<FormInst | null>(null)
let modelProvider = ref({
switchValue: false,
})
let modelProviderApp = ref({
switchValue: false,
id: '',
password: '',
})
const rules = {
id: {
required: true,
message: '请输入正确的ID',
trigger: ['input'],
const NativeProvider = [
{
provider: 'username',
label: '账号/密码',
icon: KeyOutline,
disabled: false,
},
password: {
required: true,
message: '请输入正确的密钥',
trigger: ['input'],
{
provider: 'email',
label: '电子邮件/密码',
icon: MailOutline,
disabled: true,
},
}
let isShowFormProvider = ref('')
let isShowForm = ref(false)
let isShowList = ref(true)
{
provider: 'guest',
label: '游客访问',
icon: PersonCircleOutline,
disabled: true,
},
]
const columns = ref([
{ title: '提供方', key: 'provider' },
{ title: '状态', key: 'status' },
])
const DomesticProvider = [
{
provider: 'alipay',
label: '微信',
image: wechat,
description: '允许用户使用支付宝扫码登录。',
disabled: true,
},
{
provider: 'wechat',
label: '支付宝',
icon: LogoAlipay,
description: '允许用户使用微信扫码。',
disabled: true,
},
]
const OtherProvider = [
{
provider: 'google',
label: 'Goole',
image: google,
description: '允许用户使用微信扫码。',
disabled: true,
},
{
provider: 'Facebook',
label: 'facebook',
image: facebook,
description: '允许用户使用微信扫码。',
disabled: true,
},
{
provider: 'microsoft',
label: 'Microsoft',
image: microsoft,
description: '允许用户使用微信扫码。',
disabled: true,
},
{
provider: 'github',
label: 'Github',
image: github,
description: '允许用户使用微信扫码。',
disabled: true,
},
]
let isShowList = ref(true)
let data = ref([{ provider: '电子邮件/密码', status: '已启动' }])
const handleValidateButtonClick = () => {
formProvider.value?.validate((errors) => {
if (!errors) {
console.log('保存成功')
isShowForm.value = false
isShowList.value = true
} else {
console.log('保存失败')
}
})
modelProvider.value = { switchValue: false }
modelProviderApp.value = { switchValue: false, id: '', password: '' }
}
const handleCloseButtonClick = () => {
isShowForm.value = false
modelProvider.value = { switchValue: false }
modelProviderApp.value = { switchValue: false, id: '', password: '' }
}
function onClickProvider(str: string): void {
isShowForm.value = true
isShowFormProvider.value = str
function onClickProvider(provider: string): void {
// todo
console.log(provider)
}
</script>
<template>
<n-layout content-style="padding: 24px;">
<n-card v-show="!isShowList">
<div v-show="isShowForm" class="provider-form">
<n-form
v-if="isShowFormProvider == 'email'"
ref="formProvider"
class="provider-form-mail"
:model="modelProvider"
label-placement="left"
label-align="left"
label-width="160"
>
<n-form-item label="电子邮件/密码" path="switchValue">
<div class="provider-form-item">
<n-switch v-model:value="modelProvider.switchValue"></n-switch>
</div>
</n-form-item>
<n-form-item>
<p>
允许用户使用自己的电子邮件地址和密码进行注册我们的 SDK
还提供电子邮件地址验证密码恢复和电子邮件地址更改等基本功能
</p>
</n-form-item>
<div class="provider-btn">
<n-button secondary round @click="handleCloseButtonClick()">
取消
</n-button>
<n-card v-show="!isShowList" title="添加新提供方">
<template #header-extra>
<n-button @click="isShowList = true"> 返回 </n-button>
</template>
<n-grid cols="1 650:4" class="divide-x">
<n-grid-item :span="0.8" class="p-2">
<div class="leading-8">原生提供方</div>
<div class="flex flex-col space-y-2">
<n-button
secondary
round
type="primary"
@click="handleValidateButtonClick()"
v-for="(item, index) in NativeProvider"
:key="index"
class="w-full justify-start"
:disabled="item.disabled"
@click="onClickProvider(item.provider)"
>
保存
<template #icon>
<n-icon v-if="item.icon" size="20" :component="item.icon" />
</template>
{{ item.label }}
</n-button>
</div>
</n-form>
<n-form
v-if="isShowFormProvider == 'password'"
ref="formProvider"
class="provider-form-password"
:model="modelProvider"
label-placement="left"
label-align="left"
label-width="80"
>
<n-form-item label="账号/密码" path="switchValue">
<div class="provider-form-item">
<n-switch v-model:value="modelProvider.switchValue"></n-switch>
</div>
</n-form-item>
<n-form-item>
<p>
允许用户使用自己的账号和密码进行注册我们的 SDK
还提供找回账号密码重置和密码修改等基本功能
</p>
</n-form-item>
<div class="provider-btn">
<n-button secondary round @click="handleCloseButtonClick()">
取消
</n-button>
<n-button
secondary
round
type="primary"
@click="handleValidateButtonClick()"
>
保存
</n-button>
</div>
</n-form>
<n-form
v-if="isShowFormProvider == 'person'"
ref="formProvider"
class="provider-form-person"
:model="modelProvider"
label-placement="left"
label-align="left"
label-width="80"
>
<n-form-item label="游客访问" path="switchValue">
<div class="provider-form-item">
<n-switch v-model:value="modelProvider.switchValue"></n-switch>
</div>
</n-form-item>
<n-form-item>
<p>
在您的应用中启用匿名访客账号这样可让您强制执行针对特定用户的安全性规则和春松客服规则而不需要用户提供凭据
</p>
</n-form-item>
<div class="provider-btn">
<n-button secondary round @click="handleCloseButtonClick()">
取消
</n-button>
<n-button
secondary
round
type="primary"
@click="handleValidateButtonClick()"
>
保存
</n-button>
</div>
</n-form>
<n-form
v-if="isShowFormProvider == 'wechat'"
ref="formProvider"
class="provider-form-wechat"
:model="modelProvider"
label-placement="left"
label-align="left"
label-width="160"
>
<n-form-item label="微信扫码登录" path="switchValue">
<div class="provider-form-item">
<n-switch v-model:value="modelProvider.switchValue"></n-switch>
</div>
</n-form-item>
<n-form-item>
<p>允许用户使用微信扫码</p>
</n-form-item>
<div class="provider-btn">
<n-button secondary round @click="handleCloseButtonClick()">
取消
</n-button>
<n-button
secondary
round
type="primary"
@click="handleValidateButtonClick()"
>
保存
</n-button>
</div>
</n-form>
<n-form
v-if="isShowFormProvider == 'alipay'"
ref="formProvider"
class="provider-form-alipay"
:model="modelProvider"
label-placement="left"
label-align="left"
label-width="160"
>
<n-form-item label="支付宝扫码" path="switchValue">
<div class="provider-form-item">
<n-switch v-model:value="modelProvider.switchValue"></n-switch>
</div>
</n-form-item>
<n-form-item>
<p>允许用户使用支付宝扫码登录</p>
</n-form-item>
<div class="provider-btn">
<n-button secondary round @click="handleCloseButtonClick()">
取消
</n-button>
<n-button
secondary
round
type="primary"
@click="handleValidateButtonClick()"
>
保存
</n-button>
</div>
</n-form>
<n-form
v-if="isShowFormProvider == 'google'"
ref="formProvider"
class="provider-form-google"
:rules="rules"
:model="modelProviderApp"
label-placement="left"
label-align="left"
label-width="160"
>
<n-form-item label="Google" path="switchValue">
<div class="provider-form-item">
<n-switch v-model:value="modelProvider.switchValue"></n-switch>
</div>
</n-form-item>
<n-form-item path="id" label="Web客户端ID">
<n-input
v-model:value="modelProviderApp.id"
@keydown.enter.prevent
/>
</n-form-item>
<n-form-item path="password" label="Web客户端密钥">
<n-input
v-model:value="modelProviderApp.password"
@keydown.enter.prevent
/>
</n-form-item>
<n-form-item>
<p>
重要提示若要为您的 Android 应用启用 Google
登录功能您必须为每个应用提供
<n-button
text
tag="a"
href="https://developers.google.com/android/guides/client-auth?hl=zh-cn"
target="_blank"
type="primary"
>
SHA-1 版本指纹
</n-button>
</p>
</n-form-item>
<div class="provider-btn">
<n-button secondary round @click="handleCloseButtonClick()">
取消
</n-button>
<n-button
secondary
round
type="primary"
@click="handleValidateButtonClick()"
>
保存
</n-button>
</div>
</n-form>
<n-form
v-if="isShowFormProvider == 'facebook'"
ref="formProvider"
class="provider-form-facebook"
:model="modelProviderApp"
:rules="rules"
label-placement="left"
label-align="left"
label-width="80"
>
<n-form-item label="Facebook" path="switchValue">
<div class="provider-form-item">
<n-switch v-model:value="modelProviderApp.switchValue"></n-switch>
</div>
</n-form-item>
<n-form-item path="id" label="应用ID">
<n-input
v-model:value="modelProviderApp.id"
@keydown.enter.prevent
/>
</n-form-item>
<n-form-item path="password" label="应用密钥">
<n-input
v-model:value="modelProviderApp.password"
@keydown.enter.prevent
/>
</n-form-item>
<n-form-item>
<p>
若要完成设置请在您的 Facebook 应用配置中添加此 OAuth 重定向
URI
<n-button
text
tag="a"
href="https://firebase.google.com/docs/auth/?hl=zh&authuser=0&_gl=1*yqljpk*_ga*MjEyMzg3MjAyNi4xNjkyNTM0MjU4*_ga_CW55HF8NVT*MTY5MzU1NzM3Ni4xMC4xLjE2OTM1NTc0MDYuMC4wLjA."
target="_blank"
type="primary"
>
了解详情
</n-button>
</p>
</n-form-item>
<div class="provider-btn">
<n-button secondary round @click="handleCloseButtonClick()">
取消
</n-button>
<n-button
secondary
round
type="primary"
@click="handleValidateButtonClick()"
>
保存
</n-button>
</div>
</n-form>
<n-form
v-if="isShowFormProvider == 'microsoft'"
ref="formProvider"
class="provider-form-microsoft"
:model="modelProviderApp"
:rules="rules"
label-placement="left"
label-align="left"
label-width="80"
>
<n-form-item label="Microsoft" path="switchValue">
<div class="provider-form-item">
<n-switch v-model:value="modelProviderApp.switchValue"></n-switch>
</div>
</n-form-item>
<n-form-item path="id" label="应用ID">
<n-input
v-model:value="modelProviderApp.id"
@keydown.enter.prevent
/>
</n-form-item>
<n-form-item path="password" label="应用密钥">
<n-input
v-model:value="modelProviderApp.password"
@keydown.enter.prevent
/>
</n-form-item>
<n-form-item>
<p>
若要完成设置请在您的 Facebook 应用配置中添加此 OAuth 重定向
URI
<n-button
text
tag="a"
href="https://firebase.google.com/docs/auth/?hl=zh&authuser=0&_gl=1*r9xise*_ga*MjEyMzg3MjAyNi4xNjkyNTM0MjU4*_ga_CW55HF8NVT*MTY5MzU2MzM0My4xMS4wLjE2OTM1NjMzNTAuMC4wLjA."
target="_blank"
type="primary"
>
了解详情
</n-button>
</p>
</n-form-item>
<div class="provider-btn">
<n-button secondary round @click="handleCloseButtonClick()">
取消
</n-button>
<n-button
secondary
round
type="primary"
@click="handleValidateButtonClick()"
>
保存
</n-button>
</div>
</n-form>
<n-form
v-if="isShowFormProvider == 'github'"
ref="formProvider"
class="provider-form-github"
:model="modelProviderApp"
:rules="rules"
label-placement="left"
label-align="left"
label-width="80"
>
<n-form-item label="GitHub" path="switchValue">
<div class="provider-form-item">
<n-switch v-model:value="modelProviderApp.switchValue"></n-switch>
</div>
</n-form-item>
<n-form-item path="id" label="应用ID">
<n-input
v-model:value="modelProviderApp.id"
@keydown.enter.prevent
/>
</n-form-item>
<n-form-item path="password" label="应用密钥">
<n-input
v-model:value="modelProviderApp.password"
@keydown.enter.prevent
/>
</n-form-item>
<n-form-item>
<p>
若要完成设置请在您的 Facebook 应用配置中添加此 OAuth 重定向
URI
<n-button
text
tag="a"
href="https://firebase.google.com/docs/auth/?hl=zh&authuser=0&_gl=1*r9xise*_ga*MjEyMzg3MjAyNi4xNjkyNTM0MjU4*_ga_CW55HF8NVT*MTY5MzU2MzM0My4xMS4wLjE2OTM1NjMzNTAuMC4wLjA."
target="_blank"
type="primary"
>
了解详情
</n-button>
</p>
</n-form-item>
<div class="provider-btn">
<n-button secondary round @click="handleCloseButtonClick()">
取消
</n-button>
<n-button
secondary
round
type="primary"
@click="handleValidateButtonClick()"
>
保存
</n-button>
</div>
</n-form>
</div>
<div v-show="!isShowForm" class="provider-headline">添加登录提供方</div>
<div v-show="!isShowForm">
<n-grid cols="1 650:4">
<n-grid-item>
<div class="provider-col">
<div class="provider-title">原生提供方</div>
<ul class="provider-ul">
<li @click="onClickProvider('email')">
<div class="provider-tile">
<div class="provider-name-group">
<n-icon
class="provider-icon"
size="20"
:component="MailOutline"
/>
<div class="provider-name-text">电子邮件/密码</div>
</div>
</div>
</li>
<li @click="onClickProvider('password')">
<div class="provider-tile">
<div class="provider-name-group">
<n-icon
class="provider-icon"
size="20"
:component="KeyOutline"
/>
<div class="provider-name-text">账号/密码</div>
</div>
</div>
</li>
<li @click="onClickProvider('person')">
<div class="provider-tile">
<div class="provider-name-group">
<n-icon
class="provider-icon"
size="20"
:component="PersonCircleOutline"
/>
<div class="provider-name-text">游客访问</div>
</div>
</div>
</li>
</ul>
</div>
</n-grid-item>
<n-grid-item>
<div class="provider-col">
<div class="provider-title">国内提供方</div>
<ul class="provider-ul">
<li @click="onClickProvider('wechat')">
<div class="provider-tile">
<div class="provider-name-group">
<div class="provider-icon-svg">
<img :src="wechat" alt="wechat" />
</div>
<div class="provider-name-text">微信</div>
</div>
</div>
</li>
<li @click="onClickProvider('alipay')">
<div class="provider-tile">
<div class="provider-name-group">
<n-icon
class="provider-icon"
size="20"
:component="LogoAlipay"
color="#1677ff"
/>
<div class="provider-name-text">支付宝</div>
</div>
</div>
</li>
</ul>
<n-grid-item :span="0.8" class="p-2">
<div class="leading-8">国内提供方</div>
<div class="flex flex-col space-y-2">
<n-button
v-for="(item, index) in DomesticProvider"
:key="index"
:disabled="item.disabled"
class="w-full justify-start"
@click="onClickProvider(item.provider)"
>
<template #icon>
<n-icon v-if="item.icon" size="20" :component="item.icon" />
<img v-if="item.image" :src="item.image" />
</template>
{{ item.label }}
</n-button>
</div>
</n-grid-item>
<n-grid-item :span="2">
<div class="provider-col last">
<div class="provider-title">其他提供方</div>
<ul class="provider-ul other">
<li @click="onClickProvider('google')">
<div class="provider-tile">
<div class="provider-name-group">
<div class="provider-icon-svg provider-google">
<img :src="google" alt="google" />
</div>
<div class="provider-name-text">Google</div>
</div>
</div>
</li>
<li @click="onClickProvider('facebook')">
<div class="provider-tile">
<div class="provider-name-group">
<n-icon
class="provider-icon"
size="20"
:component="LogoFacebook"
color="#1977f3"
/>
<div class="provider-name-text">Facebook</div>
</div>
</div>
</li>
<li @click="onClickProvider('microsoft')">
<div class="provider-tile">
<div class="provider-name-group">
<div class="provider-icon-svg provider-microsoft">
<img :src="microsoft" alt="Microsoft" />
</div>
<div class="provider-name-text">Microsoft</div>
</div>
</div>
</li>
<li @click="onClickProvider('github')">
<div class="provider-tile">
<div class="provider-name-group">
<n-icon
class="provider-icon"
size="20"
:component="LogoGithub"
/>
<div class="provider-name-text">GitHub</div>
</div>
</div>
</li>
</ul>
<n-grid-item :span="2" class="p-2">
<div class="leading-8">其他提供方</div>
<div class="flex flex-row flex-wrap justify-between">
<n-button
v-for="(item, index) in OtherProvider"
:key="index"
:disabled="item.disabled"
class="w-1/2 justify-start mb-2"
@click="onClickProvider(item.provider)"
>
<template #icon>
<img v-if="item.image" :src="item.image" width="24" />
</template>
{{ item.label }}
</n-button>
</div>
</n-grid-item>
</n-grid>
</div>
</n-card>
<n-card v-show="isShowList">
<div class="provider-list">
<div class="btn">
<n-button type="info" @click="isShowList = false"
>添加新提供方</n-button
>
<div class="flex flex-col">
<div class="flex justify-end p-2 pr-0">
<n-button @click="isShowList = false"> 添加新提供方 </n-button>
</div>
<n-data-table :columns="columns" :data="data" />
<n-data-table
:columns="[
{ title: '提供方', key: 'provider' },
{ title: '状态', key: 'status' },
]"
:data="data"
/>
</div>
</n-card>
</n-layout>
</template>
<style scoped>
.provider-tile {
align-items: center;
border-radius: 8px;
box-sizing: border-box;
display: flex;
height: 52px;
justify-content: space-between;
max-height: 52px;
min-width: 120px;
padding: 4px 12px;
width: 100%;
border: 1px solid #041e491a;
cursor: pointer;
}
.provider-tile:hover {
background-color: #f5f5f5;
border: 1px solid rgb(0 0 0 / 12%);
}
.provider-name-group {
font-size: 14px;
line-height: 20px;
align-items: center;
display: flex;
}
.provider-name-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.provider-ul li {
padding: 6px;
box-sizing: border-box;
flex: 1 1 100%;
}
.provider-ul {
align-items: center;
display: flex;
flex-flow: row wrap;
list-style-type: none;
justify-content: flex-start;
margin: 0;
padding: 0;
}
.provider-ul.other li {
flex: 1 1 50%;
max-width: none;
}
.provider-title {
font-size: 14px;
line-height: 20px;
font-weight: 500;
color: #000000de;
padding: 12px 8px;
}
.provider-headline {
font-size: 20px;
line-height: 28px;
font-weight: 400;
color: #000000de;
margin: 0 12px 32px;
}
.provider-col {
border-right: 1px solid #0000001f;
flex: 1 1 0;
padding: 0 4px;
}
.provider-col.last {
border-right: 0;
}
.provider-icon {
margin-right: 10px;
}
.provider-form {
margin: auto;
margin-bottom: 32px;
margin-top: 32px;
max-width: 36em;
}
.provider-form-item {
display: flex;
justify-content: flex-end;
width: 100%;
}
.provider-btn {
display: flex;
justify-content: flex-end;
}
.provider-btn .n-button {
margin-left: 10px;
}
.provider-btn .n-button--default-type {
background-color: rgba(46, 51, 56, 0.05);
}
.provider-btn .n-button--default-type:hover {
background-color: rgba(46, 51, 56, 0.09);
}
.provider-btn .n-button--primary-type {
background-color: rgba(24, 160, 88, 0.16);
}
.provider-btn .n-button--primary-type:hover {
background-color: rgba(24, 160, 88, 0.22);
}
.provider-list .btn {
display: flex;
justify-content: flex-end;
margin-bottom: 20px;
}
.provider-list .n-button--info-type {
background-color: #2080f0;
}
.provider-list .n-button--info-type:hover {
background-color: #4098fc;
}
.provider-icon-svg {
height: 1em;
width: 1.5em;
line-height: 1em;
text-align: center;
display: inline-block;
position: relative;
fill: currentColor;
transform: translateZ(0);
margin-right: 10px;
}
.provider-microsoft {
width: 1em;
}
.provider-google {
height: 1.5em;
}
@media only screen and (max-width: 1100px) {
.provider-col {
border-right: 0;
}
}
</style>