This commit is contained in:
wenfp
2026-07-27 16:36:33 +08:00
parent 53f48de2b7
commit 7f819cd775
19 changed files with 623 additions and 173 deletions
+26 -4
View File
@@ -1,8 +1,10 @@
<script setup lang="ts">
import {
BankOutlined,
AppstoreOutlined,
FileTextOutlined,
LoginOutlined,
PictureOutlined,
ProfileOutlined,
ShoppingOutlined,
TeamOutlined,
@@ -94,6 +96,18 @@ onMounted(fetchTemples);
<template #icon><ShoppingOutlined /></template>
商品管理
</a-menu-item>
<a-menu-item key="feature-icons" @click="openRoute('/feature-icons')">
<template #icon><AppstoreOutlined /></template>
图标管理
</a-menu-item>
<a-menu-item key="ad-slots" @click="openRoute('/ad-slots')">
<template #icon><PictureOutlined /></template>
广告位管理
</a-menu-item>
<a-menu-item key="ads" @click="openRoute('/ads')">
<template #icon><PictureOutlined /></template>
广告管理
</a-menu-item>
<a-menu-item key="orders" @click="openRoute('/orders')">
<template #icon><FileTextOutlined /></template>
订单管理
@@ -120,10 +134,18 @@ onMounted(fetchTemples);
placeholder="选择寺院"
@change="changeTemple"
/>
<a-button type="link" @click="submitLogout">
<template #icon><LoginOutlined /></template>
退出登录
</a-button>
<a-popconfirm
title="确认退出登录?"
ok-text="退出"
cancel-text="取消"
placement="bottomRight"
@confirm="submitLogout"
>
<a-button type="link">
<template #icon><LoginOutlined /></template>
退出登录
</a-button>
</a-popconfirm>
</a-space>
</a-layout-header>
+56 -2
View File
@@ -1,4 +1,27 @@
import Antd from 'ant-design-vue';
import Avatar from 'ant-design-vue/es/avatar';
import Breadcrumb from 'ant-design-vue/es/breadcrumb';
import Button from 'ant-design-vue/es/button';
import Col from 'ant-design-vue/es/col';
import DatePicker from 'ant-design-vue/es/date-picker';
import Form from 'ant-design-vue/es/form';
import Image from 'ant-design-vue/es/image';
import Input from 'ant-design-vue/es/input';
import InputNumber from 'ant-design-vue/es/input-number';
import Layout from 'ant-design-vue/es/layout';
import Menu from 'ant-design-vue/es/menu';
import Modal from 'ant-design-vue/es/modal';
import Popconfirm from 'ant-design-vue/es/popconfirm';
import Row from 'ant-design-vue/es/row';
import Segmented from 'ant-design-vue/es/segmented';
import Select from 'ant-design-vue/es/select';
import Space from 'ant-design-vue/es/space';
import Spin from 'ant-design-vue/es/spin';
import Switch from 'ant-design-vue/es/switch';
import Table from 'ant-design-vue/es/table';
import Tabs from 'ant-design-vue/es/tabs';
import Tag from 'ant-design-vue/es/tag';
import Tooltip from 'ant-design-vue/es/tooltip';
import Upload from 'ant-design-vue/es/upload';
import { createApp } from 'vue';
import 'ant-design-vue/dist/reset.css';
@@ -10,4 +33,35 @@ import router from './router';
document.title = appConfig.name;
createApp(App).use(router).use(Antd).mount('#app');
const app = createApp(App);
[
Avatar,
Breadcrumb,
Button,
Col,
DatePicker,
Form,
Image,
Input,
InputNumber,
Layout,
Menu,
Modal,
Popconfirm,
Row,
Segmented,
Select,
Space,
Spin,
Switch,
Table,
Tabs,
Tag,
Tooltip,
Upload,
].forEach((component) => {
app.use(component);
});
app.use(router).mount('#app');
+39 -8
View File
@@ -1,14 +1,18 @@
import { createRouter, createWebHistory } from 'vue-router';
import { clearAuthUser, getCurrentUser, getStoredUser, storeAuthUser } from '@/api/auth';
import AdminLayout from '@/layouts/AdminLayout.vue';
import LoginPage from '@/views/login/LoginPage.vue';
import OrderManagement from '@/views/orders/OrderManagement.vue';
import ProductDetail from '@/views/products/ProductDetail.vue';
import ProductManagement from '@/views/products/ProductManagement.vue';
import RitualManagement from '@/views/rituals/RitualManagement.vue';
import TempleManagement from '@/views/temples/TempleManagement.vue';
import UserManagement from '@/views/users/UserManagement.vue';
const AdminLayout = () => import('@/layouts/AdminLayout.vue');
const AdSlotManagement = () => import('@/views/ad-slots/AdSlotManagement.vue');
const AdManagement = () => import('@/views/ads/AdManagement.vue');
const FeatureIconManagement = () => import('@/views/feature-icons/FeatureIconManagement.vue');
const LoginPage = () => import('@/views/login/LoginPage.vue');
const OrderManagement = () => import('@/views/orders/OrderManagement.vue');
const ProductDetail = () => import('@/views/products/ProductDetail.vue');
const ProductManagement = () => import('@/views/products/ProductManagement.vue');
const RitualManagement = () => import('@/views/rituals/RitualManagement.vue');
const TempleManagement = () => import('@/views/temples/TempleManagement.vue');
const UserManagement = () => import('@/views/users/UserManagement.vue');
export const router = createRouter({
history: createWebHistory(),
@@ -68,6 +72,33 @@ export const router = createRouter({
title: '编辑商品',
},
},
{
path: 'feature-icons',
name: 'feature-icons',
component: FeatureIconManagement,
meta: {
module: 'feature-icons',
title: '图标管理',
},
},
{
path: 'ad-slots',
name: 'ad-slots',
component: AdSlotManagement,
meta: {
module: 'ad-slots',
title: '广告位管理',
},
},
{
path: 'ads',
name: 'ads',
component: AdManagement,
meta: {
module: 'ads',
title: '广告管理',
},
},
{
path: 'orders',
name: 'orders',
+165 -150
View File
@@ -1,206 +1,221 @@
:root {
color: #1f2937;
font-family:
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
sans-serif;
background: #f3f5f8;
color: #1f2937;
font-family:
Inter,
ui-sans-serif,
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif;
background: #f3f5f8;
}
* {
box-sizing: border-box;
box-sizing: border-box;
}
body {
margin: 0;
min-width: 320px;
margin: 0;
min-width: 320px;
}
.app-shell {
min-height: 100vh;
min-height: 100vh;
}
.sidebar {
background: #fff !important;
border-right: 1px solid #e5e7eb;
background: #fff !important;
border-right: 1px solid #e5e7eb;
}
.brand {
align-items: center;
border-bottom: 1px solid #e5e7eb;
display: flex;
gap: 12px;
height: 44px;
padding: 0 20px;
align-items: center;
border-bottom: 1px solid #e5e7eb;
display: flex;
gap: 12px;
height: 44px;
padding: 0 20px;
}
.brand-mark {
align-items: center;
background: #1677ff;
border-radius: 6px;
color: #fff;
display: flex;
font-weight: 700;
height: 32px;
justify-content: center;
width: 32px;
align-items: center;
background: #1677ff;
border-radius: 6px;
color: #fff;
display: flex;
font-weight: 700;
height: 32px;
justify-content: center;
width: 32px;
}
.brand-name {
color: #111827;
font-size: 15px;
font-weight: 700;
line-height: 20px;
color: #111827;
font-size: 15px;
font-weight: 700;
line-height: 20px;
}
.brand-subtitle {
color: #6b7280;
font-size: 12px;
line-height: 18px;
color: #6b7280;
font-size: 12px;
line-height: 18px;
}
.side-menu {
background: transparent;
border-inline-end: 0 !important;
background: transparent;
border-inline-end: 0 !important;
}
.topbar {
align-items: center;
background: #fff !important;
border-bottom: 1px solid #e5e7eb;
color: #1f2937;
display: flex;
height: 64px;
justify-content: space-between;
padding: 0 24px;
align-items: center;
background: #fff !important;
border-bottom: 1px solid #e5e7eb;
color: #1f2937;
display: flex;
justify-content: space-between;
padding: 0 14px;
height: 44px !important;
}
.content {
padding: 14px;
padding: 14px;
}
.breadcrumb {
margin-bottom: 14px;
margin-bottom: 14px;
}
.temple-selector {
width: 160px;
width: 160px;
}
.workspace {
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 20px;
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 20px;
}
.page-heading {
align-items: center;
display: flex;
gap: 16px;
justify-content: space-between;
margin-bottom: 18px;
align-items: center;
display: flex;
gap: 16px;
justify-content: space-between;
margin-bottom: 18px;
}
.page-heading h1 {
font-size: 20px;
line-height: 28px;
margin: 0;
font-size: 20px;
line-height: 28px;
margin: 0;
}
.page-heading p {
color: #6b7280;
font-size: 13px;
line-height: 20px;
margin: 4px 0 0;
color: #6b7280;
font-size: 13px;
line-height: 20px;
margin: 4px 0 0;
}
.query-bar {
margin-bottom: 16px;
margin-bottom: 16px;
}
.table-toolbar {
display: flex;
justify-content: flex-end;
margin-bottom: 12px;
display: flex;
justify-content: flex-end;
margin-bottom: 12px;
}
.square-preview,
.square-preview img {
border-radius: 6px;
object-fit: cover;
}
.ad-preview,
.ad-preview img {
border-radius: 6px;
object-fit: cover;
}
.login-page {
align-items: center;
background:
linear-gradient(135deg, rgba(22, 119, 255, 0.12), transparent 36%),
#f3f5f8;
display: flex;
min-height: 100vh;
padding: 24px;
align-items: center;
background: linear-gradient(135deg, rgba(22, 119, 255, 0.12), transparent 36%), #f3f5f8;
display: flex;
min-height: 100vh;
padding: 24px;
}
.login-panel {
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 8px;
box-shadow: 0 18px 45px rgba(15, 23, 42, 0.08);
margin: 0 auto;
max-width: 420px;
padding: 28px;
width: 100%;
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 8px;
box-shadow: 0 18px 45px rgba(15, 23, 42, 0.08);
margin: 0 auto;
max-width: 420px;
padding: 28px;
width: 100%;
}
.login-brand {
align-items: center;
display: flex;
gap: 14px;
margin-bottom: 28px;
align-items: center;
display: flex;
gap: 14px;
margin-bottom: 28px;
}
.login-brand h1 {
font-size: 22px;
line-height: 30px;
margin: 0;
font-size: 22px;
line-height: 30px;
margin: 0;
}
.login-brand p {
color: #6b7280;
font-size: 13px;
line-height: 20px;
margin: 2px 0 0;
color: #6b7280;
font-size: 13px;
line-height: 20px;
margin: 2px 0 0;
}
.login-form {
width: 100%;
width: 100%;
}
.login-options {
align-items: center;
display: flex;
justify-content: space-between;
margin: -4px 0 18px;
align-items: center;
display: flex;
justify-content: space-between;
margin: -4px 0 18px;
}
.captcha-row {
display: grid;
gap: 10px;
grid-template-columns: minmax(0, 1fr) 132px;
display: grid;
gap: 10px;
grid-template-columns: minmax(0, 1fr) 132px;
}
.empty-icon {
color: #1677ff;
font-size: 56px;
color: #1677ff;
font-size: 56px;
}
.full-width-control {
width: 100%;
width: 100%;
}
.upload-text {
margin-top: 8px;
margin-top: 8px;
}
.product-detail-page {
display: flex;
flex-direction: column;
height: calc(100vh - 142px);
height: calc(100dvh - 142px);
overflow: hidden;
display: flex;
flex-direction: column;
height: calc(100vh - 142px);
height: calc(100dvh - 142px);
overflow: hidden;
}
.product-detail-body,
@@ -208,72 +223,72 @@ body {
.product-detail-body .ant-spin-container,
.product-detail-form,
.product-detail-tabs {
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
}
.product-detail-tabs .ant-tabs-content-holder {
flex: 1;
min-height: 0;
overflow: hidden;
flex: 1;
min-height: 0;
overflow: hidden;
}
.product-detail-tabs .ant-tabs-content {
height: 100%;
height: 100%;
}
.product-detail-tabs .ant-tabs-tabpane {
height: 100%;
overflow: auto;
height: 100%;
overflow: auto;
}
.product-rich-editor {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
}
.product-rich-editor .ql-container {
flex: 1;
min-height: 0;
flex: 1;
min-height: 0;
}
.product-rich-editor .ql-editor {
min-height: 0;
overflow-y: auto;
min-height: 0;
overflow-y: auto;
}
@media (max-width: 768px) {
.app-shell {
display: block;
}
.app-shell {
display: block;
}
.sidebar {
display: none;
}
.sidebar {
display: none;
}
.topbar,
.page-heading {
align-items: flex-start;
flex-direction: column;
}
.topbar,
.page-heading {
align-items: flex-start;
flex-direction: column;
}
.content {
padding: 2px;
}
.content {
padding: 2px;
}
.workspace {
padding: 14px;
}
.workspace {
padding: 14px;
}
.product-rich-editor {
min-height: 360px;
}
.product-rich-editor {
min-height: 360px;
}
.login-page {
padding: 16px;
}
.login-page {
padding: 16px;
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { LockOutlined, ReloadOutlined, SafetyCertificateOutlined, UserOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import message from 'ant-design-vue/es/message';
import { onMounted, reactive, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
+2 -1
View File
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons-vue';
import { Modal, message } from 'ant-design-vue';
import Modal from 'ant-design-vue/es/modal';
import message from 'ant-design-vue/es/message';
import type { Rule } from 'ant-design-vue/es/form';
import type { ColumnsType } from 'ant-design-vue/es/table';
import { computed, onMounted, reactive, ref } from 'vue';
+1 -1
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { ArrowLeftOutlined, PlusOutlined, SaveOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import message from 'ant-design-vue/es/message';
import type { Rule } from 'ant-design-vue/es/form';
import type { UploadFile } from 'ant-design-vue/es/upload/interface';
import type { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons-vue';
import { Modal, message } from 'ant-design-vue';
import Modal from 'ant-design-vue/es/modal';
import message from 'ant-design-vue/es/message';
import type { ColumnsType } from 'ant-design-vue/es/table';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
+2 -1
View File
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons-vue';
import { Modal, message } from 'ant-design-vue';
import Modal from 'ant-design-vue/es/modal';
import message from 'ant-design-vue/es/message';
import type { Rule } from 'ant-design-vue/es/form';
import type { ColumnsType } from 'ant-design-vue/es/table';
import { computed, onMounted, reactive, ref } from 'vue';
+2 -1
View File
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons-vue';
import { Modal, message } from 'ant-design-vue';
import Modal from 'ant-design-vue/es/modal';
import message from 'ant-design-vue/es/message';
import type { Rule } from 'ant-design-vue/es/form';
import type { ColumnsType } from 'ant-design-vue/es/table';
import { computed, onMounted, reactive, ref } from 'vue';
+2 -1
View File
@@ -6,7 +6,8 @@ import {
ReloadOutlined,
UserOutlined,
} from '@ant-design/icons-vue';
import { Modal, message } from 'ant-design-vue';
import Modal from 'ant-design-vue/es/modal';
import message from 'ant-design-vue/es/message';
import type { Rule } from 'ant-design-vue/es/form';
import type { ColumnsType } from 'ant-design-vue/es/table';
import { computed, onMounted, reactive, ref } from 'vue';