mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-09-06 07:57:04 +08:00
feat: add copy email button
This commit is contained in:
@@ -10,7 +10,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vueuse/core": "^10.1.2",
|
"@vueuse/core": "^10.1.2",
|
||||||
"naive-ui": "^2.34.3",
|
"naive-ui": "^2.34.3",
|
||||||
"vue": "^3.3.4"
|
"vue": "^3.3.4",
|
||||||
|
"vue-clipboard3": "^2.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^4.2.3",
|
"@vitejs/plugin-vue": "^4.2.3",
|
||||||
|
|||||||
Generated
+35
@@ -14,6 +14,9 @@ dependencies:
|
|||||||
vue:
|
vue:
|
||||||
specifier: ^3.3.4
|
specifier: ^3.3.4
|
||||||
version: 3.3.4
|
version: 3.3.4
|
||||||
|
vue-clipboard3:
|
||||||
|
specifier: ^2.0.0
|
||||||
|
version: 2.0.0
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@vitejs/plugin-vue':
|
'@vitejs/plugin-vue':
|
||||||
@@ -411,6 +414,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
|
resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/clipboard@2.0.11:
|
||||||
|
resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==}
|
||||||
|
dependencies:
|
||||||
|
good-listener: 1.2.2
|
||||||
|
select: 1.1.2
|
||||||
|
tiny-emitter: 2.1.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/css-render@0.15.12:
|
/css-render@0.15.12:
|
||||||
resolution: {integrity: sha512-eWzS66patiGkTTik+ipO9qNGZ+uNuGyTmnz6/+EJIiFg8+3yZRpnMwgFo8YdXhQRsiePzehnusrxVvugNjXzbw==}
|
resolution: {integrity: sha512-eWzS66patiGkTTik+ipO9qNGZ+uNuGyTmnz6/+EJIiFg8+3yZRpnMwgFo8YdXhQRsiePzehnusrxVvugNjXzbw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -440,6 +451,10 @@ packages:
|
|||||||
'@babel/runtime': 7.22.10
|
'@babel/runtime': 7.22.10
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/delegate@3.2.0:
|
||||||
|
resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/esbuild@0.18.20:
|
/esbuild@0.18.20:
|
||||||
resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
|
resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -485,6 +500,12 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
/good-listener@1.2.2:
|
||||||
|
resolution: {integrity: sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==}
|
||||||
|
dependencies:
|
||||||
|
delegate: 3.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/highlight.js@11.8.0:
|
/highlight.js@11.8.0:
|
||||||
resolution: {integrity: sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg==}
|
resolution: {integrity: sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
@@ -562,10 +583,18 @@ packages:
|
|||||||
resolution: {integrity: sha512-lEV5VB8BUKTo/AfktXJcy+JeXns26ylbMkIUco8CYREsQijuz4mrXres2Q+vMLdwkuLxJdIPQ8IlCIxLYm71Yw==}
|
resolution: {integrity: sha512-lEV5VB8BUKTo/AfktXJcy+JeXns26ylbMkIUco8CYREsQijuz4mrXres2Q+vMLdwkuLxJdIPQ8IlCIxLYm71Yw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/select@1.1.2:
|
||||||
|
resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/source-map-js@1.0.2:
|
/source-map-js@1.0.2:
|
||||||
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
/tiny-emitter@2.1.0:
|
||||||
|
resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/to-fast-properties@2.0.0:
|
/to-fast-properties@2.0.0:
|
||||||
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -627,6 +656,12 @@ packages:
|
|||||||
vue: 3.3.4
|
vue: 3.3.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/vue-clipboard3@2.0.0:
|
||||||
|
resolution: {integrity: sha512-Q9S7dzWGax7LN5iiSPcu/K1GGm2gcBBlYwmMsUc5/16N6w90cbKow3FnPmPs95sungns4yvd9/+JhbAznECS2A==}
|
||||||
|
dependencies:
|
||||||
|
clipboard: 2.0.11
|
||||||
|
dev: false
|
||||||
|
|
||||||
/vue-demi@0.14.5(vue@3.3.4):
|
/vue-demi@0.14.5(vue@3.3.4):
|
||||||
resolution: {integrity: sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==}
|
resolution: {integrity: sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|||||||
+3
-175
@@ -1,182 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { NGrid, NGi, NSpace, NAlert, NMessageProvider } from 'naive-ui'
|
import { NMessageProvider } from 'naive-ui'
|
||||||
import { NSpin, NButton, NCard, NLayout, NPopconfirm } from 'naive-ui'
|
import Content from './Content.vue';
|
||||||
import { watch, onMounted, ref } from "vue";
|
|
||||||
import { useStorage } from '@vueuse/core'
|
|
||||||
|
|
||||||
const jwt = useStorage('jwt')
|
|
||||||
const address = ref("")
|
|
||||||
const result = ref("")
|
|
||||||
const loading = ref(false)
|
|
||||||
const data = ref([])
|
|
||||||
const API_BASE = import.meta.env.VITE_API_BASE || "";
|
|
||||||
|
|
||||||
const refresh = async () => {
|
|
||||||
if (typeof address.value != 'string' || address.value.trim() === '') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
loading.value = true;
|
|
||||||
const response = await fetch(`${API_BASE}/api/mails?address=${address.value}`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Authorization": `Bearer ${jwt.value}`,
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`${response.status} ${await response.text()}` || "error");
|
|
||||||
}
|
|
||||||
let res = await response.json();
|
|
||||||
data.value = res;
|
|
||||||
result.value = "";
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
result.value = error.message || "error";
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const newEmail = async () => {
|
|
||||||
try {
|
|
||||||
loading.value = true;
|
|
||||||
const response = await fetch(`${API_BASE}/api/new_address`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`${response.status} ${await response.text()}` || "error");
|
|
||||||
}
|
|
||||||
let res = await response.json();
|
|
||||||
jwt.value = res["jwt"];
|
|
||||||
} catch (error) {
|
|
||||||
jwt.value = "";
|
|
||||||
console.error(error);
|
|
||||||
result.value = error.message || "error";
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
await refresh();
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSettings = async (jwt) => {
|
|
||||||
const response = await fetch(`${API_BASE}/api/settings`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Authorization": `Bearer ${jwt}`,
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
console.error(response);
|
|
||||||
address.value = "";
|
|
||||||
}
|
|
||||||
let res = await response.json();
|
|
||||||
address.value = res["address"];
|
|
||||||
await refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(jwt, async (jwt, old) => getSettings(jwt))
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
getSettings(jwt.value)
|
|
||||||
await refresh();
|
|
||||||
const token = import.meta.env.VITE_CF_WEB_ANALY_TOKEN;
|
|
||||||
|
|
||||||
const exist = document.querySelector('script[src="https://static.cloudflareinsights.com/beacon.min.js"]') !== null
|
|
||||||
if (token && !exist) {
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.defer = true;
|
|
||||||
script.src = 'https://static.cloudflareinsights.com/beacon.min.js';
|
|
||||||
script.dataset.cfBeacon = `{ token: ${token} }`;
|
|
||||||
document.body.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-message-provider>
|
<n-message-provider>
|
||||||
<n-spin size="large" description="loading..." :show="loading">
|
<Content />
|
||||||
<n-grid x-gap="12" :cols="6">
|
|
||||||
<n-gi span="6">
|
|
||||||
<div class="main">
|
|
||||||
<n-space vertical>
|
|
||||||
<h2>Temp Email</h2>
|
|
||||||
<n-layout>
|
|
||||||
<n-layout>
|
|
||||||
<n-card>
|
|
||||||
<n-alert type="info" show-icon>
|
|
||||||
<span v-if="address">
|
|
||||||
Your email address is <b>{{ address }}</b>
|
|
||||||
</span>
|
|
||||||
<span v-else>
|
|
||||||
Please click <b>Get New Email</b> button to get a new email address
|
|
||||||
</span>
|
|
||||||
</n-alert>
|
|
||||||
</n-card>
|
|
||||||
<n-popconfirm @positive-click="newEmail" :show-icon="false">
|
|
||||||
<template #trigger>
|
|
||||||
<n-button class="center" tertiary round type="primary">
|
|
||||||
Get New Email
|
|
||||||
</n-button>
|
|
||||||
</template>
|
|
||||||
Get New Email?
|
|
||||||
</n-popconfirm>
|
|
||||||
<n-button class="center" @click="refresh" tertiary round type="primary">
|
|
||||||
Refresh
|
|
||||||
</n-button>
|
|
||||||
<n-card>
|
|
||||||
<n-alert type="" show-icon v-if="result">
|
|
||||||
<span>
|
|
||||||
<pre>{{ result }}</pre>
|
|
||||||
</span>
|
|
||||||
</n-alert>
|
|
||||||
<n-alert v-for="row in data" v-bind:key="row.id" :title="`FROM: ${row.source} ID: ${row.id}`"
|
|
||||||
type="default">
|
|
||||||
<p>{{ row.subject }}</p>
|
|
||||||
<div v-html="row.message"></div>
|
|
||||||
</n-alert>
|
|
||||||
</n-card>
|
|
||||||
</n-layout>
|
|
||||||
</n-layout>
|
|
||||||
</n-space>
|
|
||||||
</div>
|
|
||||||
</n-gi>
|
|
||||||
</n-grid>
|
|
||||||
</n-spin>
|
|
||||||
</n-message-provider>
|
</n-message-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.side {
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main {
|
|
||||||
height: 100vh;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.n-grid {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.n-gi {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.n-space {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.n-alert {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -0,0 +1,203 @@
|
|||||||
|
<script setup>
|
||||||
|
import { NGrid, NGi, NSpace, NAlert, NMessageProvider } from 'naive-ui'
|
||||||
|
import { NSpin, NButton, NCard, NLayout, NPopconfirm } from 'naive-ui'
|
||||||
|
import { watch, onMounted, ref } from "vue";
|
||||||
|
import { useStorage } from '@vueuse/core'
|
||||||
|
import useClipboard from 'vue-clipboard3'
|
||||||
|
import { useMessage } from 'naive-ui'
|
||||||
|
|
||||||
|
const { toClipboard } = useClipboard()
|
||||||
|
const message = useMessage()
|
||||||
|
|
||||||
|
const jwt = useStorage('jwt')
|
||||||
|
const address = ref("")
|
||||||
|
const result = ref("")
|
||||||
|
const loading = ref(false)
|
||||||
|
const data = ref([])
|
||||||
|
const API_BASE = import.meta.env.VITE_API_BASE || "";
|
||||||
|
|
||||||
|
const refresh = async () => {
|
||||||
|
if (typeof address.value != 'string' || address.value.trim() === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
const response = await fetch(`${API_BASE}/api/mails?address=${address.value}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Bearer ${jwt.value}`,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
message.error(`${response.status} ${await response.text()}` || "error");
|
||||||
|
throw new Error(`${response.status} ${await response.text()}` || "error");
|
||||||
|
}
|
||||||
|
let res = await response.json();
|
||||||
|
data.value = res;
|
||||||
|
result.value = "";
|
||||||
|
} catch (error) {
|
||||||
|
message.error(error.message || "error");
|
||||||
|
console.error(error);
|
||||||
|
result.value = error.message || "error";
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const copy = async () => {
|
||||||
|
try {
|
||||||
|
await toClipboard(address.value)
|
||||||
|
message.success('Copied');
|
||||||
|
} catch (e) {
|
||||||
|
message.error(e.message || "error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const newEmail = async () => {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
const response = await fetch(`${API_BASE}/api/new_address`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
message.error(
|
||||||
|
`${response.status} ${await response.text()}` || "error",
|
||||||
|
);
|
||||||
|
throw new Error(`${response.status} ${await response.text()}` || "error");
|
||||||
|
}
|
||||||
|
let res = await response.json();
|
||||||
|
jwt.value = res["jwt"];
|
||||||
|
} catch (error) {
|
||||||
|
jwt.value = "";
|
||||||
|
message.error(error.message || "error");
|
||||||
|
console.error(error);
|
||||||
|
result.value = error.message || "error";
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
await refresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSettings = async (jwt) => {
|
||||||
|
const response = await fetch(`${API_BASE}/api/settings`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Bearer ${jwt}`,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
message.error(`${response.status} ${await response.text()}` || "error");
|
||||||
|
console.error(response);
|
||||||
|
address.value = "";
|
||||||
|
}
|
||||||
|
let res = await response.json();
|
||||||
|
address.value = res["address"];
|
||||||
|
await refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(jwt, async (jwt, old) => getSettings(jwt))
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
getSettings(jwt.value)
|
||||||
|
await refresh();
|
||||||
|
const token = import.meta.env.VITE_CF_WEB_ANALY_TOKEN;
|
||||||
|
|
||||||
|
const exist = document.querySelector('script[src="https://static.cloudflareinsights.com/beacon.min.js"]') !== null
|
||||||
|
if (token && !exist) {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.defer = true;
|
||||||
|
script.src = 'https://static.cloudflareinsights.com/beacon.min.js';
|
||||||
|
script.dataset.cfBeacon = `{ token: ${token} }`;
|
||||||
|
document.body.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<n-spin size="large" description="loading..." :show="loading">
|
||||||
|
<n-grid x-gap="12" :cols="6">
|
||||||
|
<n-gi span="6">
|
||||||
|
<div class="main">
|
||||||
|
<n-space vertical>
|
||||||
|
<h2>Temp Email</h2>
|
||||||
|
<n-layout>
|
||||||
|
<n-layout>
|
||||||
|
<n-card>
|
||||||
|
<n-alert type="info" show-icon>
|
||||||
|
<span v-if="address">
|
||||||
|
Your email address is <b>{{ address }}</b>
|
||||||
|
<n-button style="margin-left: 10px;" @click="copy" size="small" tertiary round
|
||||||
|
type="primary">Copy</n-button>
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
Please click <b>Get New Email</b> button to get a new email address
|
||||||
|
</span>
|
||||||
|
</n-alert>
|
||||||
|
</n-card>
|
||||||
|
<n-popconfirm @positive-click="newEmail" :show-icon="false">
|
||||||
|
<template #trigger>
|
||||||
|
<n-button class="center" tertiary round type="primary">
|
||||||
|
Get New Email
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
Get New Email?
|
||||||
|
</n-popconfirm>
|
||||||
|
<n-button class="center" @click="refresh" tertiary round type="primary">
|
||||||
|
Refresh
|
||||||
|
</n-button>
|
||||||
|
<n-card>
|
||||||
|
<n-alert type="" show-icon v-if="result">
|
||||||
|
<span>
|
||||||
|
<pre>{{ result }}</pre>
|
||||||
|
</span>
|
||||||
|
</n-alert>
|
||||||
|
<n-alert v-for="row in data" v-bind:key="row.id" :title="`FROM: ${row.source} ID: ${row.id}`"
|
||||||
|
type="default">
|
||||||
|
<p>{{ row.subject }}</p>
|
||||||
|
<div v-html="row.message"></div>
|
||||||
|
</n-alert>
|
||||||
|
</n-card>
|
||||||
|
</n-layout>
|
||||||
|
</n-layout>
|
||||||
|
</n-space>
|
||||||
|
</div>
|
||||||
|
</n-gi>
|
||||||
|
</n-grid>
|
||||||
|
</n-spin>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.side {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
height: 100vh;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.n-grid {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.n-gi {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.n-space {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.n-alert {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user