feat: 添加通知详情页面及通知列表点击跳转功能;优化分隔线样式
This commit is contained in:
2
auto-imports.d.ts
vendored
2
auto-imports.d.ts
vendored
@@ -156,8 +156,6 @@ declare global {
|
|||||||
const useAsyncQueue: typeof import('@vueuse/core').useAsyncQueue
|
const useAsyncQueue: typeof import('@vueuse/core').useAsyncQueue
|
||||||
const useAsyncState: typeof import('@vueuse/core').useAsyncState
|
const useAsyncState: typeof import('@vueuse/core').useAsyncState
|
||||||
const useAttrs: typeof import('vue').useAttrs
|
const useAttrs: typeof import('vue').useAttrs
|
||||||
const useAuth: typeof import('./src/composables/useAuth').useAuth
|
|
||||||
const useBack: typeof import('./src/composables/useBack').useBack
|
|
||||||
const useBase64: typeof import('@vueuse/core').useBase64
|
const useBase64: typeof import('@vueuse/core').useBase64
|
||||||
const useBattery: typeof import('@vueuse/core').useBattery
|
const useBattery: typeof import('@vueuse/core').useBattery
|
||||||
const useBluetooth: typeof import('@vueuse/core').useBluetooth
|
const useBluetooth: typeof import('@vueuse/core').useBluetooth
|
||||||
|
|||||||
2
components.d.ts
vendored
2
components.d.ts
vendored
@@ -50,6 +50,7 @@ declare module 'vue' {
|
|||||||
IonSearchbar: typeof import('@ionic/vue')['IonSearchbar']
|
IonSearchbar: typeof import('@ionic/vue')['IonSearchbar']
|
||||||
IonSelect: typeof import('@ionic/vue')['IonSelect']
|
IonSelect: typeof import('@ionic/vue')['IonSelect']
|
||||||
IonSelectOption: typeof import('@ionic/vue')['IonSelectOption']
|
IonSelectOption: typeof import('@ionic/vue')['IonSelectOption']
|
||||||
|
IonSpinner: typeof import('@ionic/vue')['IonSpinner']
|
||||||
IonTabBar: typeof import('@ionic/vue')['IonTabBar']
|
IonTabBar: typeof import('@ionic/vue')['IonTabBar']
|
||||||
IonTabButton: typeof import('@ionic/vue')['IonTabButton']
|
IonTabButton: typeof import('@ionic/vue')['IonTabButton']
|
||||||
IonTabs: typeof import('@ionic/vue')['IonTabs']
|
IonTabs: typeof import('@ionic/vue')['IonTabs']
|
||||||
@@ -104,6 +105,7 @@ declare global {
|
|||||||
const IonSearchbar: typeof import('@ionic/vue')['IonSearchbar']
|
const IonSearchbar: typeof import('@ionic/vue')['IonSearchbar']
|
||||||
const IonSelect: typeof import('@ionic/vue')['IonSelect']
|
const IonSelect: typeof import('@ionic/vue')['IonSelect']
|
||||||
const IonSelectOption: typeof import('@ionic/vue')['IonSelectOption']
|
const IonSelectOption: typeof import('@ionic/vue')['IonSelectOption']
|
||||||
|
const IonSpinner: typeof import('@ionic/vue')['IonSpinner']
|
||||||
const IonTabBar: typeof import('@ionic/vue')['IonTabBar']
|
const IonTabBar: typeof import('@ionic/vue')['IonTabBar']
|
||||||
const IonTabButton: typeof import('@ionic/vue')['IonTabButton']
|
const IonTabButton: typeof import('@ionic/vue')['IonTabButton']
|
||||||
const IonTabs: typeof import('@ionic/vue')['IonTabs']
|
const IonTabs: typeof import('@ionic/vue')['IonTabs']
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/notify/:id",
|
||||||
|
props: true,
|
||||||
|
component: () => import("@/views/notify/detail.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/onchain-address",
|
path: "/onchain-address",
|
||||||
component: () => import("@/views/onchain-address/index.vue"),
|
component: () => import("@/views/onchain-address/index.vue"),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ defineProps<{ text?: string }>();
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="divider ion-margin-vertical" v-bind="$attrs">
|
<div class="divider ion-margin-vertical" v-bind="$attrs">
|
||||||
<span>{{ text }}</span>
|
<span v-if="text">{{ text }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ defineProps<{ text?: string }>();
|
|||||||
.divider::after {
|
.divider::after {
|
||||||
content: "";
|
content: "";
|
||||||
flex: 1;
|
flex: 1;
|
||||||
border-bottom: 1px solid var(--ion-color-medium);
|
border-bottom: 1px solid var(--ion-text-color-step-900);
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider span {
|
.divider span {
|
||||||
|
|||||||
87
src/views/notify/detail.vue
Normal file
87
src/views/notify/detail.vue
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import IcBaselineNotificationsNone from "~icons/ic/baseline-notifications-none";
|
||||||
|
import { mockClient } from "@/api";
|
||||||
|
|
||||||
|
const props = defineProps<{ id: string }>();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const { data: allNotifications } = await mockClient("notify.list");
|
||||||
|
|
||||||
|
const notification = computed(() => {
|
||||||
|
return allNotifications.value.find(item => String(item.id) === props.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(notification, (val) => {
|
||||||
|
if (!val && allNotifications.value.length > 0) {
|
||||||
|
router.replace("/layout/notify");
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
|
function handleBack() {
|
||||||
|
router.back();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<IonPage>
|
||||||
|
<IonHeader class="ion-no-border">
|
||||||
|
<ion-toolbar class="ui-toolbar">
|
||||||
|
<ui-back-button slot="start" />
|
||||||
|
<ion-title>通知详情</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</IonHeader>
|
||||||
|
<IonContent :fullscreen="true" class="ion-padding">
|
||||||
|
<div v-if="notification" class="notification-detail">
|
||||||
|
<!-- 图标和标题 -->
|
||||||
|
<div class="flex items-start gap-4 mb-2">
|
||||||
|
<div class="bg-[#f1f1f1] dark:bg-[#2d2d2d] p-2.5 rounded-full shrink-0">
|
||||||
|
<IcBaselineNotificationsNone class="text-2xl text-[#71cc51]" />
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<div class="text-xl font-semibold wrap-break-word">
|
||||||
|
{{ notification.title }}
|
||||||
|
</div>
|
||||||
|
<ion-note class="text-xs">
|
||||||
|
{{ useDateFormat(notification.date, 'YYYY-MM-DD HH:mm:ss') }}
|
||||||
|
</ion-note>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 分割线 -->
|
||||||
|
<ui-divider />
|
||||||
|
|
||||||
|
<!-- 内容 -->
|
||||||
|
<div class="notification-content">
|
||||||
|
<p class="text-base leading-relaxed whitespace-pre-wrap wrap-break-word">
|
||||||
|
{{ notification.content }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<div v-else class="flex items-center justify-center h-full">
|
||||||
|
<ion-spinner name="crescent" />
|
||||||
|
</div>
|
||||||
|
</IonContent>
|
||||||
|
</IonPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.notification-detail {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-content {
|
||||||
|
color: var(--ion-text-color);
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 深色模式适配 */
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.notification-content {
|
||||||
|
color: var(--ion-color-step-600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -4,7 +4,12 @@ import IconParkOutlineClearFormat from "~icons/icon-park-outline/clear-format";
|
|||||||
import MaterialSymbolsAndroidContacts from "~icons/material-symbols/android-contacts";
|
import MaterialSymbolsAndroidContacts from "~icons/material-symbols/android-contacts";
|
||||||
import { mockClient } from "@/api";
|
import { mockClient } from "@/api";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
const { data } = mockClient("notify.list");
|
const { data } = mockClient("notify.list");
|
||||||
|
|
||||||
|
function handleItemClick(id: number) {
|
||||||
|
router.push(`/notify/${id}`);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -24,8 +29,14 @@ const { data } = mockClient("notify.list");
|
|||||||
<ion-searchbar placeholder="Search" />
|
<ion-searchbar placeholder="Search" />
|
||||||
|
|
||||||
<ion-list lines="none">
|
<ion-list lines="none">
|
||||||
<ion-item v-for="item in data" :key="item.id" class="py-3">
|
<ion-item
|
||||||
<div slot="start" class="bg-[#f1f1f1] p-2.5 rounded-full">
|
v-for="item in data"
|
||||||
|
:key="item.id"
|
||||||
|
class="py-3"
|
||||||
|
button
|
||||||
|
@click="handleItemClick(item.id)"
|
||||||
|
>
|
||||||
|
<div slot="start" class="bg-[#f1f1f1] dark:bg-[#2d2d2d] p-2.5 rounded-full">
|
||||||
<IcBaselineNotificationsNone class="text-2xl text-[#71cc51]" />
|
<IcBaselineNotificationsNone class="text-2xl text-[#71cc51]" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pl-3 w-full">
|
<div class="pl-3 w-full">
|
||||||
|
|||||||
Reference in New Issue
Block a user