refactor: 个人自用,移除登录与云同步全链路
站点只给本人用,云乐坊 SSO 授权、收藏/历史云同步、获客归因和账号切换记账都没有收益,却被登录状态检查和同步失败提示持续打扰。 - 删除 useYunlefunAuth / yunlefunAuth / yunlefunSsoConfig / yunlefunAuth 适配器、useUserDataSync / userDataSync / userData 适配器、三个 client 插件与 /auth/callback 回调页 - 抽出 adapters/cloudbase.ts,让「反馈一下」和匿名筛选信号不再依赖登录态;cook-feedback 云函数保留 - 删除 cook-user-data 云函数与 cook_user_data 权限规则,移除 @yunlefun/sso 依赖 - 「我的」页删掉登录按钮、账号卡、四个统计格和退出登录;「关于」页删掉项目作者、致谢名单和上游宣传链接 - 本地收藏/历史与导出导入保留,删除同步专用的 lastUid 记账 取舍见 docs/decisions/0005-drop-login-and-sync.md
This commit is contained in:
@@ -1,116 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import type { PersonalAcknowledgement } from '~/constants/acknowledgements'
|
||||
import { acknowledgements, personalAcknowledgements } from '~/constants/acknowledgements'
|
||||
|
||||
// 图标映射表(提取为常量以提升性能)
|
||||
const ICON_MAP: Record<string, string> = {
|
||||
github: 'i-ri-github-line',
|
||||
bilibili: 'i-ri-bilibili-line',
|
||||
weibo: 'i-ri-weibo-line',
|
||||
twitter: 'i-ri-twitter-x-line',
|
||||
wechat: 'i-ri-wechat-2-line',
|
||||
blog: 'i-ri-article-line',
|
||||
website: 'i-ri-global-line',
|
||||
email: 'i-ri-mail-line',
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据链接类型返回对应的图标类名
|
||||
*/
|
||||
function getIconClass(type?: string): string {
|
||||
return ICON_MAP[type || 'website'] || 'i-ri-links-line'
|
||||
}
|
||||
|
||||
function getLinkKey(ackIndex: number, linkIndex: number): string {
|
||||
return `link-${ackIndex}-${linkIndex}`
|
||||
}
|
||||
|
||||
function getPersonKey(person: PersonalAcknowledgement, index: number): string {
|
||||
return person.link ? `${person.name}-${person.link}` : `${person.name}-${index}`
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button default-href="/about" />
|
||||
</ion-buttons>
|
||||
<ion-title>致谢</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<!-- 个人致谢名单 -->
|
||||
<ion-list-header>
|
||||
<ion-label class="text-sm op-50">
|
||||
感谢以下朋友在项目早期的支持与帮助
|
||||
</ion-label>
|
||||
</ion-list-header>
|
||||
<ion-list v-if="personalAcknowledgements.length > 0" :inset="true">
|
||||
<!-- 使用 ion-item 展示每个个人 -->
|
||||
<ion-item
|
||||
v-for="(person, index) in personalAcknowledgements"
|
||||
:key="getPersonKey(person, index)"
|
||||
:href="person.link"
|
||||
:target="person.link ? '_blank' : undefined"
|
||||
:button="!!person.link"
|
||||
:detail="!!person.link"
|
||||
lines="full"
|
||||
>
|
||||
<div slot="start" class="h-6 w-6 inline-flex items-center justify-center text-5 color-[var(--ion-color-medium)]" i-ri-user-3-line />
|
||||
<ion-label>
|
||||
<h3 class="m-0 text-[17px] color-[var(--ion-text-color)] font-normal">
|
||||
{{ person.name }}
|
||||
</h3>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<!-- 团队/组织致谢 -->
|
||||
<template v-for="(ack, index) in acknowledgements" :key="index">
|
||||
<ion-list-header>
|
||||
<ion-label class="tracking-wide uppercase opacity-50 text-[13px]! font-medium!">
|
||||
{{ ack.description }}
|
||||
</ion-label>
|
||||
</ion-list-header>
|
||||
<ion-list :inset="true">
|
||||
<!-- 链接列表 -->
|
||||
<ion-item
|
||||
v-for="(link, linkIndex) in ack.links"
|
||||
:key="getLinkKey(index, linkIndex)"
|
||||
:href="link.href"
|
||||
:target="link.target || '_blank'"
|
||||
:detail="true"
|
||||
button
|
||||
>
|
||||
<div v-if="link.type" slot="start" class="inline-flex" :class="getIconClass(link.type)" />
|
||||
<ion-label>{{ link.label }}</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</template>
|
||||
|
||||
<!-- 底部说明 -->
|
||||
<div class="px-4 pb-8 pt-4">
|
||||
<p class="m-0 text-center text-[13px] leading-[1.4] opacity-50">
|
||||
感谢所有支持和帮助过本项目的人们 ❤️
|
||||
</p>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
ion-list-header {
|
||||
ion-label {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
ion-list {
|
||||
margin-top: 8px !important;
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { isClient } from '@vueuse/core'
|
||||
import pkg from '~/../package.json'
|
||||
import { icp, links } from '~/constants'
|
||||
import { icp } from '~/constants'
|
||||
|
||||
const displayICP = ref(true)
|
||||
|
||||
@@ -52,14 +52,7 @@ onBeforeMount(() => {
|
||||
<div class="label">
|
||||
<b>Commit Hash</b>
|
||||
</div>
|
||||
<a
|
||||
class="value"
|
||||
:href="`https://github.com/YunYouJun/cook/commit/${commitSha}`"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
{{ commitSha }}
|
||||
</a>
|
||||
<span class="value">{{ commitSha }}</span>
|
||||
</div>
|
||||
<div v-if="displayICP" class="ledger-setting-row">
|
||||
<div class="label">
|
||||
@@ -74,13 +67,12 @@ onBeforeMount(() => {
|
||||
|
||||
<section class="ledger-section">
|
||||
<div class="ledger-section-head">
|
||||
<h2>项目</h2>
|
||||
<h2>数据来源</h2>
|
||||
</div>
|
||||
<div class="ledger-menu">
|
||||
<a href="https://www.bilibili.com/blackboard/dynamic/306882" target="_blank" rel="noopener">
|
||||
<span class="ico"><ion-icon :icon="ioniconsPlayOutline" aria-hidden="true" /></span>
|
||||
<span class="label">数据来源</span>
|
||||
<span class="value">哔哩哔哩</span>
|
||||
<span class="label">哔哩哔哩</span>
|
||||
<span class="chev"><ion-icon :icon="ioniconsChevronForwardOutline" aria-hidden="true" /></span>
|
||||
</a>
|
||||
<a href="https://github.com/YunYouJun/cook" target="_blank" rel="noopener">
|
||||
@@ -89,65 +81,48 @@ onBeforeMount(() => {
|
||||
<span class="value">GitHub</span>
|
||||
<span class="chev"><ion-icon :icon="ioniconsChevronForwardOutline" aria-hidden="true" /></span>
|
||||
</a>
|
||||
<NuxtLink to="/about/me">
|
||||
<span class="ico"><ion-icon :icon="ioniconsPersonOutline" aria-hidden="true" /></span>
|
||||
<span class="label">项目作者</span>
|
||||
<span class="value">云游君</span>
|
||||
<span class="chev"><ion-icon :icon="ioniconsChevronForwardOutline" aria-hidden="true" /></span>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/about/acknowledgements">
|
||||
<span class="ico"><ion-icon :icon="ioniconsHeartOutline" aria-hidden="true" /></span>
|
||||
<span class="label">致谢名单</span>
|
||||
<span class="chev"><ion-icon :icon="ioniconsChevronForwardOutline" aria-hidden="true" /></span>
|
||||
</NuxtLink>
|
||||
<a :href="links.cook" target="_blank" rel="noopener">
|
||||
<span class="ico"><ion-icon :icon="ioniconsGlobeOutline" aria-hidden="true" /></span>
|
||||
<span class="label">网页版本</span>
|
||||
<span class="value">cook.yunyoujun.cn</span>
|
||||
<span class="chev"><ion-icon :icon="ioniconsChevronForwardOutline" aria-hidden="true" /></span>
|
||||
</a>
|
||||
<a :href="links.yyj.bilibiliOpus" target="_blank" rel="noopener">
|
||||
<span class="ico"><ion-icon :icon="ioniconsMicOutline" aria-hidden="true" /></span>
|
||||
<span class="label">旅程的起点</span>
|
||||
<span class="value">动态</span>
|
||||
<span class="chev"><ion-icon :icon="ioniconsChevronForwardOutline" aria-hidden="true" /></span>
|
||||
</a>
|
||||
<a :href="links.yyj.mpArticle" target="_blank" rel="noopener">
|
||||
<span class="ico"><ion-icon :icon="ioniconsDocumentTextOutline" aria-hidden="true" /></span>
|
||||
<span class="label">关于食用手册的前世今生</span>
|
||||
<span class="value">文章</span>
|
||||
<span class="chev"><ion-icon :icon="ioniconsChevronForwardOutline" aria-hidden="true" /></span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ledger-mobile-only">
|
||||
<TheAboutList />
|
||||
<ion-list :inset="true">
|
||||
<ion-item>
|
||||
<ion-label>当前版本</ion-label>
|
||||
<ion-text>v{{ pkg.version }}</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>构建时间</ion-label>
|
||||
<ion-text>{{ buildDate }}</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ion-item v-if="commitSha" :href="`https://github.com/YunYouJun/cook/commit/${commitSha}`" target="_blank">
|
||||
<ion-label>Commit Hash</ion-label>
|
||||
<ion-text>{{ commitSha }}</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ion-item v-if="displayICP" href="https://beian.miit.gov.cn/" target="_blank">
|
||||
<ion-label>备案号</ion-label>
|
||||
<ion-text>{{ icp }}</ion-text>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list :inset="true">
|
||||
<ion-item :href="links.cook" target="_blank">
|
||||
<ion-label>网页版本</ion-label>
|
||||
<ion-text class="inline-flex items-center justify-center">
|
||||
<div class="inline-flex" i-ri-global-line />
|
||||
<span m="l-1" class="inline-flex">cook.yunyoujun.cn</span>
|
||||
</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ion-item :href="links.yyj.bilibiliOpus" target="_blank">
|
||||
<ion-label>旅程的起点</ion-label>
|
||||
<ion-item href="https://www.bilibili.com/blackboard/dynamic/306882" target="_blank">
|
||||
<ion-label>数据来源</ion-label>
|
||||
<ion-text class="inline-flex items-center justify-center">
|
||||
<div class="inline-flex" i-ri-bilibili-line />
|
||||
<span m="l-1" class="inline-flex">动态</span>
|
||||
<span m="l-1" class="inline-flex">哔哩哔哩</span>
|
||||
</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ion-item :href="links.yyj.mpArticle" target="_blank">
|
||||
<ion-label>关于食用手册的前世今生</ion-label>
|
||||
<ion-item href="https://github.com/YunYouJun/cook" target="_blank">
|
||||
<ion-label>开源代码</ion-label>
|
||||
<ion-text class="inline-flex items-center justify-center">
|
||||
<div class="inline-flex" i-ri-wechat-2-line />
|
||||
<span m="l-1" class="inline-flex">文章</span>
|
||||
<div class="inline-flex" i-ri-github-line />
|
||||
<span m="l-1" class="inline-flex">GitHub</span>
|
||||
</ion-text>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { links } from '~/constants'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button default-href="/my" />
|
||||
</ion-buttons>
|
||||
<ion-title>关于作者</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-list :inset="true">
|
||||
<ion-item :href="links.yyj.bilibili" target="_blank">
|
||||
<div slot="start" class="inline-flex" i-ri-bilibili-line />
|
||||
<ion-label>哔哩哔哩</ion-label>
|
||||
<ion-text class="inline-flex items-center justify-center">
|
||||
<span m="l-1" class="inline-flex">云游君</span>
|
||||
</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ion-item :href="links.yyj.github" target="_blank">
|
||||
<div slot="start" class="inline-flex" i-ri-github-line />
|
||||
<ion-label>GitHub</ion-label>
|
||||
<ion-text class="inline-flex items-center justify-center">
|
||||
<span m="l-1" class="inline-flex">YunYouJun</span>
|
||||
</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ion-item :href="links.yyj.blog" target="_blank">
|
||||
<div slot="start" class="inline-flex" i-ri-article-line />
|
||||
<ion-label>博客</ion-label>
|
||||
<ion-text class="inline-flex items-center justify-center">
|
||||
云游君的小站
|
||||
</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ion-item :href="links.yyj.mp" target="_blank">
|
||||
<div slot="start" class="inline-flex" i-ri-wechat-2-line />
|
||||
<ion-label>公众号</ion-label>
|
||||
<ion-text class="inline-flex items-center justify-center">
|
||||
云游君
|
||||
</ion-text>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
@@ -1,51 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
const {
|
||||
configurationMessage,
|
||||
errorMessage,
|
||||
initialize,
|
||||
status,
|
||||
} = useYunlefunAuth()
|
||||
|
||||
onMounted(() => {
|
||||
void initialize()
|
||||
})
|
||||
|
||||
const message = computed(() => configurationMessage.value
|
||||
|| errorMessage.value
|
||||
|| (status.value === 'signed-in'
|
||||
? '登录成功,正在返回'
|
||||
: status.value === 'error'
|
||||
? '登录未完成,请返回后重试'
|
||||
: '正在验证云乐坊授权'))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>登录授权</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-list :inset="true">
|
||||
<ion-item>
|
||||
<ion-spinner
|
||||
v-if="status === 'idle' || status === 'checking' || status === 'signing-in'"
|
||||
slot="start"
|
||||
name="crescent"
|
||||
/>
|
||||
<ion-icon
|
||||
v-else
|
||||
slot="start"
|
||||
:color="status === 'signed-in' ? 'success' : 'danger'"
|
||||
:icon="status === 'signed-in' ? ioniconsCheckmarkCircleOutline : ioniconsAlertCircleOutline"
|
||||
/>
|
||||
<ion-label class="ion-text-wrap">
|
||||
{{ message }}
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
@@ -21,7 +21,7 @@ const faqs = [
|
||||
},
|
||||
{
|
||||
q: '收藏和历史存在哪?',
|
||||
a: '存在这台设备的浏览器本地存储里,不上传服务器。换个浏览器或清了浏览器数据就没了。登录后可以同步到你的云乐坊账号。',
|
||||
a: '存在这台设备的浏览器本地存储里,不上传服务器。换个浏览器或清了浏览器数据就没了,可以在设置页导出后再导入到另一台设备。',
|
||||
},
|
||||
{
|
||||
q: '菜谱里的用量和调味在哪看?',
|
||||
|
||||
@@ -292,7 +292,7 @@ async function importFromPaste(): Promise<void> {
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
<p class="cook-group-footer">
|
||||
导入会和本机已有数据合并,不会覆盖。登录云乐坊账号后,收藏和历史会自动同步。
|
||||
导入会和本机已有数据合并,不会覆盖。收藏和历史只存在这台设备上,换设备或清了浏览器数据就没了,可以先导出再导入。
|
||||
</p>
|
||||
<input
|
||||
ref="importInput"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
import dayjs from 'dayjs'
|
||||
import { customRecipes } from '~/composables/store/customRecipe'
|
||||
import { favoriteEntries } from '~/composables/store/favorite'
|
||||
import { recipeHistories } from '~/composables/store/history'
|
||||
@@ -9,60 +8,14 @@ definePageMeta({
|
||||
alias: ['/my'],
|
||||
})
|
||||
|
||||
const {
|
||||
account,
|
||||
configurationMessage,
|
||||
errorMessage,
|
||||
isAuthenticated,
|
||||
signIn,
|
||||
signOut,
|
||||
status,
|
||||
} = useYunlefunAuth()
|
||||
|
||||
const authBusy = computed(() => status.value === 'checking' || status.value === 'signing-in')
|
||||
|
||||
const {
|
||||
errorMessage: syncErrorMessage,
|
||||
lastSyncedAt,
|
||||
status: syncStatus,
|
||||
syncNow,
|
||||
} = useUserDataSync()
|
||||
|
||||
const syncText = computed(() => {
|
||||
switch (syncStatus.value) {
|
||||
case 'syncing':
|
||||
return '正在同步…'
|
||||
case 'synced':
|
||||
return `已同步 ${dayjs(lastSyncedAt.value).format('HH:mm')}`
|
||||
case 'error':
|
||||
return `${syncErrorMessage.value},点击重试`
|
||||
default:
|
||||
return '等待同步'
|
||||
}
|
||||
})
|
||||
|
||||
const rStore = useRecipeStore()
|
||||
|
||||
const favCount = computed(() => favoriteEntries.value.length)
|
||||
const historyCount = computed(() => recipeHistories.value.length)
|
||||
const mineCount = computed(() => customRecipes.value.length)
|
||||
const syncedText = computed(() => lastSyncedAt.value ? dayjs(lastSyncedAt.value).format('MM-DD HH:mm') : '—')
|
||||
const pantryText = computed(() => rStore.selectedPantry.join('、') || '无')
|
||||
const avoidText = computed(() => rStore.selectedAvoid.join('、') || '无')
|
||||
const spicyText = computed(() => rStore.noSpicy ? '开' : '关')
|
||||
|
||||
function handleSyncClick(): void {
|
||||
if (syncStatus.value === 'error')
|
||||
syncNow()
|
||||
}
|
||||
|
||||
async function handleSignIn(): Promise<void> {
|
||||
await signIn()
|
||||
}
|
||||
|
||||
async function handleSignOut(): Promise<void> {
|
||||
await signOut()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -83,66 +36,13 @@ async function handleSignOut(): Promise<void> {
|
||||
</ion-header>
|
||||
|
||||
<div class="ledger-desktop-block">
|
||||
<PageHead title="我的" subtitle="收藏、历史和自己记的菜谱都在这儿">
|
||||
<button
|
||||
v-if="!isAuthenticated"
|
||||
type="button"
|
||||
class="ledger-btn is-ghost is-sm"
|
||||
:disabled="authBusy || Boolean(configurationMessage)"
|
||||
@click="handleSignIn"
|
||||
>
|
||||
<ion-icon :icon="ioniconsLogInOutline" aria-hidden="true" />
|
||||
<span>{{ authBusy ? '检查中…' : '登录' }}</span>
|
||||
</button>
|
||||
</PageHead>
|
||||
|
||||
<section class="ledger-section">
|
||||
<div class="ledger-account">
|
||||
<span class="avatar">
|
||||
<img v-if="account?.avatarUrl" :alt="account.displayName" :src="account.avatarUrl">
|
||||
<ion-icon v-else :icon="ioniconsPersonCircle" aria-hidden="true" />
|
||||
</span>
|
||||
<div class="ledger-account-info">
|
||||
<b>{{ account?.displayName ?? '未登录' }}</b>
|
||||
<small>{{ isAuthenticated ? '云乐坊账号' : '登录后可以同步收藏和历史' }}</small>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="ledger-btn is-ghost is-sm"
|
||||
:disabled="!isAuthenticated || syncStatus === 'syncing'"
|
||||
@click="handleSyncClick"
|
||||
>
|
||||
<ion-icon :icon="ioniconsCloudDoneOutline" aria-hidden="true" />
|
||||
<span>{{ syncStatus === 'syncing' ? '同步中' : '同步' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="ledger-section">
|
||||
<div class="ledger-stat-grid">
|
||||
<div class="ledger-stat">
|
||||
<span>收藏</span>
|
||||
<b>{{ favCount }}</b>
|
||||
</div>
|
||||
<div class="ledger-stat">
|
||||
<span>浏览历史</span>
|
||||
<b>{{ historyCount }}</b>
|
||||
</div>
|
||||
<div class="ledger-stat">
|
||||
<span>我的菜谱</span>
|
||||
<b>{{ mineCount }}</b>
|
||||
</div>
|
||||
<div class="ledger-stat">
|
||||
<span>上次同步</span>
|
||||
<b>{{ syncedText }}</b>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<PageHead title="我的" subtitle="收藏、历史和自己记的菜谱都在这儿" />
|
||||
|
||||
<div class="ledger-menu-grid">
|
||||
<section class="ledger-section">
|
||||
<div class="ledger-section-head">
|
||||
<h2>我的菜谱</h2>
|
||||
<span class="hint">共 {{ favCount + historyCount + mineCount }} 条记录</span>
|
||||
</div>
|
||||
<div class="ledger-menu">
|
||||
<NuxtLink to="/recipes/favorites">
|
||||
@@ -220,69 +120,9 @@ async function handleSignOut(): Promise<void> {
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section v-if="isAuthenticated" class="ledger-section">
|
||||
<button type="button" class="ledger-btn is-ghost" @click="handleSignOut">
|
||||
退出登录
|
||||
</button>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="ledger-mobile-only">
|
||||
<ion-list :inset="true">
|
||||
<ion-item v-if="isAuthenticated && account" class="my-account" lines="full">
|
||||
<ion-avatar v-if="account.avatarUrl" slot="start">
|
||||
<img :alt="account.displayName" :src="account.avatarUrl">
|
||||
</ion-avatar>
|
||||
<ion-icon v-else slot="start" class="my-account-placeholder" :icon="ioniconsPersonCircle" />
|
||||
<ion-label>
|
||||
<h2>{{ account.displayName }}</h2>
|
||||
<p>云乐坊账号</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item
|
||||
v-if="isAuthenticated"
|
||||
:button="syncStatus === 'error'"
|
||||
:detail="false"
|
||||
@click="handleSyncClick"
|
||||
>
|
||||
<span v-if="syncStatus === 'syncing'" slot="start" class="my-sync-spinner">
|
||||
<ion-spinner name="crescent" />
|
||||
</span>
|
||||
<CookListIcon
|
||||
v-else
|
||||
slot="start"
|
||||
:icon="syncStatus === 'error' ? ioniconsCloudOfflineOutline : ioniconsCloudDoneOutline"
|
||||
:color="syncStatus === 'error' ? '#ff3b30' : '#34c759'"
|
||||
/>
|
||||
<ion-label>
|
||||
<h2>收藏和历史云同步</h2>
|
||||
<p>{{ syncText }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item
|
||||
v-if="!isAuthenticated"
|
||||
:button="true"
|
||||
:disabled="authBusy || Boolean(configurationMessage)"
|
||||
@click="handleSignIn"
|
||||
>
|
||||
<span v-if="authBusy" slot="start" class="my-sync-spinner">
|
||||
<ion-spinner name="crescent" />
|
||||
</span>
|
||||
<CookListIcon v-else slot="start" :icon="ioniconsLogInOutline" color="#007aff" />
|
||||
<ion-label>
|
||||
<h2>{{ authBusy ? '正在检查登录状态' : '使用云乐坊账号登录' }}</h2>
|
||||
<p>安全授权,无需在 Cook 输入密码</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item v-if="configurationMessage || errorMessage" lines="none">
|
||||
<ion-icon slot="start" color="danger" :icon="ioniconsAlertCircleOutline" />
|
||||
<ion-label class="ion-text-wrap" color="danger">
|
||||
{{ configurationMessage || errorMessage }}
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list :inset="true">
|
||||
<ion-item router-link="/recipes/history">
|
||||
<CookListIcon slot="start" :icon="ioniconsTimeOutline" color="#5856d6" />
|
||||
@@ -337,42 +177,7 @@ async function handleSignOut(): Promise<void> {
|
||||
<ion-label>关于</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list v-if="isAuthenticated" :inset="true">
|
||||
<ion-item :button="true" :detail="false" :disabled="authBusy" @click="handleSignOut">
|
||||
<ion-label class="ion-text-center" color="danger">
|
||||
退出登录
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.my-account {
|
||||
--padding-top: 6px;
|
||||
--padding-bottom: 6px;
|
||||
}
|
||||
.my-account ion-avatar {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin-inline-end: 14px;
|
||||
}
|
||||
.my-account-placeholder {
|
||||
font-size: 56px;
|
||||
margin-inline-end: 14px;
|
||||
color: var(--ion-color-medium);
|
||||
}
|
||||
.my-account h2 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.my-sync-spinner {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
width: 29px;
|
||||
margin-inline-end: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user