feat:更新首页

This commit is contained in:
fangyunong 2025-07-05 14:11:07 +08:00
parent a29bba3406
commit 5acb144b21
13 changed files with 945 additions and 9 deletions

View File

@ -11,6 +11,7 @@
"dependencies": {
"@auth0/auth0-vue": "^2.4.0",
"axios": "^1.7.2",
"echarts": "^5.6.0",
"ftp-deploy": "^2.4.7",
"js-cookie": "^3.0.5",
"naive-ui": "^2.39.0",

66
pnpm-lock.yaml generated
View File

@ -14,6 +14,9 @@ importers:
axios:
specifier: ^1.7.2
version: 1.10.0
echarts:
specifier: ^5.6.0
version: 5.6.0
ftp-deploy:
specifier: ^2.4.7
version: 2.4.7(promise-ftp-common@1.1.5)
@ -40,7 +43,7 @@ importers:
version: 14.2.1(sass@1.77.2)
unplugin-auto-import:
specifier: ^0.18.0
version: 0.18.6(rollup@4.44.1)
version: 0.18.6(@vueuse/core@10.11.1(vue@3.5.17(typescript@5.8.3)))(rollup@4.44.1)
vfonts:
specifier: ^0.0.3
version: 0.0.3
@ -481,6 +484,9 @@ packages:
'@types/node@24.0.7':
resolution: {integrity: sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw==}
'@types/web-bluetooth@0.0.20':
resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
'@vicons/ionicons5@0.12.0':
resolution: {integrity: sha512-Iy1EUVRpX0WWxeu1VIReR1zsZLMc4fqpt223czR+Rpnrwu7pt46nbnC2ycO7ItI/uqDLJxnbcMC7FujKs9IfFA==}
@ -559,6 +565,15 @@ packages:
'@vue/shared@3.5.17':
resolution: {integrity: sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==}
'@vueuse/core@10.11.1':
resolution: {integrity: sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==}
'@vueuse/metadata@10.11.1':
resolution: {integrity: sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==}
'@vueuse/shared@10.11.1':
resolution: {integrity: sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==}
acorn@8.15.0:
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
engines: {node: '>=0.4.0'}
@ -687,6 +702,9 @@ packages:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
echarts@5.6.0:
resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==}
electron-to-chromium@1.5.177:
resolution: {integrity: sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g==}
@ -1114,6 +1132,9 @@ packages:
treemate@0.3.11:
resolution: {integrity: sha512-M8RGFoKtZ8dF+iwJfAJTOH/SM4KluKOKRJpjCMhI8bG3qB74zrFoArKZ62ll0Fr3mqkMJiQOmWYkdYgDeITYQg==}
tslib@2.3.0:
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
tweetnacl@0.14.5:
resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
@ -1251,6 +1272,9 @@ packages:
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
zrender@5.6.1:
resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==}
snapshots:
'@ampproject/remapping@2.3.0':
@ -1576,6 +1600,9 @@ snapshots:
undici-types: 7.8.0
optional: true
'@types/web-bluetooth@0.0.20':
optional: true
'@vicons/ionicons5@0.12.0': {}
'@vitejs/plugin-vue@5.2.4(vite@5.3.4(@types/node@24.0.7)(sass@1.77.2))(vue@3.5.17(typescript@5.8.3))':
@ -1698,6 +1725,28 @@ snapshots:
'@vue/shared@3.5.17': {}
'@vueuse/core@10.11.1(vue@3.5.17(typescript@5.8.3))':
dependencies:
'@types/web-bluetooth': 0.0.20
'@vueuse/metadata': 10.11.1
'@vueuse/shared': 10.11.1(vue@3.5.17(typescript@5.8.3))
vue-demi: 0.14.10(vue@3.5.17(typescript@5.8.3))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
optional: true
'@vueuse/metadata@10.11.1':
optional: true
'@vueuse/shared@10.11.1(vue@3.5.17(typescript@5.8.3))':
dependencies:
vue-demi: 0.14.10(vue@3.5.17(typescript@5.8.3))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
optional: true
acorn@8.15.0: {}
alien-signals@1.0.13: {}
@ -1826,6 +1875,11 @@ snapshots:
es-errors: 1.3.0
gopd: 1.2.0
echarts@5.6.0:
dependencies:
tslib: 2.3.0
zrender: 5.6.1
electron-to-chromium@1.5.177: {}
entities@4.5.0: {}
@ -2263,6 +2317,8 @@ snapshots:
treemate@0.3.11: {}
tslib@2.3.0: {}
tweetnacl@0.14.5: {}
typedarray@0.0.6: {}
@ -2293,7 +2349,7 @@ snapshots:
transitivePeerDependencies:
- rollup
unplugin-auto-import@0.18.6(rollup@4.44.1):
unplugin-auto-import@0.18.6(@vueuse/core@10.11.1(vue@3.5.17(typescript@5.8.3)))(rollup@4.44.1):
dependencies:
'@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.2.0(rollup@4.44.1)
@ -2303,6 +2359,8 @@ snapshots:
minimatch: 9.0.5
unimport: 3.14.6(rollup@4.44.1)
unplugin: 1.16.1
optionalDependencies:
'@vueuse/core': 10.11.1(vue@3.5.17(typescript@5.8.3))
transitivePeerDependencies:
- rollup
@ -2386,3 +2444,7 @@ snapshots:
xregexp@2.0.0: {}
yallist@3.1.1: {}
zrender@5.6.1:
dependencies:
tslib: 2.3.0

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1751689452739" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6754" width="16" height="16" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M510.0032 492.9536c-12.16 0-24.3456-2.3808-35.9424-7.1168L71.7824 300.5952c-11.3408-4.6336-18.816-15.5648-19.072-27.8016s6.784-23.4496 17.92-28.544l400.1536-183.296a100.1728 100.1728 0 0 1 82.7648-0.3072l398.1056 178.8416c11.1616 5.0176 18.2784 16.1792 18.1248 28.416s-7.5776 23.2192-18.8672 27.9296l-404.3264 189.7216a94.26944 94.26944 0 0 1-36.5824 7.3984zM160.64 270.592l336.7424 158.3872a33.0496 33.0496 0 0 0 25.5232-0.1024l338.9952-162.3808-333.5424-149.8112a38.6688 38.6688 0 0 0-32 0.128L160.64 270.592z" fill="#3D8EFF" p-id="6755"></path><path d="M510.1568 722.7648c-14.4896 0-28.9536-3.3536-42.1632-10.0864L68.3264 509.0816c-8.576-4.3776-15.0784-12.2624-16.9472-21.6832a30.7072 30.7072 0 0 1 15.0272-32.8192l189.6704-106.9568c19.5584-11.0336 44.3136-4.1216 55.3472 15.4368l10.2144 18.1248-175.1808 98.7904L495.872 657.92a31.5392 31.5392 0 0 0 28.672-0.0512l354.0224-181.9136-175.9488-100.736 10.3424-18.0736c11.1616-19.4816 35.968-26.2144 55.4496-15.0784l189.7984 108.672c9.7792 5.6064 15.6928 16.1024 15.4368 27.3664s-6.656 21.4784-16.6656 26.624l-404.352 207.7696a92.53376 92.53376 0 0 1-42.4704 10.2656z" fill="#3D8EFF" p-id="6756"></path><path d="M512.2048 975.9744c-4.7872 0-9.5744-1.1264-13.952-3.3536L70.2464 754.5856c-8.576-4.3776-15.0784-12.2624-16.9472-21.7088a30.72512 30.72512 0 0 1 15.0272-32.8192l192.1536-108.3648c18.176-10.24 41.2416-3.8144 51.4816 14.3616l11.6224 20.608-175.1808 98.7904 363.7504 185.2928 368.3584-189.2608-175.9488-100.736 11.7504-20.5312c10.368-18.1248 33.4592-24.3968 51.584-14.0288l192.2816 110.08c9.7792 5.6064 15.6928 16.1024 15.4368 27.3664a30.72 30.72 0 0 1-16.6656 26.624l-432.6656 222.3104a31.0272 31.0272 0 0 1-14.08 3.4048z" fill="#3D8EFF" p-id="6757"></path></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1751689762805" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11546" width="16" height="16" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M720.213333 269.653333c30.72 0 51.2-20.48 54.613334-47.786666v-170.666667c0-27.306667-20.48-47.786667-51.2-47.786667-27.306667 0-51.2 20.48-51.2 47.786667v170.666667c0 23.893333 20.48 44.373333 47.786666 47.786666zM300.373333 269.653333c30.72 0 51.2-20.48 54.613334-47.786666v-170.666667C351.573333 23.893333 331.093333 0 303.786667 0 273.066667 0 252.586667 20.48 252.586667 47.786667v170.666666c0 27.306667 20.48 47.786667 47.786666 51.2zM409.6 85.333333h201.386667v102.4H409.6z" fill="#FFFFFF" p-id="11547"></path><path d="M890.88 85.333333h-61.44v102.4H887.466667c20.48 0 34.133333 17.066667 34.133333 34.133334v215.04l3.413333 447.146666c0 20.48-17.066667 37.546667-37.546666 37.546667H136.533333c-20.48 0-37.546667-17.066667-37.546666-37.546667L102.4 436.906667V221.866667c0-17.066667 13.653333-34.133333 34.133333-34.133334h58.026667v-102.4H133.12C61.44 85.333333 0 143.36 0 218.453333v672.426667C0 962.56 61.44 1024 133.12 1024h757.76c71.68 0 133.12-61.44 133.12-133.12V218.453333c0-75.093333-61.44-133.12-133.12-133.12z" fill="#FFFFFF" p-id="11548"></path><path d="M682.666667 624.64c27.306667 0 51.2-23.893333 51.2-51.2s-23.893333-51.2-51.2-51.2h-47.786667l81.92-81.92c20.48-20.48 20.48-51.2 0-71.68-20.48-20.48-51.2-20.48-71.68 0L512 498.346667l-133.12-133.12c-20.48-20.48-51.2-20.48-71.68 0-20.48 20.48-20.48 51.2 0 71.68l81.92 81.92H341.333333c-27.306667 0-51.2 23.893333-51.2 51.2s23.893333 51.2 51.2 51.2h119.466667V682.666667H341.333333c-27.306667 0-51.2 23.893333-51.2 51.2S314.026667 785.066667 341.333333 785.066667h119.466667v37.546666c0 27.306667 23.893333 51.2 51.2 51.2s51.2-23.893333 51.2-51.2V785.066667H682.666667c27.306667 0 51.2-23.893333 51.2-51.2S709.973333 682.666667 682.666667 682.666667h-119.466667v-61.44H682.666667z" fill="#FFFFFF" p-id="11549"></path></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1751687644150" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5527" width="24" height="24" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M701.3376 147.2c66.048 0 118.8608 55.5008 121.6512 123.904l0.128 5.7344v444.7232c0 69.12-51.0208 126.464-116.3008 129.5104l-5.4784 0.128H322.6624c-66.048 0-118.8608-55.5008-121.6512-123.904l-0.128-5.7344v-83.5328a32 32 0 0 1 63.8464-3.2768l0.1536 3.2768v83.5328c0 35.328 24.4224 63.3088 54.0416 65.5104l3.7376 0.128h378.6752c30.0288 0 55.6544-26.5472 57.6512-61.2608l0.128-4.3776V276.8384c0-35.328-24.4224-63.3088-54.0416-65.5104l-3.7376-0.128H322.6624c-30.0288 0-55.6544 26.5472-57.6512 61.2608l-0.128 4.3776v211.1488a32 32 0 0 1-63.8208 3.2768l-0.1792-3.2768v-211.1488c0-69.12 51.0208-126.464 116.3008-129.5104l5.4784-0.128h378.6752z" fill="#FFFFFF" p-id="5528"></path><path d="M440.2688 352.512a25.6 25.6 0 0 1 39.2448 32.7168l-2.048 2.4832-56.2176 59.4176a25.6 25.6 0 0 1-32.4096 3.968l-2.4832-1.8176-36.608-30.2592a25.6 25.6 0 0 1 30.0032-41.3696l2.5856 1.8944 18.1504 15.0016 39.7824-42.0352zM440.2688 561.664a25.6 25.6 0 0 1 39.2448 32.7168l-2.048 2.4576-56.2176 59.4432a25.6 25.6 0 0 1-32.4096 3.9424l-2.4832-1.792-36.608-30.2848a25.6 25.6 0 0 1 30.0032-41.344l2.5856 1.8944 18.1504 14.976 39.7824-42.0096zM668.5696 384a25.6 25.6 0 0 1 2.9952 51.0208l-2.9952 0.1792h-138.24a25.6 25.6 0 0 1-2.9696-51.0208l2.9696-0.1792h138.24zM668.5696 583.3728a25.6 25.6 0 0 1 2.9952 51.0208l-2.9952 0.1792h-142.08a25.6 25.6 0 0 1-2.9696-51.0464l2.9696-0.1536h142.08z" fill="#FFFFFF" p-id="5529"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -2,3 +2,6 @@ $primaryColor: #3D8EFF; // 主色保持不变的蓝色
$primaryColorHover: #6AA1FF; // 比主色亮20%的浅蓝色
$primaryColorPressed: #2B7AEB;// 比主色深10%的深蓝色
$primaryColorSuppl: #5A95FF; // 介于主色和hover之间的蓝色
// 字体相关颜色
$titleTextColor:#808080; //标题颜色
$dashLineColor:#E7E7E7; //border-color的颜色

View File

@ -0,0 +1,153 @@
<template>
<div class="header__item">
<header>
<div class="icon">
<img src="@/assets/icons/order.svg">
</div>
<p class="title">今日新增订单</p>
</header>
<footer>
<p class="count">15</p>
<p class="compare__text">
<span style="color:#f40">10%</span>
<!-- <span style="color:#0da777"></span> -->
<span>相较于昨日</span>
</p>
</footer>
</div>
<div class="header__item">
<header>
<div class="icon">
<img src="@/assets/icons/order.svg">
</div>
<p class="title">今日新增陪玩</p>
</header>
<footer>
<p class="count">12</p>
<p class="compare__text">
<span style="color:#f40">2%</span>
<!-- <span style="color:#0da777"></span> -->
<span>相较于昨日</span>
</p>
</footer>
</div>
<div class="header__item">
<header>
<div class="icon">
<img src="@/assets/icons/money.svg">
</div>
<p class="title">今日订单金额</p>
</header>
<footer>
<p class="count">1,238</p>
<p class="compare__text">
<span style="color:#f40">10%</span>
<!-- <span style="color:#0da777"></span> -->
<span>相较于昨日</span>
</p>
</footer>
</div>
<div class="header__item">
<header>
<div class="icon">
<img src="@/assets/icons/order.svg">
</div>
<p class="title">今日活跃代理数</p>
</header>
<footer>
<p class="count">8</p>
<p class="compare__text">
<!-- <span style="color:#f40">10%</span> -->
<span style="color:#0da777">5%</span>
<span>相较于昨日</span>
</p>
</footer>
</div>
<div class="header__item">
<header>
<div class="icon">
<img src="@/assets/icons/order.svg">
</div>
<p class="title">本月订单总数</p>
</header>
<footer>
<p class="count">1,558</p>
<p class="compare__text">
<span style="color:#f40">2%</span>
<!-- <span style="color:#0da777"></span> -->
<span>相较于上月</span>
</p>
</footer>
</div>
</template>
<script setup lang='ts'>
</script>
<style scoped lang='scss'>
$colors: #00b882, #4d76eb, #db4c4d, #dc6333, #897dd7;
.header__item {
border-radius: 4px;
background: #fff;
height: 100px;
padding: 0 12px;
// Loop through each item and apply colors
@for $i from 1 through 5 {
&:nth-child(#{$i}) {
border-right: 3px solid nth($colors, $i);
header .icon {
background: nth($colors, $i);
// Create a lighter version of the color for box-shadow
box-shadow: 0 2px 8px rgba(nth($colors, $i), 0.15);
}
}
}
header {
height: 60px;
display: flex;
align-items: center;
gap: 6px;
border-bottom: 1px solid $dashLineColor;
box-sizing: border-box;
.title {
font-size: 14px;
font-weight: bold;
color: $titleTextColor;
}
.icon {
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
width: 25px;
height: 25px;
img {
width: 16px;
height: 16px;
}
}
}
footer {
height: 40px;
display: flex;
align-items: center;
justify-content: space-between;
.count {
font-weight: bold;
}
.compare__text {
font-size: 11px;
color: #a7a5a6;
font-weight: 600;
}
}
}
</style>

View File

@ -0,0 +1,193 @@
<template>
<header>
<img src="@/assets/icons/mainproject.svg">
<p class="title">周订单统计</p>
</header>
<div class="line" ref="chartRef"></div>
</template>
<script setup lang='ts'>
import * as echarts from 'echarts';
const chartRef = ref<HTMLElement>();
onMounted(() => {
if (!chartRef.value) return;
const chart = echarts.init(chartRef.value);
// Mock data for the past 7 days
const dates = [];
const orderCounts = [];
const orderAmounts = [];
// Generate data for the last 7 days
for (let i = 6; i >= 0; i--) {
const date = new Date();
date.setDate(date.getDate() - i);
dates.push(`${date.getMonth() + 1}-${date.getDate()}`);
// Random mock data
orderCounts.push(Math.floor(Math.random() * 200) + 50);
orderAmounts.push(Math.floor(Math.random() * 50000) + 10000);
}
const option = {
color: ['#3D8EFF', '#FF9843'], // Blue for count, orange for amount
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['订单数量', '订单金额'],
bottom: 0,
itemGap: 20
},
grid: {
left: '3%',
right: '4%',
bottom: '12%',
top: '5%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: dates,
axisLine: {
lineStyle: {
color: '#E5E5E5'
}
},
axisLabel: {
color: '#666'
}
},
yAxis: [
{
type: 'value',
name: '订单数量',
axisLine: {
show: true,
lineStyle: {
color: '#E5E5E5'
}
},
axisLabel: {
color: '#666',
formatter: '{value}'
},
splitLine: {
lineStyle: {
color: '#F5F5F5'
}
}
},
{
type: 'value',
name: '订单金额',
axisLine: {
show: true,
lineStyle: {
color: '#E5E5E5'
}
},
axisLabel: {
color: '#666',
formatter: '¥{value}'
},
splitLine: {
show: false
}
}
],
series: [
{
name: '订单数量',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 8,
lineStyle: {
width: 3,
color: '#3D8EFF'
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(61, 142, 255, 0.3)'
},
{
offset: 1,
color: 'rgba(61, 142, 255, 0.1)'
}
])
},
data: orderCounts
},
{
name: '订单金额',
type: 'line',
yAxisIndex: 1,
smooth: true,
symbol: 'circle',
symbolSize: 8,
lineStyle: {
width: 3,
color: '#FF9843'
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(255, 152, 67, 0.3)'
},
{
offset: 1,
color: 'rgba(255, 152, 67, 0.1)'
}
])
},
data: orderAmounts
}
]
};
chart.setOption(option);
// Handle window resize
window.addEventListener('resize', function() {
chart.resize();
});
});
</script>
<style scoped lang='scss'>
header {
height: 40px;
display: flex;
align-items: center;
padding: 0 16px;
border-bottom: 1px solid $dashLineColor;
gap:4px;
img {
width: 16px;
height: 16px;
}
.title {
color: $titleTextColor;
font-weight: bold;
}
}
.line {
height: 400px;
margin: 0 auto;
padding:16px
}
</style>

View File

@ -0,0 +1,93 @@
<template>
<n-tabs type="line" animated>
<n-tab-pane name="oasis" tab="订单进度">
<div class="panel">
<div class="panel-item">
<header>
<p class="name">罗澜</p>
<img src="@/assets/images/luolan_avatar.jpg">
</header>
<footer>
<div class="info">
<p class="task"> 巅峰七阶A牌教授</p>
<n-tag type="success" size="small" style="width:fit-content">
已完成
<template #icon>
<n-icon :component="CheckmarkCircle" />
</template>
</n-tag>
<p class="time">2025-07-05</p>
</div>
<img src="@/assets/icons/mainproject.svg">
</footer>
</div>
</div>
</n-tab-pane>
<n-tab-pane name="the beatles" tab="热门陪玩">
Hey Jude
</n-tab-pane>
</n-tabs>
</template>
<script setup lang='ts'>
import { CheckmarkCircle } from '@vicons/ionicons5'
</script>
<style scoped lang='scss'>
.panel {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
.panel-item {
background: #f5f5f5;
width: 100%;
height: 120px;
padding: 0 12px;
border-radius: 4px;
header {
display: flex;
justify-content: space-between;
align-items: center;
height: 40px;
border-bottom: 1px solid $dashLineColor;
.name {
font-weight: bold;
font-size: 14px;
color: $titleTextColor;
}
img {
height: 25px;
width: 25px;
border-radius: 4px;
}
}
footer {
height: 80px;
display: flex;
align-items: center;
justify-content: space-between;
.info {
display: flex;
flex-direction: column;
gap: 4px;
.time {
color: #999;
font-size: 12px;
}
}
img {
width: 50px;
height: 50px;
}
}
}
}
</style>

View File

@ -0,0 +1,39 @@
<template>
<header>
<img src="@/assets/icons/mainproject.svg">
<p class="title">系统行为日志</p>
</header>
<main>
<n-timeline>
<n-timeline-item type="success" title="login" content="用户罗澜登录了系统" time="2025-07-05 11:46" />
<n-timeline-item type="error" title="cancel" content="用户落雪取消了繁星发起的订单uuid为029201919210" time="2025-07-03 20:46" />
</n-timeline>
</main>
</template>
<script setup lang='ts'>
</script>
<style scoped lang='scss'>
header {
height: 40px;
display: flex;
align-items: center;
padding: 0 16px;
border-bottom: 1px solid $dashLineColor;
gap: 4px;
img {
width: 16px;
height: 16px;
}
.title {
color: $titleTextColor;
font-weight: bold;
}
}
main {
padding:16px;
}
</style>

View File

@ -0,0 +1,222 @@
<template>
<header>
<img src="@/assets/icons/mainproject.svg">
<p class="title">近三月陪玩团情况</p>
</header>
<div class="bar" ref="chartRef"></div>
</template>
<script setup lang='ts'>
import { onMounted, ref } from 'vue';
import * as echarts from 'echarts';
const chartRef = ref<HTMLElement>();
onMounted(() => {
if (!chartRef.value) return;
const chart = echarts.init(chartRef.value);
const weeks = [ '五月','六月', '七月'];
// Mock data
const orderCount = [125, 210, 180]; //
const playerCount = [80, 120, 95]; //
const orderAmount = [3560, 4820, 4150]; //
const agentCount = [15, 22, 18]; //
const option = {
color: ['#3D8EFF', '#00C4DF', '#FF9843', '#897DD7'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function(params: any[]) {
let result = params[0].axisValue + '<br/>';
params.forEach((item: any) => {
const value = item.seriesIndex === 2 ?
'¥' + item.value.toLocaleString() :
item.value + '个';
result += `${item.marker} ${item.seriesName}: <strong>${value}</strong><br/>`;
});
return result;
}
},
legend: {
data: ['销售订单数', '陪玩人数', '订单金额', '代理人数'],
bottom: 10,
itemGap: 20,
textStyle: {
color: '#666'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '15%',
top: '10%',
containLabel: true
},
xAxis: {
type: 'category',
data: weeks,
axisLine: {
lineStyle: {
color: '#E5E5E5'
}
},
axisLabel: {
color: '#666'
}
},
yAxis: [
{
type: 'value',
name: '数量(个)',
axisLine: {
show: true,
lineStyle: {
color: '#E5E5E5'
}
},
axisLabel: {
color: '#666',
formatter: '{value}'
},
splitLine: {
lineStyle: {
color: '#F5F5F5'
}
}
},
{
type: 'value',
name: '金额(元)',
axisLine: {
show: true,
lineStyle: {
color: '#E5E5E5'
}
},
axisLabel: {
color: '#666',
formatter: '¥{value}'
},
splitLine: {
show: false
}
}
],
series: [
{
name: '销售订单数',
type: 'bar',
barWidth: 16,
barGap: '10%',
barCategoryGap: '30%',
itemStyle: {
borderRadius: [4, 4, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#3D8EFF' },
{ offset: 1, color: '#8BB8FF' }
])
},
label: {
show: true,
position: 'top',
formatter: '{c}个'
},
data: orderCount
},
{
name: '陪玩人数',
type: 'bar',
barWidth: 16,
itemStyle: {
borderRadius: [4, 4, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#00C4DF' },
{ offset: 1, color: '#5BD9E9' }
])
},
label: {
show: true,
position: 'top',
formatter: '{c}个'
},
data: playerCount
},
{
name: '订单金额',
type: 'bar',
yAxisIndex: 1,
barWidth: 16,
itemStyle: {
borderRadius: [4, 4, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#FF9843' },
{ offset: 1, color: '#FFBB78' }
])
},
label: {
show: true,
position: 'top',
formatter: '¥{c}'
},
data: orderAmount
},
{
name: '代理人数',
type: 'bar',
barWidth: 16,
itemStyle: {
borderRadius: [4, 4, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#897DD7' },
{ offset: 1, color: '#B4ACEA' }
])
},
label: {
show: true,
position: 'top',
formatter: '{c}个'
},
data: agentCount
}
]
};
chart.setOption(option);
// Handle window resize
window.addEventListener('resize', function() {
chart.resize();
});
});
</script>
<style scoped lang='scss'>
header {
height: 40px;
display: flex;
align-items: center;
padding: 0 16px;
border-bottom: 1px solid $dashLineColor;
gap: 4px;
img {
width: 16px;
height: 16px;
}
.title {
color: $titleTextColor;
font-weight: bold;
}
}
.bar {
height: 400px;
margin: 0 auto;
padding: 16px;
}
</style>

View File

@ -0,0 +1,77 @@
<template>
<header>
<img src="@/assets/icons/mainproject.svg">
<p class="title">快捷跳转</p>
</header>
<main>
<div class="icon__item">
<div class="icon">
<img src="@/assets/icons/order.svg">
</div>
<p>系统菜单</p>
</div>
</main>
</template>
<script setup lang='ts'>
</script>
<style scoped lang='scss'>
header {
height: 40px;
display: flex;
align-items: center;
padding: 0 16px;
border-bottom: 1px solid $dashLineColor;
gap: 4px;
img {
width: 16px;
height: 16px;
}
.title {
color: $titleTextColor;
font-weight: bold;
}
}
main {
min-height: 40px;
padding: 16px;
display: flex;
gap: 12px;
.icon__item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap:4px;
cursor: pointer;
&:hover{
p{
color:$primaryColor;
}
}
.icon {
display: flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
background:$primaryColor;
border-radius: 4px;
img{
height: 25px;
width: 25px;
}
}
> p{
font-size: 12px;
font-weight: 400;
color:#666;
}
}
}
</style>

View File

@ -1,12 +1,102 @@
<template>
<div class="main__container">我老家</div>
<div class="main__container home">
<div class="main-dashboard">
<div class="main-dashboard__header">
<MainDashBoardHeader />
</div>
<div class="main-dashboard__liner">
<MainDashBoardLiner />
</div>
<div class="main-dashboard__proxy">
<MainDashBoradProxy />
</div>
</div>
<div class="sub-dashboard">
<div class="sub-dashboard__quick">
<SubDashBoardQuick />
</div>
<div class="sub-dashboard__money">
<SubDashBoardMoney/>
</div>
<div class="sub-dashboard__history">
<SubDashBoardHistory />
</div>
</div>
</div>
</template>
<script setup lang='ts'>
<script setup lang="ts">
import MainDashBoardHeader from './compoents/MainDashBoardHeader.vue';
import MainDashBoardLiner from './compoents/MainDashBoardLiner.vue';
import MainDashBoradProxy from './compoents/MainDashBoradProxy.vue';
import SubDashBoardQuick from './compoents/SubDashBoardQuick.vue';
import SubDashBoardMoney from './compoents/SubDashBoardMoney.vue';
import SubDashBoardHistory from './compoents/SubDashBoardHistory.vue';
</script>
<style scoped lang='scss'>
.main__container{
background:url('../../assets/images/home_bg.webp');
background-size: cover;
<style lang="scss" scoped>
$boardGap: 16px;
.main__container.home {
display: grid;
grid-template-columns: 70% 30%;
gap: $boardGap;
.main-dashboard {
width: 100%;
display: flex;
flex-direction: column;
gap: $boardGap;
&__header {
display: grid;
grid-template-columns: repeat(5, 1fr);
align-items: center;
gap: $boardGap;
}
&__liner {
width: 100%;
background: #fff;
border-radius: 4px;
overflow: hidden;
}
&__proxy {
padding: 12px;
min-height: 400px;
background: #fff;
border-radius: 4px;
overflow: hidden;
}
}
.sub-dashboard {
width: 100%;
display: flex;
flex-direction: column;
gap: $boardGap;
&__quick {
width: 100%;
background: #fff;
border-radius: 4px;
overflow: hidden;
}
&__money {
width: 100%;
background: #fff;
border-radius: 4px;
overflow: hidden;
}
&__history {
width: 100%;
background: #fff;
border-radius: 4px;
overflow: hidden;
}
}
}
</style>