feat: add page components

This commit is contained in:
张传龙 2022-08-28 19:37:23 +08:00
parent 841bab0d63
commit 079761b6fd
23 changed files with 272 additions and 221 deletions

View File

@ -44,7 +44,7 @@
"fs-extra": "^10.0.1", "fs-extra": "^10.0.1",
"husky": "^8.0.1", "husky": "^8.0.1",
"lint-staged": "^13.0.3", "lint-staged": "^13.0.3",
"naive-ui": "^2.32.1", "naive-ui": "^2.32.2",
"prettier": "^2.6.1", "prettier": "^2.6.1",
"rollup-plugin-visualizer": "^5.6.0", "rollup-plugin-visualizer": "^5.6.0",
"sass": "^1.49.10", "sass": "^1.49.10",

60
pnpm-lock.yaml generated
View File

@ -26,7 +26,7 @@ specifiers:
lodash-es: ^4.17.21 lodash-es: ^4.17.21
md-editor-v3: ^1.11.4 md-editor-v3: ^1.11.4
mockjs: ^1.1.0 mockjs: ^1.1.0
naive-ui: ^2.32.1 naive-ui: ^2.32.2
pinia: ^2.0.13 pinia: ^2.0.13
prettier: ^2.6.1 prettier: ^2.6.1
rollup-plugin-visualizer: ^5.6.0 rollup-plugin-visualizer: ^5.6.0
@ -75,7 +75,7 @@ devDependencies:
fs-extra: 10.0.1 fs-extra: 10.0.1
husky: 8.0.1 husky: 8.0.1
lint-staged: 13.0.3 lint-staged: 13.0.3
naive-ui: 2.32.1_vue@3.2.31 naive-ui: 2.32.2_vue@3.2.31
prettier: 2.6.1 prettier: 2.6.1
rollup-plugin-visualizer: 5.6.0 rollup-plugin-visualizer: 5.6.0
sass: 1.49.10 sass: 1.49.10
@ -314,16 +314,16 @@ packages:
'@jridgewell/trace-mapping': 0.3.9 '@jridgewell/trace-mapping': 0.3.9
dev: true dev: true
/@css-render/plugin-bem/0.15.10_css-render@0.15.10: /@css-render/plugin-bem/0.15.11_css-render@0.15.11:
resolution: {integrity: sha512-V7b08sM2PWJlXI7BJiVIa0Sg30H3u/jHay4AclNXfF2yRFwwb4ZJjggsMfzwj3WSihAdNf2WTqvOU5qsOD80Dg==} resolution: {integrity: sha512-Bn8qadYPIz5DhZ4obTGHOJzeziQH6kY0+Fk5AEvwuuy378SLwwvXuuoechLjBHcgKkPCM03Oo4dDSGP/6NMdyw==}
peerDependencies: peerDependencies:
css-render: ~0.15.10 css-render: ~0.15.11
dependencies: dependencies:
css-render: 0.15.10 css-render: 0.15.11
dev: true dev: true
/@css-render/vue3-ssr/0.15.10_vue@3.2.31: /@css-render/vue3-ssr/0.15.11_vue@3.2.31:
resolution: {integrity: sha512-keGKnkB2nyVGoA8GezMKNsmvTGXEzgLOGGlgshwOTSEzd1dsROyZ2m/khJ9jV5zbzDM4rWeAWbWF0zwHemsJcw==} resolution: {integrity: sha512-n+SuqLPbY30FUTM8slX75OaEG+c8XlTOFrAklekX2XQGvBbz9XdBE6hTEgGlV5kPcTMqTJeCG7Vzhs9/29VC7w==}
peerDependencies: peerDependencies:
vue: ^3.0.11 vue: ^3.0.11
dependencies: dependencies:
@ -436,8 +436,8 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.14 '@jridgewell/sourcemap-codec': 1.4.14
dev: true dev: true
/@juggle/resize-observer/3.3.1: /@juggle/resize-observer/3.4.0:
resolution: {integrity: sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw==} resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
dev: true dev: true
/@nodelib/fs.scandir/2.1.5: /@nodelib/fs.scandir/2.1.5:
@ -534,11 +534,11 @@ packages:
/@types/lodash-es/4.17.6: /@types/lodash-es/4.17.6:
resolution: {integrity: sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==} resolution: {integrity: sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==}
dependencies: dependencies:
'@types/lodash': 4.14.183 '@types/lodash': 4.14.184
dev: true dev: true
/@types/lodash/4.14.183: /@types/lodash/4.14.184:
resolution: {integrity: sha512-UXavyuxzXKMqJPEpFPri6Ku5F9af6ZJXUneHhvQJxavrEjuHkFp2YnDWHcxJiG7hk8ZkWqjcyNeW1s/smZv5cw==} resolution: {integrity: sha512-RoZphVtHbxPZizt4IcILciSWiC6dcn+eZ8oX9IWEYfDMcocdd42f7NPI6fQj+6zI8y4E0L7gu2pcZKLGTRaV9Q==}
dev: true dev: true
/@types/minimist/1.2.2: /@types/minimist/1.2.2:
@ -1488,8 +1488,8 @@ packages:
which: 2.0.2 which: 2.0.2
dev: true dev: true
/css-render/0.15.10: /css-render/0.15.11:
resolution: {integrity: sha512-6j5acvm81sXTHJiF47FNNICtDpF74YoWk1xEK3qQvdqgW6vc+OXrPqflL6m8f5GE6XuFYrbACNEd17kraCSBAQ==} resolution: {integrity: sha512-hnLrHPUndVUTF5nmNPRey6hpixK02IPUGdEsm2xRjvJuewToyrVFx9Nmai8rgfVzhTFo5SJVh2PHAtzaIV8JKw==}
dependencies: dependencies:
'@emotion/hash': 0.8.0 '@emotion/hash': 0.8.0
'@types/node': 17.0.23 '@types/node': 17.0.23
@ -1592,16 +1592,16 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/date-fns-tz/1.3.6_date-fns@2.29.1: /date-fns-tz/1.3.6_date-fns@2.29.2:
resolution: {integrity: sha512-C8q7mErvG4INw1ZwAFmPlGjEo5Sv4udjKVbTc03zpP9cu6cp5AemFzKhz0V68LGcWEtX5mJudzzg3G04emIxLA==} resolution: {integrity: sha512-C8q7mErvG4INw1ZwAFmPlGjEo5Sv4udjKVbTc03zpP9cu6cp5AemFzKhz0V68LGcWEtX5mJudzzg3G04emIxLA==}
peerDependencies: peerDependencies:
date-fns: '>=2.0.0' date-fns: '>=2.0.0'
dependencies: dependencies:
date-fns: 2.29.1 date-fns: 2.29.2
dev: true dev: true
/date-fns/2.29.1: /date-fns/2.29.2:
resolution: {integrity: sha512-dlLD5rKaKxpFdnjrs+5azHDFOPEu4ANy/LTh04A1DTzMM7qoajmKCBc8pkKRFT41CNzw+4gQh79X5C+Jq27HAw==} resolution: {integrity: sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==}
engines: {node: '>=0.11'} engines: {node: '>=0.11'}
dev: true dev: true
@ -3767,19 +3767,19 @@ packages:
resolution: {integrity: sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=} resolution: {integrity: sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=}
dev: true dev: true
/naive-ui/2.32.1_vue@3.2.31: /naive-ui/2.32.2_vue@3.2.31:
resolution: {integrity: sha512-4zRHAn9d273qKWHs2ZQ+9xZmGTfxhL/CI1tj8bJkE313zjwyGRaiPbCeh3hQgrNdZWiRXdqmA442EVKHizGWeg==} resolution: {integrity: sha512-vTNuZ8LBlfo/cdiv4S8o6Cg5g7p9V9cR5rK+Fag2cplOnng5twTILD3sBaCqw3k/BV1331Xdk26ml8Me8QJ7iA==}
peerDependencies: peerDependencies:
vue: ^3.0.0 vue: ^3.0.0
dependencies: dependencies:
'@css-render/plugin-bem': 0.15.10_css-render@0.15.10 '@css-render/plugin-bem': 0.15.11_css-render@0.15.11
'@css-render/vue3-ssr': 0.15.10_vue@3.2.31 '@css-render/vue3-ssr': 0.15.11_vue@3.2.31
'@types/lodash': 4.14.183 '@types/lodash': 4.14.184
'@types/lodash-es': 4.17.6 '@types/lodash-es': 4.17.6
async-validator: 4.2.5 async-validator: 4.2.5
css-render: 0.15.10 css-render: 0.15.11
date-fns: 2.29.1 date-fns: 2.29.2
date-fns-tz: 1.3.6_date-fns@2.29.1 date-fns-tz: 1.3.6_date-fns@2.29.2
evtd: 0.2.4 evtd: 0.2.4
highlight.js: 11.6.0 highlight.js: 11.6.0
lodash: 4.17.21 lodash: 4.17.21
@ -5604,9 +5604,9 @@ packages:
peerDependencies: peerDependencies:
vue: ^3.0.11 vue: ^3.0.11
dependencies: dependencies:
'@css-render/vue3-ssr': 0.15.10_vue@3.2.31 '@css-render/vue3-ssr': 0.15.11_vue@3.2.31
'@juggle/resize-observer': 3.3.1 '@juggle/resize-observer': 3.4.0
css-render: 0.15.10 css-render: 0.15.11
evtd: 0.2.4 evtd: 0.2.4
seemly: 0.3.6 seemly: 0.3.6
vdirs: 0.1.8_vue@3.2.31 vdirs: 0.1.8_vue@3.2.31

View File

@ -1,8 +1,7 @@
<script setup> <script setup>
import { renderCustomIcon } from '@/utils/icon' /** 自定义图标 */
const props = defineProps({ const props = defineProps({
/** 图标名称(图片的文件名) */ /** 图标名称(assets/svg下的文件名) */
icon: { icon: {
type: String, type: String,
required: true, required: true,
@ -16,10 +15,8 @@ const props = defineProps({
default: undefined, default: undefined,
}, },
}) })
const iconCom = computed(() => renderCustomIcon(props.icon, props))
</script> </script>
<template> <template>
<component :is="iconCom" /> <TheIcon type="custom" v-bind="props" />
</template> </template>

View File

@ -1,4 +1,4 @@
<script setup name="SvgIcon"> <script setup>
const props = defineProps({ const props = defineProps({
icon: { icon: {
type: String, type: String,

View File

@ -0,0 +1,33 @@
<script setup>
import { renderIcon, renderCustomIcon } from '@/utils/icon'
const props = defineProps({
icon: {
type: String,
required: true,
},
size: {
type: Number,
default: 14,
},
color: {
type: String,
default: undefined,
},
/** iconify | custom */
type: {
type: String,
default: 'iconify',
},
})
const iconCom = computed(() =>
props.type === 'iconify'
? renderIcon(props.icon, { size: props.size, color: props.color })
: renderCustomIcon(props.icon, { size: props.size, color: props.color })
)
</script>
<template>
<component :is="iconCom" />
</template>

View File

@ -0,0 +1,17 @@
<template>
<transition name="fade-slide" mode="out-in" appear>
<section class="cus-scroll-y wh-full p-15 flex-col bg-[#f5f6fb]">
<slot />
<AppFooter v-if="showFooter" mt-15 />
</section>
</transition>
</template>
<script setup>
defineProps({
showFooter: {
type: Boolean,
default: false,
},
})
</script>

View File

@ -0,0 +1,28 @@
<template>
<AppPage :show-footer="showFooter">
<n-card rounded-10 flex-1>
<slot v-if="showHeader" name="header">
<h2 mb-15 color="#333">{{ title || route.meta?.title }}</h2>
</slot>
<slot />
</n-card>
</AppPage>
</template>
<script setup>
defineProps({
showFooter: {
type: Boolean,
default: false,
},
showHeader: {
type: Boolean,
default: true,
},
title: {
type: String,
default: undefined,
},
})
const route = useRoute()
</script>

View File

@ -1,10 +1,6 @@
<template> <template>
<router-view v-slot="{ Component, route }"> <router-view v-slot="{ Component }">
<transition name="fade-slide" mode="out-in" appear> <component :is="Component" v-if="appStore.reloadFlag" />
<keep-alive :include="keepAliveRouteNames">
<component :is="Component" v-if="appStore.reloadFlag" :key="route.path" />
</keep-alive>
</transition>
</router-view> </router-view>
</template> </template>
@ -12,9 +8,4 @@
import { useAppStore } from '@/store/modules/app' import { useAppStore } from '@/store/modules/app'
const appStore = useAppStore() const appStore = useAppStore()
const router = useRouter()
const allRoutes = router.getRoutes()
const keepAliveRouteNames = computed(() => {
return allRoutes.filter((route) => route.meta?.keepAlive).map((route) => route.name)
})
</script> </script>

View File

@ -1,5 +1,4 @@
<template> <template>
<header px-15 h-full flex items-center>
<div flex items-center> <div flex items-center>
<MenuCollapse /> <MenuCollapse />
<BreadCrumb ml-15 /> <BreadCrumb ml-15 />
@ -9,7 +8,6 @@
<FullScreen /> <FullScreen />
<UserAvatar /> <UserAvatar />
</div> </div>
</header>
</template> </template>
<script setup> <script setup>

View File

@ -106,7 +106,7 @@ function handleMenuSelect(key, item) {
&.n-menu-item-content--selected, &.n-menu-item-content--selected,
&:hover { &:hover {
&::before { &::before {
border-left: 4px solid var(--primaryColor); border-left: 4px solid var(--primary-color);
} }
} }
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<n-layout has-sider h-full> <n-layout has-sider wh-full>
<n-layout-sider <n-layout-sider
bordered bordered
collapse-mode="width" collapse-mode="width"
@ -10,19 +10,18 @@
> >
<SideBar /> <SideBar />
</n-layout-sider> </n-layout-sider>
<n-layout>
<n-layout-header bg-white border-b bc-eee :style="`height: ${header.height ?? 60}px`">
<AppHeader />
</n-layout-header>
<n-layout bg="#f5f6fb" :style="`height: calc(100% - ${header.height ?? 60}px)`"> <article flex-1 flex-col overflow-hidden>
<AppTags v-if="tags.visible" :style="`height: ${tags.height ?? 50}px`" /> <header bg-white px-15 border-b bc-eee flex items-center :style="`height: ${header.height}px`">
<AppMain <AppHeader />
class="cus-scroll border-t bc-eee overflow-auto" </header>
:style="{ height: `calc(100% - ${tags.visible ? tags.height ?? 50 : 0}px)` }" <section v-if="tags.visible" border-b bc-eee>
/> <AppTags :style="{ height: `${tags.height}px` }" />
</n-layout> </section>
</n-layout> <section flex-1 overflow-hidden>
<AppMain />
</section>
</article>
</n-layout> </n-layout>
</template> </template>

View File

@ -32,25 +32,42 @@ body {
transform: translateX(30px); transform: translateX(30px);
} }
/* 自定义滚动条样式 */
/* 自定义滚动条样式 */ /* 自定义滚动条样式 */
.cus-scroll { .cus-scroll {
overflow: auto;
&::-webkit-scrollbar { &::-webkit-scrollbar {
width: 8px; width: 8px;
height: 8px; height: 8px;
} }
}
.cus-scroll-x {
overflow-x: auto;
&::-webkit-scrollbar {
width: 0;
height: 8px;
}
}
.cus-scroll-y {
overflow-y: auto;
&::-webkit-scrollbar {
width: 8px;
height: 0;
}
}
.cus-scroll,
.cus-scroll-x,
.cus-scroll-y {
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
background-color: transparent; background-color: transparent;
border-radius: 3px; border-radius: 4px;
}
&::-webkit-scrollbar-corner {
background: #f6f6f6;
} }
&:hover { &:hover {
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
background: #bfbfbf; background: #bfbfbf;
} }
&::-webkit-scrollbar-thumb:hover { &::-webkit-scrollbar-thumb:hover {
background: #999999; background: var(--primary-color);
} }
} }
} }

View File

@ -1,7 +1,7 @@
import { h } from 'vue' import { h } from 'vue'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
import { NIcon } from 'naive-ui' import { NIcon } from 'naive-ui'
import SvgIcon from '@/components/custom/SvgIcon.vue' import SvgIcon from '@/components/icon/SvgIcon.vue'
export function renderIcon(icon, props = { size: 12 }) { export function renderIcon(icon, props = { size: 12 }) {
return () => h(NIcon, props, { default: () => h(Icon, { icon }) }) return () => h(NIcon, props, { default: () => h(Icon, { icon }) })

View File

@ -1,5 +1,5 @@
<template> <template>
<div h-full flex> <AppPage>
<n-result m-auto status="404" description="抱歉,您访问的页面不存在。"> <n-result m-auto status="404" description="抱歉,您访问的页面不存在。">
<template #icon> <template #icon>
<img src="@/assets/images/404.webp" width="500" /> <img src="@/assets/images/404.webp" width="500" />
@ -8,7 +8,7 @@
<n-button @click="replace('/')">返回首页</n-button> <n-button @click="replace('/')">返回首页</n-button>
</template> </template>
</n-result> </n-result>
</div> </AppPage>
</template> </template>
<script setup> <script setup>

View File

@ -1,5 +1,5 @@
<template> <template>
<div p-24> <CommonPage :show-header="false" title="32323">
<div h-60 pl-20 pr-20 flex items-center bg-white> <div h-60 pl-20 pr-20 flex items-center bg-white>
<input <input
v-model="post.title" v-model="post.title"
@ -7,10 +7,12 @@
type="text" type="text"
placeholder="输入文章标题..." placeholder="输入文章标题..."
/> />
<n-button type="primary" style="width: 80px" :loading="btnLoading" @click="handleSavePost">保存</n-button> <n-button type="primary" style="width: 80px" :loading="btnLoading" @click="handleSavePost">
</div> <TheIcon v-if="!btnLoading" icon="line-md:confirm-circle" class="mr-5" :size="18" /> 保存
<MdEditor v-model="post.content" style="height: calc(100vh - 220px)" /> </n-button>
</div> </div>
<MdEditor v-model="post.content" style="height: calc(100vh - 250px)" />
</CommonPage>
</template> </template>
<script setup> <script setup>

View File

@ -1,8 +1,5 @@
<template> <template>
<div p-24> <CommonPage show-footer title="文章">
<div flex>
<n-button size="small" type="primary" @click="handleCreate">新建文章</n-button>
</div>
<n-data-table <n-data-table
mt-20 mt-20
:loading="loading" :loading="loading"
@ -13,7 +10,7 @@
:row-key="(row) => row.id" :row-key="(row) => row.id"
@update:checked-row-keys="handleCheck" @update:checked-row-keys="handleCheck"
/> />
</div> </CommonPage>
</template> </template>
<script setup> <script setup>

View File

@ -1,12 +1,15 @@
<template> <template>
<div class="cus-scroll h-full py-15 flex-col overflow-auto bg-cover" :style="{ backgroundImage: `url(${bgImg})` }"> <AppPage :show-footer="true" bg-cover :style="{ backgroundImage: `url(${bgImg})` }">
<div m-auto p-15 f-c-c min-w-345 rounded-10 card-shadow bg-white dark:bg-dark bg-opacity-60> <div
style="transform: translateY(25px)"
class="m-auto p-15 f-c-c min-w-345 max-w-700 rounded-10 card-shadow bg-white bg-opacity-60"
>
<div w-380 hidden md:block px-20 py-35> <div w-380 hidden md:block px-20 py-35>
<img src="@/assets/images/login_banner.webp" w-full alt="login_banner" /> <img src="@/assets/images/login_banner.webp" w-full alt="login_banner" />
</div> </div>
<div w-320 flex-col px-20 py-35> <div w-320 flex-col px-20 py-35>
<h5 f-c-c text-24 font-normal color="#6a6a6a"><icon-custom-logo mr-30 text-50 color-primary />{{ title }}</h5> <h5 f-c-c text-24 font-normal color="#6a6a6a"><icon-custom-logo mr-10 text-50 color-primary />{{ title }}</h5>
<div mt-30> <div mt-30>
<n-input <n-input
v-model:value="loginInfo.name" v-model:value="loginInfo.name"
@ -39,8 +42,7 @@
</div> </div>
</div> </div>
</div> </div>
<AppFooter /> </AppPage>
</div>
</template> </template>
<script setup> <script setup>

View File

@ -1,7 +1,7 @@
<template> <template>
<div p24> <CommonPage :show-header="false">
<n-button type="error" @click="handleDelete"> <icon-mi:delete mr-5 />删除</n-button> <n-button type="error" @click="handleDelete"> <icon-mi:delete mr-5 />删除</n-button>
</div> </CommonPage>
</template> </template>
<script setup name="TestDialog"> <script setup name="TestDialog">

View File

@ -1,20 +0,0 @@
<template>
<div p24>
<n-gradient-text gradient="linear-gradient(90deg, red 0%, green 50%, blue 100%)"> 注意查看提示语 </n-gradient-text>
</div>
</template>
<!--使用keep-alive须设置name注意请与对应的路由的name保持一致方便统一处理-->
<script setup name="TestKeepAlive">
onMounted(() => {
$message.success('触发onMounted')
})
onActivated(() => {
$message.success('触发onActivated')
})
onDeactivated(() => {
$message.success('触发onDeactivated')
})
</script>

View File

@ -1,10 +1,10 @@
<template> <template>
<div p24> <CommonPage title="我是自定义Title">
<n-button type="primary" @click="handleLogin"> <n-button type="primary" @click="handleLogin">
<icon-mdi:login mr-5 /> <icon-mdi:login mr-5 />
登陆 登陆
</n-button> </n-button>
</div> </CommonPage>
</template> </template>
<script setup> <script setup>

View File

@ -38,15 +38,5 @@ export default {
icon: 'material-symbols:auto-awesome-outline-rounded', icon: 'material-symbols:auto-awesome-outline-rounded',
}, },
}, },
{
name: 'TestKeepAlive',
path: 'keep-alive',
component: () => import('./keep-alive/index.vue'),
meta: {
title: '测试Keep-Alive',
keepAlive: true,
icon: 'material-symbols:auto-awesome-outline-rounded',
},
},
], ],
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<div p-24> <CommonPage show-footer>
<p> <p>
文档<a hover-decoration-underline c-blue href="https://uno.antfu.me/" target="_blank">https://uno.antfu.me/</a> 文档<a hover-decoration-underline c-blue href="https://uno.antfu.me/" target="_blank">https://uno.antfu.me/</a>
</p> </p>
@ -10,10 +10,8 @@
</a> </a>
</p> </p>
<div flex mt-20> <div f-c-c mt-20 w-350 rounded-10 b-1 bc-ccc>
<div flex p-20 rounded-5 bg="#fff"> <div flex w-360 flex-wrap justify-around p-10>
<div text-20 font-600>Flex布局</div>
<div flex w-360 flex-wrap justify-around ml-15 p-10>
<div w-50 h-50 b-1 rounded-5 f-c-c p-10 m-20> <div w-50 h-50 b-1 rounded-5 f-c-c p-10 m-20>
<span w-6 h-6 rounded-3 bg-black></span> <span w-6 h-6 rounded-3 bg-black></span>
</div> </div>
@ -63,6 +61,6 @@
</div> </div>
</div> </div>
</div> </div>
</div> <h2 font-normal text-18 text-center w-350 mt-10 color-gray-400>Flex 骰子</h2>
</div> </CommonPage>
</template> </template>

View File

@ -1,5 +1,6 @@
<template> <template>
<div p-15> <AppPage :show-footer="true">
<div flex-1>
<n-card rounded-10> <n-card rounded-10>
<div flex items-center> <div flex items-center>
<img rounded-full width="60" :src="userStore.avatar" /> <img rounded-full width="60" :src="userStore.avatar" />
@ -47,6 +48,7 @@
</div> </div>
</n-card> </n-card>
</div> </div>
</AppPage>
</template> </template>
<script setup> <script setup>