update home tab

This commit is contained in:
Timi
2026-09-12 16:21:05 +08:00
parent cb4c19f9e4
commit 194a55a03f
+131 -79
View File
@@ -1,22 +1,27 @@
<template> <template>
<div class="entry-page"> <div class="entry-page">
<section class="entry-list"> <section
<div v-for="group in visibleEntryGroupList"
v-entrance-transition="index * 70" :key="group.title"
v-for="(item, index) in visibleEntryList" class="entry-group"
:key="item.path" >
class="item" <h2 v-text="group.title" />
:class="{ wide: item.wide }" <div class="entry-list" :class="group.layout">
@click="go(item.path)" <div
> v-entrance-transition="index * 70"
v-for="(item, index) in group.entryList"
:key="item.path"
class="item"
@click="go(item.path)"
>
<div class="body"> <div class="body">
<t-icon :name="item.icon" size="1.75rem" /> <t-icon :name="item.icon" size="1.75rem" />
<h2 v-text="item.title" /> <h2 v-text="item.title" />
</div> </div>
<p v-text="item.desc" />
</div> </div>
</div>
</section> </section>
<div class="tips gray" v-entrance-transition="visibleEntryList.length * 70">微信内打开本站可能会经常在扫码时需要授权,建议使用浏览器打开(右上角菜单,使用默认浏览器打开),并添加快捷入口到桌面。</div> <div class="tips gray" v-entrance-transition="visibleEntryCount * 70">微信内打开本站可能会经常在扫码时需要授权,建议使用浏览器打开(右上角菜单,使用默认浏览器打开),并添加快捷入口到桌面。</div>
</div> </div>
</template> </template>
@@ -35,32 +40,76 @@ const userStore = useUserStore();
const unreadNotifyCount = ref(0); const unreadNotifyCount = ref(0);
let isPageActive = true; let isPageActive = true;
const entryList = [ interface HomeEntry {
path: string;
permission: string;
icon: string;
title: string;
}
interface HomeEntryGroup {
title: string;
layout?: "customer";
entryList: HomeEntry[];
}
const entryGroupList: HomeEntryGroup[] = [
{ {
path: "/customer/quick-sign-in", title: "客户管理",
permission: permissionCodes.eventRecord.create, layout: "customer",
icon: "scan", entryList: [
title: "快速扫码登记", {
desc: "扫码选择客户并按配置事件登记", path: "/management/customers/create?redirect=/customers",
wide: true permission: permissionCodes.customer.create,
icon: "edit-1",
title: "录入"
},
{
path: "/customer/registration",
permission: permissionCodes.eventRecord.create,
icon: "task-checked",
title: "登记"
},
{
path: "/customer/quick-sign-in",
permission: permissionCodes.eventRecord.create,
icon: "scan",
title: "快速扫码登记"
}
]
}, },
{ {
path: "/management/customers/create?redirect=/customers", title: "订单管理",
permission: permissionCodes.customer.create, entryList: [
icon: "edit-1", {
title: "录入", path: "/management/sales-orders",
desc: "新建客户档案并完善基础资料" permission: permissionCodes.salesOrder.read,
}, icon: "task",
{ title: "订单列表"
path: "/customer/registration", },
permission: permissionCodes.eventRecord.create, {
icon: "task-checked", path: "/management/sales-orders/create",
title: "登记", permission: permissionCodes.salesOrder.create,
desc: "按流程完成客户登记" icon: "task-add",
title: "创建订单"
},
{
path: "/management/customer-packages/create",
permission: permissionCodes.customerPackage.create,
icon: "layers",
title: "创建套餐订单"
}
]
} }
]; ];
const visibleEntryList = computed(() => entryList.filter(item => userStore.hasPermissions(item.permission))); const visibleEntryGroupList = computed(() => entryGroupList
.map(group => ({
...group,
entryList: group.entryList.filter(item => userStore.hasPermissions(item.permission))
}))
.filter(group => group.entryList.length));
const visibleEntryCount = computed(() => visibleEntryGroupList.value.reduce((count, group) => count + group.entryList.length, 0));
const canReadNotify = computed(() => userStore.hasPermissions(corePermissionCodes.notify.read)); const canReadNotify = computed(() => userStore.hasPermissions(corePermissionCodes.notify.read));
async function go(path: string): Promise<void> { async function go(path: string): Promise<void> {
@@ -100,58 +149,60 @@ onUnmounted(() => {
<style scoped lang="less"> <style scoped lang="less">
.entry-page { .entry-page {
padding: calc(var(--app-nav-height) + 1rem) 1rem 6rem 1rem; gap: 2rem;
display: flex;
padding: calc(var(--app-nav-height) + 1rem) 1rem 1rem 1rem;
flex-direction: column;
.entry-list { .entry-group {
display: grid;
gap: .875rem;
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.item { & + & {
color: #0f766e; margin-top: 1.5rem;
padding: 1rem;
display: flex;
position: relative;
text-align: center;
background: rgba(255, 255, 255, .92);
box-shadow: 0 .75rem 2rem rgba(15, 23, 42, .08);
align-items: center;
aspect-ratio: 1;
border-radius: 1.4rem;
flex-direction: column;
justify-content: center;
.body {
inset: 1rem;
display: flex;
gap: .5rem;
position: absolute;
align-items: center;
flex-direction: column;
justify-content: center;
} }
h2 { > h2 {
margin: 0; color: #52607a;
font-size: 1.1rem; margin: 0 0 .75rem 0;
line-height: 1.5; font-size: .875rem;
font-weight: 700;
} }
p { .entry-list {
left: 1rem; display: grid;
right: 1rem; gap: .875rem;
bottom: 1rem; grid-template-columns: repeat(3, minmax(0, 1fr));
color: #7b889d;
margin: 0;
position: absolute;
font-size: .75rem;
line-height: 1.25;
}
&.wide { .item {
grid-column: 1 / -1; color: #0f766e;
aspect-ratio: 2 / 1; padding: 1rem;
display: flex;
position: relative;
text-align: center;
background: rgba(255, 255, 255, .92);
box-shadow: 0 .75rem 2rem rgba(15, 23, 42, .08);
align-items: center;
aspect-ratio: 1;
border-radius: 1.4rem;
flex-direction: column;
justify-content: center;
.body {
inset: 1rem;
display: flex;
gap: .5rem;
position: absolute;
align-items: center;
flex-direction: column;
justify-content: center;
}
h2 {
margin: 0;
font-size: .75rem;
line-height: 1.5;
}
}
} }
} }
@@ -164,13 +215,14 @@ onUnmounted(() => {
:global(html.theme-dark) { :global(html.theme-dark) {
.entry-page { .entry-page {
.entry-group > h2 {
color: #94a3b8;
}
.item { .item {
background: rgba(15, 23, 42, .88); background: rgba(15, 23, 42, .88);
box-shadow: 0 .75rem 2rem rgba(2, 6, 23, .32); box-shadow: 0 .75rem 2rem rgba(2, 6, 23, .32);
p {
color: #94a3b8;
}
} }
} }
} }