灌糖包子 96b032d262
refactor: 全面迁移 vue-class-component 至 Vue 3 Composition API
- 将所有页面组件从 class 语法重写为 <script setup> 风格
  - App.vue / Login.vue / Home.vue / Welcome.vue
  - api: Hitokoto.vue / HitokotoAdd.vue / Music.vue / PhotoWall.vue / SourceImage.vue
  - system: Article.vue / Statistics.vue / SystemConfig.vue / SystemConfigAdd.vue / SystemRole.vue / SystemUser.vue

- 新增 src/utils/http.ts:独立 axios 实例,含请求/响应拦截器,替代 vue-axios 插件
- baselist.ts:abstract class BaseList<T> → useBaseList<T>() 组合式函数
- types.ts:VForm 类型改用 Element Plus 原生 FormInstance
- main.ts:移除 vue-axios 及内联 axios 配置,路由守卫直接引用 store

- 依赖清理:移除 vue-class-component、vue-axios
2026-03-19 23:05:59 +08:00

126 lines
4.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-container class="layout">
<el-header class="layout-header">
<div class="main-title">博客管理后台</div>
<div class="nav-btns-right">
<el-dropdown @command="dropdownMenuCommand">
<el-button link type="primary">
<UserFilled style="width: 18px" />
{{ realname }}
<ArrowDown style="width: 18px"/>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="home">返回首页</el-dropdown-item>
<el-dropdown-item command="changePassword">修改密码</el-dropdown-item>
<el-dropdown-item command="logout" divided>退出</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</el-header>
<el-container>
<el-aside width="200px">
<el-menu :default-active="defaultActiveMenuKey" :default-openeds="openMenuNames" style="height: 100%;">
<el-sub-menu v-for="menu in menus" :key="menu.name" :index="menu.name">
<template #title>
<component :is="menu.icon" style="width: 18px; margin-right: 5px;"></component>
<span>{{menu.title}}</span>
</template>
<el-menu-item v-for="(subItem,subIndex) in menu.child" :key="subIndex" :index="subItem.path" @click="openMenu(subItem.path)">
{{subItem.title}}
</el-menu-item>
</el-sub-menu>
</el-menu>
</el-aside>
<el-main class="layout-main">
<div class="layout-tabs">
<el-tabs type="card" class="nav-tabs" v-model="store.state.activeTab" @tab-change="openMenu" @tab-remove="removeTab">
<el-tab-pane label="首页" name="/"></el-tab-pane>
<el-tab-pane v-for="tab in store.state.tabs" :key="tab.name" :label="tab.title" :name="tab.path" closable></el-tab-pane>
</el-tabs>
</div>
<div class="layout-content">
<router-view class="main-view" v-slot="{ Component }">
<keep-alive :include="keepViews">
<component :is="Component" />
</keep-alive>
</router-view>
</div>
<div class="layout-copy">2016-{{currentYear}} &copy; colorfulsweet 上次更新{{ version }}</div>
</el-main>
</el-container>
</el-container>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useStore } from 'vuex'
import { useRouter, useRoute } from 'vue-router'
import menus from '../config/menu'
import http from '@/utils/http'
const store = useStore()
const router = useRouter()
const route = useRoute()
const version = process.env.VERSION
const currentYear = new Date().getFullYear()
const defaultActiveMenuKey = ref<string | null>(null)
const openMenuNames = ref<string[]>([])
const realname = computed((): null | string => {
return store.state.loginInfo.userInfo
? store.state.loginInfo.userInfo.realname : null
})
const keepViews = computed((): string[] => {
return store.state.tabs
.filter((item: any) => item.name)
.map((item: any) => item.name)
})
// created
defaultActiveMenuKey.value = route.path
if (defaultActiveMenuKey.value) {
let result = /^\/(.*)\//.exec(defaultActiveMenuKey.value)
if (result) {
openMenuNames.value.push(result[1])
}
}
if (!store.state.loginInfo.token) {
router.push('/login')
} else {
http.post<{token: string}, any>('/api/v1/common/verifyToken', {token: store.state.loginInfo.token}).then(data => {
if (data.status) {
store.commit('login', {token: data.newToken || store.state.loginInfo.token, userInfo: data.userInfo})
} else {
router.push('/login')
}
})
}
function dropdownMenuCommand(command: string): void {
switch (command) {
case 'home':
router.push('/')
break
case 'changePassword':
// TODO
break
case 'logout':
store.commit('logout')
router.push('/login')
break
}
}
function openMenu(path: string): void {
router.push(path)
}
function removeTab(path: string): void {
store.commit('removeTab', path)
if (store.state.activeTab === path) {
const { tabs } = store.state
openMenu(tabs[tabs.length - 1]?.path || '/')
}
}
</script>