feat: Phase 3 - API layer + Pinia stores + app integration

- HTTP client (axios interceptors, token mgmt, typed APIs)
- Pinia stores: token, user (login/logout), app (dark mode, sidebar)
- globalConfig TS types + Window augmentation
- Vue Router (hash history, auth guard)
- Login/Home/Mine pages (Vant UI)
- Vant integration + globalConfig dev script
- Build passes (vue-tsc + vite)
This commit is contained in:
2026-06-15 20:56:05 +08:00
parent 74cc0df2b8
commit 9b68a2d275
19 changed files with 2080 additions and 8 deletions

125
src/views/home/index.vue Normal file
View File

@@ -0,0 +1,125 @@
<script setup lang="ts">
/**
* 首页 (placeholder)
*
* 使用 Vant Tabbar 实现底部导航切换,
* 当前仅展示占位内容,后续集成地图、管网等功能模块。
*/
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
/** 当前激活的 Tab */
const active = ref(0)
/**
* Tab 切换处理
*/
function onTabChange(index: number): void {
active.value = index
if (index === 0) {
router.replace('/home')
} else if (index === 1) {
router.replace('/mine')
}
}
</script>
<template>
<div class="home-page">
<!-- 顶部导航栏 -->
<van-nav-bar title="舆图智慧水务" fixed placeholder />
<!-- 页面主体区域 -->
<div class="home-content">
<div class="welcome-card">
<h2>欢迎使用智慧水务</h2>
<p>移动端管理平台</p>
</div>
<div class="feature-grid">
<div class="feature-item" v-for="i in 4" :key="i">
<div class="feature-icon"></div>
<span class="feature-label">功能模块 {{ i }}</span>
</div>
</div>
</div>
<!-- 底部导航栏 -->
<van-tabbar v-model="active" :fixed="true" :placeholder="true" @change="onTabChange">
<van-tabbar-item icon="home-o" name="首页">首页</van-tabbar-item>
<van-tabbar-item icon="user-o" name="我的">我的</van-tabbar-item>
</van-tabbar>
</div>
</template>
<style lang="scss" scoped>
.home-page {
min-height: 100vh;
background: var(--color-bg-page);
:deep(.van-nav-bar) {
background: var(--color-primary);
--van-nav-bar-title-text-color: #fff;
}
}
.home-content {
padding: 16px;
}
.welcome-card {
background: var(--color-bg-card);
border-radius: 12px;
padding: 32px 24px;
text-align: center;
box-shadow: var(--shadow-sm);
margin-bottom: 16px;
h2 {
font-size: 20px;
color: var(--color-text-primary);
margin-bottom: 8px;
}
p {
font-size: 14px;
color: var(--color-text-secondary);
margin: 0;
}
}
.feature-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.feature-item {
background: var(--color-bg-card);
border-radius: 12px;
padding: 24px 16px;
text-align: center;
box-shadow: var(--shadow-sm);
cursor: pointer;
transition: background-color var(--transition-fast);
&:active {
background: var(--color-border-light);
}
.feature-icon {
width: 48px;
height: 48px;
border-radius: 12px;
background: var(--color-primary-bg);
margin: 0 auto 8px;
}
.feature-label {
font-size: 14px;
color: var(--color-text-regular);
}
}
</style>