fix(ui): finalize visual contracts and map toolbar
This commit is contained in:
@@ -78,7 +78,8 @@ Hero 同时包含左侧介绍和右侧状态卡时,使用 `oc-page-hero__split
|
||||
- `oc-section-label`:详情面板中的字段标题。
|
||||
- `oc-stat-label` / `oc-stat-value`:统计数据的标签和值。
|
||||
- `oc-inset-panel`:详情中的浅色信息块。
|
||||
- `oc-panel-card` / `oc-panel-card-soft`:Naive UI 卡片的硬阴影。
|
||||
- `oc-panel-card` / `oc-panel-card-soft` / `oc-panel-card-xl`:普通、柔和和大型卡片的硬阴影。
|
||||
- `oc-floating-panel` / `oc-modal-shell`:浮动菜单与普通方形弹窗的共享表面。
|
||||
- `oc-surface`:普通 HTML 容器的标准白色表面。
|
||||
- `oc-empty-card`:空状态表面。
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ watch(() => props.initialValue, value => {
|
||||
<textarea
|
||||
v-model="form.description"
|
||||
rows="4"
|
||||
class="w-full resize-none border border-slate-300 px-3 py-2.5 text-sm focus:border-sky-500 focus:outline-none focus:ring-2 focus:ring-sky-500"
|
||||
class="oc-field-control resize-none"
|
||||
placeholder="描述一下这张图片..."
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
@@ -181,13 +181,13 @@ onBeforeUnmount(() => {
|
||||
@click="close"
|
||||
>
|
||||
<div
|
||||
class="image-detail-shell relative w-fit max-w-[92vw] overflow-hidden rounded-[30px] shadow-2xl"
|
||||
class="image-detail-shell relative w-fit max-w-[92vw] overflow-hidden shadow-2xl"
|
||||
@click.stop
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
@click="close"
|
||||
class="image-detail-close-button oc-overlay-button absolute right-4 top-4 z-30 h-10 w-10 rounded-full [&_svg]:stroke-[2.5]"
|
||||
class="image-detail-close-button oc-overlay-button absolute right-4 top-4 z-30 h-10 w-10 [&_svg]:stroke-[2.5]"
|
||||
aria-label="关闭大图"
|
||||
title="关闭大图"
|
||||
>
|
||||
@@ -223,7 +223,7 @@ onBeforeUnmount(() => {
|
||||
<button
|
||||
type="button"
|
||||
@click="toggleInfo"
|
||||
class="oc-overlay-button absolute bottom-4 right-4 z-30 h-11 w-11 rounded-full drop-shadow-[0_2px_8px_rgba(15,23,42,0.9)]"
|
||||
class="image-detail-info-button oc-overlay-button absolute bottom-4 right-4 z-30 h-11 w-11 drop-shadow-[0_2px_8px_rgba(15,23,42,0.9)]"
|
||||
:aria-label="infoOpen ? '隐藏详细信息' : '查看详细信息'"
|
||||
:title="infoOpen ? '隐藏详细信息' : '查看详细信息'"
|
||||
>
|
||||
@@ -242,7 +242,7 @@ onBeforeUnmount(() => {
|
||||
<h2 class="text-xl font-bold text-slate-900">{{ title }}</h2>
|
||||
<span
|
||||
v-if="badgeLabel"
|
||||
class="rounded-full border px-3 py-1 text-xs font-medium"
|
||||
class="border px-3 py-1 text-xs font-medium"
|
||||
:class="badgeClass"
|
||||
>
|
||||
{{ badgeLabel }}
|
||||
@@ -254,7 +254,7 @@ onBeforeUnmount(() => {
|
||||
<button
|
||||
type="button"
|
||||
@click="infoOpen = false"
|
||||
class="oc-icon-button oc-icon-button--small absolute right-3 top-3 rounded-full"
|
||||
class="image-detail-panel-close oc-icon-button oc-icon-button--small absolute right-3 top-3"
|
||||
aria-label="隐藏详细信息"
|
||||
title="隐藏详细信息"
|
||||
>
|
||||
@@ -301,7 +301,13 @@ onBeforeUnmount(() => {
|
||||
transform: translateY(10px) scale(0.97);
|
||||
}
|
||||
|
||||
.image-detail-close-button.image-detail-close-button {
|
||||
.image-detail-shell.image-detail-shell {
|
||||
border-radius: 30px !important;
|
||||
}
|
||||
|
||||
.image-detail-close-button.image-detail-close-button,
|
||||
.image-detail-info-button.image-detail-info-button,
|
||||
.image-detail-panel-close.image-detail-panel-close {
|
||||
border-radius: 9999px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import { NIcon, NSpace } from 'naive-ui'
|
||||
import { Logout, Settings, Shield, User } from '@vicons/tabler'
|
||||
import { ChevronDown, Logout, Settings, Shield, User } from '@vicons/tabler'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { RouterLink, useRoute, useRouter } from 'vue-router'
|
||||
|
||||
@@ -138,7 +138,7 @@ async function handleLogout() {
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex h-16 items-center justify-between">
|
||||
<RouterLink to="/" class="flex items-center gap-3">
|
||||
<div class="flex h-10 w-10 items-center justify-center border border-sky-200 bg-sky-100 shadow-[4px_4px_0_0_rgba(15,23,42,0.08)]">
|
||||
<div class="oc-brand-mark">
|
||||
<svg
|
||||
class="h-8 w-8"
|
||||
viewBox="0 0 16 16"
|
||||
@@ -170,7 +170,7 @@ async function handleLogout() {
|
||||
</div>
|
||||
</RouterLink>
|
||||
|
||||
<nav class="hidden items-center gap-2 border border-slate-200 bg-white px-2 py-2 shadow-[6px_6px_0_0_rgba(15,23,42,0.05)] md:flex">
|
||||
<nav class="oc-panel-card hidden items-center gap-2 border border-slate-200 bg-white px-2 py-2 md:flex">
|
||||
<RouterLink
|
||||
to="/"
|
||||
class="oc-nav-link"
|
||||
@@ -228,7 +228,7 @@ async function handleLogout() {
|
||||
<button
|
||||
type="button"
|
||||
class="oc-header-button oc-header-button--teal max-w-[8.5rem] gap-2 md:max-w-none"
|
||||
:class="route.name === 'profile' || route.name === 'profile-settings' ? 'border-teal-200 bg-teal-50/80 text-teal-800 ring-1 ring-teal-200 shadow-[4px_4px_0_0_rgba(52,116,93,0.16)]' : ''"
|
||||
:class="route.name === 'profile' || route.name === 'profile-settings' ? 'border-teal-200 bg-teal-50/80 text-teal-800 ring-1 ring-teal-200' : ''"
|
||||
aria-haspopup="menu"
|
||||
:aria-expanded="accountCardOpen"
|
||||
>
|
||||
@@ -243,7 +243,7 @@ async function handleLogout() {
|
||||
class="absolute right-0 top-full z-50 w-72 pt-3"
|
||||
role="menu"
|
||||
>
|
||||
<div class="border border-slate-200 bg-white shadow-[8px_8px_0_0_rgba(15,23,42,0.08)]">
|
||||
<div class="oc-floating-panel border border-slate-200 bg-white">
|
||||
<div class="border-b border-slate-200 bg-[linear-gradient(180deg,#f2faf6_0%,#ffffff_100%)] px-4 py-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex h-11 w-11 shrink-0 items-center justify-center border border-teal-200 bg-[linear-gradient(135deg,#eef9f3_0%,#d9efe3_100%)] text-lg font-bold text-teal-800">
|
||||
@@ -375,10 +375,10 @@ async function handleLogout() {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="pointer-events-auto flex items-center gap-2 border border-slate-300 bg-white/94 px-3 py-1.5 text-xs font-medium tracking-[0.16em] text-slate-700 shadow-[4px_4px_0_0_rgba(15,23,42,0.08)] backdrop-blur transition-colors hover:border-teal-300 hover:bg-teal-50 hover:text-teal-900 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-600"
|
||||
class="oc-header-button oc-header-button--neutral pointer-events-auto gap-2 bg-white/94 text-xs tracking-[0.16em] backdrop-blur"
|
||||
@click="showHeader(true)"
|
||||
>
|
||||
<span>▼</span>
|
||||
<NIcon size="15"><ChevronDown /></NIcon>
|
||||
<span>展开导航</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@ export function loadAMap() {
|
||||
version: '2.0',
|
||||
plugins: [
|
||||
'AMap.Scale',
|
||||
'AMap.ToolBar',
|
||||
'AMap.ControlBar',
|
||||
'AMap.Geolocation',
|
||||
'AMap.Marker',
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ export const openCloudThemeOverrides: GlobalThemeOverrides = {
|
||||
textColor1: '#0f172a',
|
||||
textColor2: '#334155',
|
||||
textColor3: '#64748b',
|
||||
textColorDisabled: '#94a3b8',
|
||||
textColorDisabled: 'var(--oc-color-text-disabled)',
|
||||
dividerColor: '#d9e3ee',
|
||||
borderColor: '#d9e3ee',
|
||||
inputColor: '#ffffff',
|
||||
|
||||
@@ -71,6 +71,11 @@
|
||||
@apply mt-4 max-w-2xl text-sm leading-7 text-slate-600;
|
||||
}
|
||||
|
||||
.oc-brand-mark {
|
||||
@apply flex h-10 w-10 items-center justify-center border border-sky-200 bg-sky-100;
|
||||
box-shadow: var(--oc-shadow-sm);
|
||||
}
|
||||
|
||||
/* Reusable text hierarchy */
|
||||
.oc-section-label {
|
||||
@apply text-xs uppercase tracking-[0.18em] text-slate-500;
|
||||
@@ -118,6 +123,10 @@
|
||||
box-shadow: var(--oc-shadow-xl) !important;
|
||||
}
|
||||
|
||||
.oc-floating-panel {
|
||||
box-shadow: var(--oc-shadow-lg);
|
||||
}
|
||||
|
||||
.oc-panel-card-soft {
|
||||
box-shadow: 6px 6px 0 0 rgb(15 23 42 / 4%) !important;
|
||||
}
|
||||
@@ -444,7 +453,7 @@
|
||||
.oc-panel-button.n-button.n-button--disabled {
|
||||
border-color: rgb(226 232 240) !important;
|
||||
background: rgb(241 245 249) !important;
|
||||
color: rgb(148 163 184) !important;
|
||||
color: var(--oc-color-text-disabled) !important;
|
||||
box-shadow: none !important;
|
||||
opacity: 0.72;
|
||||
transform: none !important;
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
--oc-color-text: #0f172a;
|
||||
--oc-color-text-secondary: #334155;
|
||||
--oc-color-text-muted: #64748b;
|
||||
--oc-color-text-disabled: #94a3b8;
|
||||
--oc-color-border: #d9e3ee;
|
||||
--oc-color-primary: #34745d;
|
||||
--oc-color-primary-hover: #2d5f4e;
|
||||
@@ -82,6 +83,7 @@
|
||||
--oc-shadow-sky: 4px 4px 0 0 rgb(14 165 233 / 14%);
|
||||
--oc-shadow-primary: 4px 4px 0 0 rgb(52 116 93 / 14%);
|
||||
--oc-shadow-primary-hover: 5px 5px 0 0 rgb(52 116 93 / 20%);
|
||||
--oc-shadow-amber: 5px 5px 0 0 rgb(245 158 11 / 12%);
|
||||
--oc-shadow-teal: var(--oc-shadow-primary);
|
||||
|
||||
--oc-duration-fast: 160ms;
|
||||
|
||||
@@ -502,7 +502,7 @@ onMounted(loadAdminData)
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<div class="flex min-w-0 items-center gap-3">
|
||||
<span class="flex h-10 w-10 shrink-0 items-center justify-center border border-sky-200 bg-sky-50 text-sky-800 shadow-[3px_3px_0_0_rgba(14,165,233,0.12)]">
|
||||
<span class="admin-brand-icon flex h-10 w-10 shrink-0 items-center justify-center border border-sky-200 bg-sky-50 text-sky-800">
|
||||
<NIcon size="22"><Shield /></NIcon>
|
||||
</span>
|
||||
<span
|
||||
@@ -538,7 +538,7 @@ onMounted(loadAdminData)
|
||||
type="button"
|
||||
class="group relative flex min-w-[150px] items-center gap-3 overflow-hidden border px-3 py-3 text-left transition-[background-color,border-color,color,box-shadow] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-600 focus-visible:ring-offset-2 lg:w-full lg:min-w-0"
|
||||
:class="activeTab === tab.key
|
||||
? 'border-teal-200 bg-teal-50 text-teal-900 shadow-[3px_3px_0_0_rgba(52,116,93,0.16)]'
|
||||
? 'admin-control-active border-teal-200 bg-teal-50 text-teal-900'
|
||||
: 'border-transparent bg-white text-slate-600 hover:border-slate-200 hover:bg-slate-50 hover:text-slate-950'"
|
||||
:aria-current="activeTab === tab.key ? 'page' : undefined"
|
||||
:aria-label="tab.label"
|
||||
@@ -580,7 +580,7 @@ onMounted(loadAdminData)
|
||||
type="button"
|
||||
class="flex h-14 min-w-0 flex-1 items-center gap-3 overflow-hidden border px-3 py-2 text-left transition-[background-color,border-color,color,box-shadow] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-600 lg:w-full"
|
||||
:class="accountMenuOpen
|
||||
? 'border-teal-200 bg-teal-50 text-teal-800 shadow-[3px_3px_0_0_rgba(52,116,93,0.16)]'
|
||||
? 'admin-control-active border-teal-200 bg-teal-50 text-teal-800'
|
||||
: 'border-slate-200 bg-slate-50 text-slate-700 hover:border-teal-200 hover:bg-teal-50 hover:text-teal-800'"
|
||||
aria-label="打开管理员账户菜单"
|
||||
aria-haspopup="menu"
|
||||
@@ -611,7 +611,7 @@ onMounted(loadAdminData)
|
||||
</template>
|
||||
|
||||
<div
|
||||
class="w-64 border border-slate-200 bg-white shadow-[8px_8px_0_0_rgba(15,23,42,0.08)]"
|
||||
class="oc-floating-panel w-64 border border-slate-200 bg-white"
|
||||
role="menu"
|
||||
aria-label="管理员账户"
|
||||
>
|
||||
@@ -663,7 +663,7 @@ onMounted(loadAdminData)
|
||||
</NPopover>
|
||||
<RouterLink
|
||||
to="/"
|
||||
class="flex h-[46px] shrink-0 items-center justify-start gap-3 overflow-hidden border border-slate-200 bg-white px-3 text-sm font-semibold text-slate-700 shadow-[3px_3px_0_0_rgba(15,23,42,0.06)] transition-colors hover:border-sky-200 hover:bg-sky-50 hover:text-sky-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-600 lg:w-full"
|
||||
class="oc-panel-button oc-panel-button--neutral flex h-[46px] shrink-0 items-center justify-start gap-3 overflow-hidden px-3 font-semibold focus-visible:ring-2 focus-visible:ring-sky-600 lg:w-full"
|
||||
title="返回主页"
|
||||
>
|
||||
<NIcon size="20" class="shrink-0"><Home /></NIcon>
|
||||
@@ -728,8 +728,8 @@ onMounted(loadAdminData)
|
||||
<div
|
||||
class="flex flex-col justify-between gap-5 border p-6 sm:flex-row sm:items-center"
|
||||
:class="dashboardStats.pending
|
||||
? 'border-amber-200 bg-[linear-gradient(135deg,#fffbeb_0%,#fff_52%,#f2faf6_100%)] shadow-[5px_5px_0_0_rgba(245,158,11,0.12)]'
|
||||
: 'border-teal-200 bg-[linear-gradient(135deg,#f2faf6_0%,#fff_55%,#eff6ff_100%)] shadow-[5px_5px_0_0_rgba(52,116,93,0.16)]'"
|
||||
? 'admin-priority-card--pending border-amber-200 bg-[linear-gradient(135deg,#fffbeb_0%,#fff_52%,#f2faf6_100%)]'
|
||||
: 'admin-priority-card--clear border-teal-200 bg-[linear-gradient(135deg,#f2faf6_0%,#fff_55%,#eff6ff_100%)]'"
|
||||
>
|
||||
<div class="flex items-center gap-5">
|
||||
<div
|
||||
@@ -1341,3 +1341,21 @@ onMounted(loadAdminData)
|
||||
</ImageDetailModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.admin-brand-icon {
|
||||
box-shadow: var(--oc-shadow-sky);
|
||||
}
|
||||
|
||||
.admin-control-active {
|
||||
box-shadow: var(--oc-shadow-primary);
|
||||
}
|
||||
|
||||
.admin-priority-card--pending {
|
||||
box-shadow: var(--oc-shadow-amber);
|
||||
}
|
||||
|
||||
.admin-priority-card--clear {
|
||||
box-shadow: var(--oc-shadow-primary-hover);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -121,7 +121,7 @@ onUnmounted(() => {
|
||||
{{ resendButtonLabel }}
|
||||
</NButton>
|
||||
<RouterLink :to="{ path: '/login', query: { email } }" class="no-underline">
|
||||
<NButton type="default" class="oc-panel-button oc-panel-button--neutral">返回登录</NButton>
|
||||
<NButton type="default" secondary strong class="oc-panel-button oc-panel-button--neutral">返回登录</NButton>
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -197,7 +197,7 @@ watch(() => route.params.id, () => {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<NCard class="mt-8 border border-slate-200">
|
||||
<div class="oc-inset-panel mt-8">
|
||||
<p class="text-sm text-slate-500">你的收集状态</p>
|
||||
<template v-if="isUnlocked && collectionEntry">
|
||||
<p class="oc-stat-value">已解锁</p>
|
||||
@@ -207,7 +207,7 @@ watch(() => route.params.id, () => {
|
||||
<p class="oc-stat-value">尚未解锁</p>
|
||||
<p class="mt-2 text-sm text-slate-600">拍到并上传这种云朵后,这枚徽章就会被点亮。</p>
|
||||
</template>
|
||||
</NCard>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -133,7 +133,7 @@ onMounted(async () => {
|
||||
</div>
|
||||
|
||||
<div v-if="!isUnlocked(cloudType.id)" class="absolute inset-0 flex items-center justify-center bg-slate-950/12">
|
||||
<span class="inline-flex items-center gap-2 border border-slate-300 bg-white/92 px-3 py-2 text-xs font-semibold text-slate-700 shadow-[3px_3px_0_0_rgba(15,23,42,0.10)] backdrop-blur">
|
||||
<span class="encyclopedia-lock-badge inline-flex items-center gap-2 border border-slate-300 bg-white/92 px-3 py-2 text-xs font-semibold text-slate-700 backdrop-blur">
|
||||
<NIcon size="15"><Lock /></NIcon>
|
||||
尚未收录
|
||||
</span>
|
||||
@@ -184,6 +184,10 @@ onMounted(async () => {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.encyclopedia-lock-badge {
|
||||
box-shadow: var(--oc-shadow-xs);
|
||||
}
|
||||
|
||||
.encyclopedia-lock-hint {
|
||||
box-shadow: var(--oc-shadow-lg);
|
||||
}
|
||||
|
||||
@@ -841,19 +841,19 @@ onUnmounted(() => {
|
||||
@close="previewCloud = null"
|
||||
>
|
||||
<div class="grid gap-4 sm:grid-cols-2">
|
||||
<div class="rounded-2xl bg-slate-50 p-4">
|
||||
<div class="oc-inset-panel">
|
||||
<p class="oc-section-label">上传时间</p>
|
||||
<p class="mt-2 text-sm font-medium text-slate-900">{{ formatDateTime(previewCloud.createdAt) }}</p>
|
||||
</div>
|
||||
<div class="rounded-2xl bg-slate-50 p-4">
|
||||
<div class="oc-inset-panel">
|
||||
<p class="oc-section-label">拍摄时间</p>
|
||||
<p class="mt-2 text-sm font-medium text-slate-900">{{ formatDateTime(previewCloud.capturedAt) }}</p>
|
||||
</div>
|
||||
<div class="rounded-2xl bg-slate-50 p-4">
|
||||
<div class="oc-inset-panel">
|
||||
<p class="oc-section-label">位置</p>
|
||||
<p class="mt-2 text-sm font-medium text-slate-900">{{ previewCloud.locationName || '未填写位置名称' }}</p>
|
||||
</div>
|
||||
<div class="rounded-2xl bg-slate-50 p-4">
|
||||
<div class="oc-inset-panel">
|
||||
<p class="oc-section-label">模糊化经纬度</p>
|
||||
<p class="mt-2 text-sm font-medium text-slate-900">
|
||||
纬度 {{ formatCoordinate(previewCloud.latitude) }} / 经度 {{ formatCoordinate(previewCloud.longitude) }}
|
||||
@@ -861,7 +861,7 @@ onUnmounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5 rounded-[28px] border border-slate-200 bg-white p-5">
|
||||
<div class="mt-5 border border-slate-200 bg-white p-5">
|
||||
<p class="oc-section-label">图片说明</p>
|
||||
<p class="mt-3 text-sm leading-7 text-slate-700">
|
||||
{{ previewCloud.description || '上传者没有留下额外说明。' }}
|
||||
|
||||
@@ -455,7 +455,7 @@ watch(selectedUploadDate, async newValue => {
|
||||
<NCard class="oc-panel-card h-full border border-slate-200 bg-white/90 backdrop-blur" :bordered="false">
|
||||
<div class="flex gap-5">
|
||||
<div
|
||||
class="flex h-20 w-20 shrink-0 items-center justify-center border border-slate-300 bg-[linear-gradient(135deg,#eef9f3_0%,#d9efe3_100%)] text-3xl font-bold text-slate-900 shadow-[4px_4px_0_0_rgba(15,23,42,0.08)]"
|
||||
class="profile-avatar flex h-20 w-20 shrink-0 items-center justify-center border border-slate-300 bg-[linear-gradient(135deg,#eef9f3_0%,#d9efe3_100%)] text-3xl font-bold text-slate-900"
|
||||
>
|
||||
<img
|
||||
v-if="profileData?.avatar_url"
|
||||
@@ -604,7 +604,7 @@ watch(selectedUploadDate, async newValue => {
|
||||
<RouterLink
|
||||
v-if="isOwnProfile"
|
||||
to="/upload"
|
||||
class="oc-panel-button oc-panel-button--sky border-0"
|
||||
class="oc-panel-button oc-panel-button--sky"
|
||||
>
|
||||
继续上传
|
||||
</RouterLink>
|
||||
@@ -712,7 +712,7 @@ watch(selectedUploadDate, async newValue => {
|
||||
<RouterLink
|
||||
v-if="isOwnProfile && !selectedUploadDate"
|
||||
to="/upload"
|
||||
class="oc-panel-button oc-panel-button--sky border-0"
|
||||
class="oc-panel-button oc-panel-button--sky"
|
||||
>
|
||||
去上传第一张
|
||||
</RouterLink>
|
||||
@@ -815,3 +815,9 @@ watch(selectedUploadDate, async newValue => {
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.profile-avatar {
|
||||
box-shadow: var(--oc-shadow-sm);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { NButton } from 'naive-ui'
|
||||
import { NButton, NIcon } from 'naive-ui'
|
||||
import { Lock } from '@vicons/tabler'
|
||||
import { RouterLink, useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
@@ -30,7 +31,7 @@ const description = computed(() => {
|
||||
<template>
|
||||
<div class="oc-system-page">
|
||||
<div class="oc-system-card">
|
||||
<div class="text-7xl leading-none">🔐</div>
|
||||
<NIcon size="72" class="text-sky-600"><Lock /></NIcon>
|
||||
<p class="mt-6 text-sm font-medium uppercase tracking-[0.24em] text-sky-600">401 Login Required</p>
|
||||
<h1 class="oc-page-title">{{ title }}</h1>
|
||||
<p class="oc-page-description mx-auto max-w-xl">
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton } from 'naive-ui'
|
||||
import { NButton, NIcon } from 'naive-ui'
|
||||
import { HandStop } from '@vicons/tabler'
|
||||
import { RouterLink } from 'vue-router'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="oc-system-page">
|
||||
<div class="oc-system-card">
|
||||
<div class="text-7xl leading-none">🖐️</div>
|
||||
<NIcon size="72" class="text-rose-600"><HandStop /></NIcon>
|
||||
<p class="mt-6 text-sm font-medium uppercase tracking-[0.24em] text-rose-600">403 Forbidden</p>
|
||||
<h1 class="oc-page-title">这里不让进</h1>
|
||||
<p class="oc-page-description mx-auto max-w-xl">
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton } from 'naive-ui'
|
||||
import { NButton, NIcon } from 'naive-ui'
|
||||
import { Help } from '@vicons/tabler'
|
||||
import { RouterLink } from 'vue-router'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="oc-system-page">
|
||||
<div class="oc-system-card">
|
||||
<div class="text-7xl leading-none">🤔</div>
|
||||
<NIcon size="72" class="text-amber-600"><Help /></NIcon>
|
||||
<p class="mt-6 text-sm font-medium uppercase tracking-[0.24em] text-amber-600">404 Not Found</p>
|
||||
<h1 class="oc-page-title">我也没想明白</h1>
|
||||
<p class="oc-page-description mx-auto max-w-xl">
|
||||
|
||||
Reference in New Issue
Block a user