霖雨寺

This commit is contained in:
wenfp
2026-07-27 09:57:35 +08:00
commit 6e531cf7af
57 changed files with 7529 additions and 0 deletions
+144
View File
@@ -0,0 +1,144 @@
<script setup lang="ts">
import {
BankOutlined,
FileTextOutlined,
LoginOutlined,
ProfileOutlined,
ShoppingOutlined,
TeamOutlined,
} from '@ant-design/icons-vue';
import { computed, onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { clearAuthUser, logout } from '@/api/auth';
import { appConfig } from '@/config/app';
import { DEFAULT_TEMPLE_ID, CURRENT_TEMPLE_ID_KEY } from '@/api/http';
import { listTemples, type Temple } from '@/api/temples';
const route = useRoute();
const router = useRouter();
const temples = ref<Temple[]>([]);
const currentTempleId = ref(localStorage.getItem(CURRENT_TEMPLE_ID_KEY) || DEFAULT_TEMPLE_ID);
const selectedKeys = computed(() => {
const moduleName = route.meta.module;
return [typeof moduleName === 'string' ? moduleName : 'users'];
});
const breadcrumbs = computed(() => {
return route.matched
.filter((matchedRoute) => matchedRoute.meta.title)
.map((matchedRoute) => ({
path: matchedRoute.path,
title: String(matchedRoute.meta.title),
}));
});
const templeOptions = computed(() => {
return temples.value.map((temple) => ({
label: temple.name,
value: String(temple.id),
}));
});
function openRoute(path: string) {
router.push(path);
}
function changeTemple(value: string) {
localStorage.setItem(CURRENT_TEMPLE_ID_KEY, value);
currentTempleId.value = value;
window.location.reload();
}
async function submitLogout() {
await logout().catch(() => undefined);
clearAuthUser();
router.push('/login');
}
async function fetchTemples() {
temples.value = await listTemples();
if (!localStorage.getItem(CURRENT_TEMPLE_ID_KEY) && temples.value.length > 0) {
const firstTempleId = String(temples.value[0].id);
localStorage.setItem(CURRENT_TEMPLE_ID_KEY, firstTempleId);
currentTempleId.value = firstTempleId;
}
}
onMounted(fetchTemples);
</script>
<template>
<a-layout class="app-shell">
<a-layout-sider class="sidebar" :width="232">
<div class="brand">
<div class="brand-mark">F</div>
<div>
<div class="brand-name">{{ appConfig.name }}</div>
<div class="brand-subtitle">{{ appConfig.subtitle }}</div>
</div>
</div>
<a-menu
class="side-menu"
mode="inline"
theme="light"
:selected-keys="selectedKeys"
>
<a-menu-item key="temples" @click="openRoute('/temples')">
<template #icon><BankOutlined /></template>
寺院管理
</a-menu-item>
<a-menu-item key="products" @click="openRoute('/products')">
<template #icon><ShoppingOutlined /></template>
商品管理
</a-menu-item>
<a-menu-item key="orders" @click="openRoute('/orders')">
<template #icon><FileTextOutlined /></template>
订单管理
</a-menu-item>
<a-menu-item key="ritual-services" @click="openRoute('/ritual-services')">
<template #icon><ProfileOutlined /></template>
法事管理
</a-menu-item>
<a-menu-item key="users" @click="openRoute('/users')">
<template #icon><TeamOutlined /></template>
用户管理
</a-menu-item>
<a-menu-item key="todos" @click="openRoute('/todos')">
<template #icon><ProfileOutlined /></template>
Todo 管理
</a-menu-item>
</a-menu>
</a-layout-sider>
<a-layout>
<a-layout-header class="topbar">
<div />
<a-space>
<a-select
class="temple-selector"
:options="templeOptions"
:value="currentTempleId"
placeholder="选择寺院"
@change="changeTemple"
/>
<a-button type="link" @click="submitLogout">
<template #icon><LoginOutlined /></template>
退出登录
</a-button>
</a-space>
</a-layout-header>
<a-layout-content class="content">
<a-breadcrumb class="breadcrumb">
<a-breadcrumb-item v-for="item in breadcrumbs" :key="item.path">
{{ item.title }}
</a-breadcrumb-item>
</a-breadcrumb>
<router-view />
</a-layout-content>
</a-layout>
</a-layout>
</template>